简体   繁体   中英

Ruby on Rails Routes Error

I am using Amistad to implement the friendship model. I have five actions in the friendships_controller : index , request_friend , approve_friend , remove_friend , block_friend .

I am not sure on how to define the routes in the routes file, I tried using resources :friendships but am unable to make a friend request from the user profile.

Here are the files:

routes.rb:

resources :friendships

friendships_controller.rb:

class FriendshipsController < ApplicationController
    before_filter :authenticate_user!

    def index
        @friends = current_user.friends
        @pending_invited_by = current_user.pending_invited_by
        @pending_invited = current_user.pending_invited
    end

    def request_friend
        @friend = User.find(params[:id])
        #if !@friend
        #    redirect_to :back
        #end
        current_user.invite @friend
        redirect_to :back
    end

    def approve_friend
        @friend = User.find(params[:id])
        current_user.approve @friend
        redirect_to :back
    end

    def remove_friend
        @friend = User.find(params[:id])
        current_user.remove_friendship @friend
        redirect_to :back
    end

    def block_friend
        @blocking = User.find(params[:id])
        current_user.block @blocking
        redirect_to :back
    end
end

I want User A to be able to send User B a friend request and User B to either accept it, delete it or ignore it.

Here is my show.html.erb

<span> 
  <% if @user == current_user %>
    <%= link_to 'Edit Profile', edit_profile_path(@user.user_name),class: 'btn edit-button' %>
  <% elsif current_user.friend_with? @user %>Already Friends!
    <%= button_to "Delete!",friendship_path(id: @user.id, friendship_action: 'remove_friendship'), method: :delete, class: "btn btn-primary" %>
  <% elsif current_user.invited? @user %>Friend request sent!
    <%= button_to "Unsend!", friendship_path(id: @user.id), :method => :delete, class: "btn btn-small btn-primary" %>
  <% elsif current_user.invited_by? @user %>
    <%= button_to "Accept!", friendship_path(@user.id, friendship_action: 'approve'), :method => :patch, class: "btn btn-small btn-primary" %>
    <%= button_to "Reject!", friendship_path(@user.id, friendship_action: 'remove_friendship'), :method => :delete, class: "btn btn-small btn-primary" %>
  <% else %>
    <%= form_tag friendship_path(@user.id,friendship_action: 'invite') do %>
      <%= submit_tag "Request Friend", class: "btn btn-primary" %>
    <% end %>
  <% end %>
</span>

This is the process going on in console when i manually do the friendships-ie user1.invite user2-it is working and changes are being made in the friendhips table-i used sqlitebrowser to verify

Here is what is going on when i press the link_to in my show.html.erb.Ive only included parts of the console related to the friendship model

I dont know why the values are not being inserted when i press the button.But when i do it manually via the console they are being inserted.

If I understood correctly this is how your routes.rb should look like

You can pass a block to the resources method to define nested resources.

resources :friendships do
  member do
    post 'approve_friendship', to: 'friendships#approve_friendship'
    post 'request_friendship', to: 'friendships#request_friendship'
    delete 'remove_friendship', to: 'friendships#remove_friendship'
    post 'block_friendship', to: 'friendships#block_friendship'
  end
end

This will define the endpoints as POST /friendships/:id/approve_friendship

You should check rails doc for more info: http://guides.rubyonrails.org/routing.html#adding-more-restful-actions

Why not just use the standard verbs?

class FriendshipsController < ApplicationController

  before_filter :authenticate_user!

  def index
    @friends = current_user.friends
    @pending_invited_by = current_user.pending_invited_by
    @pending_invited = current_user.pending_invited
  end

  def new
    @friend = User.find(params[:id])
    current_user.invite @friend
    redirect_to :back
  end

  def create
    @friend = User.find(params[:id])
    current_user.approve @friend
    redirect_to :back
  end

  def update
    @friend = User.find(params[:id])
    current_user.send blocking_method, @friend
    redirect_to :back
  end

  def destroy
    @friend = User.find(params[:id])
    current_user.remove_friendship @friend
    redirect_to :back
  end

private

  def blocking_method
    current_user.blocking?(@friend) ? :unblock : :block
  end

end

Then you can just do:

resources :friendships

Like you started with and not have to monkey around with your routes.

Also, in the update method (aka, 'blocking'), I added a toggle so that you can allow a user to block and unblock a friend.

Now, when you look at your methods, they are all essentially identical except for the call being made on current_user . So why not slim things down?

class FriendshipsController < ApplicationController
  ALLOWED_FRIENDSHIP_ACTIONS = %w('invite' 'approve' 'remove_friendship' 'block', 'unblock')

  before_filter :authenticate_user!

  def index
    @friends = current_user.friends
    @pending_invited_by = current_user.pending_invited_by
    @pending_invited = current_user.pending_invited
  end

  def update
    @friend = User.find(params[:id])
    current_user.send(friendship_action, @friend) if friendship_action
    redirect_to :back
  end

private

  def friendship_action
    if fa = params[:friendship_action]
      return fa if ALLOWED_FRIENDSHIP_ACTIONS.include?(fa)
    end
  end

end

And then you could do:

resources :friendships, :only => [:index, :update]

And use it something like:

link_to friendship_path(id: @friend.id, friendship_action: 'invite'), method: :patch

You'll have to monkey with that @friend.id bit a little depending on where you are generating your link_to (or your form , depending on how you're doing it).

I don't know. To me, that seems like cleaner code. Fewer lines, less repetition, more closely following convention. But, whatever floats your skiff.

RESPONSE TO COMMENT

Try the changes below...

This:

    <%= button_to "Delete!",friendship_path(id: @user.id, friendship_action: 'remove_friendship'), method: :delete, class: "btn btn-primary" %>

Should be this:

    <%= button_to "Delete!", friendship_path(id: @user.id, friendship_action: 'remove_friendship'), method: :patch, class: "btn btn-primary" %>

Why? Because you don't have a delete method anymore, remember? Only index and patch .

Change this:

    <%= button_to "Unsend!", friendship_path(id: @user.id), :method => :delete, class: "btn btn-small btn-primary" %>

To this:

    <%= button_to "Unsend!", friendship_path(id: @user.id, friendship_action: 'unsend'), method: :patch, class: "btn btn-small btn-primary" %>

You need the friendship_action inside the helper. And, again, :delete becomes :patch .

This:

    <%= button_to "Accept!", friendship_path(@user.id, friendship_action: 'approve'), :method => :patch, class: "btn btn-small btn-primary" %>

I would change to:

    <%= button_to "Accept!", friendship_path(id: @user.id, friendship_action: 'approve'), method: :patch, class: "btn btn-small btn-primary" %>

Adding id: in front of @user.id may be the thing. Here, you got the :method , but I would reformat to method: :patch just to be consistent.

Here:

    <%= button_to "Reject!", friendship_path(@user.id, friendship_action: 'remove_friendship'), :method => :delete, class: "btn btn-small btn-primary" %>

Change to:

    <%= button_to "Reject!", friendship_path(id: @user.id, friendship_action: 'remove_friendship'), method: :patch, class: "btn btn-small btn-primary" %>

Adding id and :delete to :patch .

Finally, this:

    <%= form_tag friendship_path(@user.id,friendship_action: 'invite') do %>
      <%= submit_tag "Request Friend", class: "btn btn-primary" %>
    <% end %>

To this:

    <%= button_to "Request Friend", friendship_path(id: @user.id, friendship_action: 'invite'), method: :patch, class: "btn btn-primary" %>

You're using button_to everywhere else. Why not here, too?

Here it is, all together:

<span> 
  <% if @user == current_user %>
    <%= link_to 'Edit Profile', edit_profile_path(@user.user_name),class: 'btn edit-button' %>
  <% elsif current_user.friend_with? @user %>Already Friends!
    <%= button_to "Delete!", friendship_path(id: @user.id, friendship_action: 'remove_friendship'), method: :patch, class: "btn btn-primary" %>
  <% elsif current_user.invited? @user %>Friend request sent!
    <%= button_to "Unsend!", friendship_path(id: @user.id, friendship_action: 'unsend'), method: :patch, class: "btn btn-small btn-primary" %>
  <% elsif current_user.invited_by? @user %>
    <%= button_to "Accept!", friendship_path(id: @user.id, friendship_action: 'approve'), method: :patch, class: "btn btn-small btn-primary" %>
    <%= button_to "Reject!", friendship_path(id: @user.id, friendship_action: 'remove_friendship'), method: :patch, class: "btn btn-small btn-primary" %>
  <% else %>
    <%= button_to "Request Friend", friendship_path(id: @user.id, friendship_action: 'invite'), method: :patch, class: "btn btn-primary" %>
</span>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM