Reputation: 61
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>
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.
Upvotes: 1
Views: 116
Reputation: 20253
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>
Upvotes: 0
Reputation: 619
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
Upvotes: 0