How do I create friends? - ruby-on-rails

I can't seem to get Amistad friendships to work correctly. I am getting the following error:
ActiveRecord::RecordNotFound in FriendshipsController#update
Couldn't find Friendship with id=29
I am also using devise and cancan. I followed the gem setup on the wiki pages and created my controller as described in this related post.
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 create
#friend = User.find(params[:user_id])
#friendship_created = current_user.invite(#friend)
if #friendship_created
redirect_to users_path, :notice => "Your friend request is pending"
end
end
def update
#friend = User.find(params[:user_id])
#friends = current_user.friends
#pending_invited_by = current_user.pending_invited_by
redirect_to users_path, :notice => "You are now friends!"
end
def destroy
#friend = User.find(params[:user_id])
#friendship = current_user.send(:find_any_friendship_with, #friend)
if #friendship
#friendship.delete
#removed = true
redirect_to users_path, :notice => "You are no longer friends!"
end
end
def createblock
#friend = User.find(params[:user_id])
current_user.block #friend
redirect_to users_path, :notice => "You have blocked #{#friend.first_name}"
end
end
I loop though my users in the following manner checking the current status of the user and offering appropriate actions.
<% if current_user.friend_with? user %>
<%= link_to "Unfriend", friend_path(user), :method => "delete", :class => 'btn btn-mini' %>
<% elsif current_user.invited? user %>
<span class="btn btn-mini disabled">Pending</span>
<% elsif user.invited? current_user %>
<%= link_to "Accept", friend_path(user), :method => "put", :class => 'request-approve btn btn-mini' %>
<%= link_to "Decline", friend_path(user), :method => "delete", :class => 'request-decline btn btn-mini' %>
<% else %>
<%= link_to "Add friend", friends_path(:user_id => user), :method => "post", :class => 'btn btn-mini' %>
<% end %>
Figured it would be useful to see what the friendships table looks like in my schema:
create_table "friendships", :force => true do |t|
t.integer "friendable_id"
t.integer "friend_id"
t.integer "blocker_id"
t.boolean "pending", :default => true
end
add_index "friendships", ["friendable_id", "friend_id"], :name => "index_friendships_on_friendable_id_and_friend_id", :unique => true
I understand the error just cannot figure out how this should change. I think my issue is that I am passing in a friend id and it is expecting a friendship id. My only problem with this solution is that every example or post I can find suggests passing user_id, like this post above where the answerer states the gem developer supplied the code he answers with.
What I feel like I need in my update method is to replace:
#friend = User.find(params[:id])
With this:
#friendship = Friendship.find_by_friend_id(params[:id])
EDIT
I can successfully request a friend, I just cannot accept or decline a friend. I a listing of users, clicking the "Add Friend" link creates the record in the friendships db correctly. If I log ins as that recently requested user and attempt to accept the request is when I get the above error. This also occurs if I attempt to decline the request.
The friends method you asked to see come with the amistad gem, here is the code for that method. As for my Ruby logs the section that displays the error was very long, so I have included it in this gist.

Given my current reputation, I can only post an answer instead of a comment to your question but as far as I can see from the controller sources you posted, you are not calling current_user.approve #friend in your update action.
I used this gem in one of my projects recently without running into any problems. The controller actions look like this:
def update
#friend = User.find_by_id(params[:id])
if current_user.approve #friend
redirect_to friendships_path, notice: t('.confirmation_successful')
else
redirect_to friendships_path, alert: t('.confirmation_unsuccessful')
end
end
def destroy
#friend = User.find_by_id(params[:id])
if current_user.remove_friendship #friend
redirect_to friendships_path, notice: t('.deletion_successful')
else
redirect_to friendships_path, alert: t('.deletion_unsuccessful')
end
end
I hope this helps.

The lookup problem is because you're passing ids inconsistently. In 3 of the links, you're passing the User object directly, which should automatically store the id in params[:id], which you can use in your action as User.find(params[:id]). But in your actions, you're extracting it from params[:user_id], which is empty. Not sure how you're getting an ID of 29 in your error message (or 32 or whatever), but...
If you change all your actions to expect params[:id] and switch the "Add friend" path link to pass in a User object the way the others already are, you should be passing the right data in the right parameter, and the lookup should straighten itself out.
Of course, as Wonky Business points out, you're not actually calling approve in your update method, so nothing will actually link, but at least you should be finding all your model objects.
As an aside, it appears from your paths you're remapping the friendship named routes to friend instead. That's muddling the issue because none of the RESTful routes are actually doing what their noun/verb combination implies: if you call friends_path(user) with a POST, there should be a new Friend object when you're done, but this controller is creating and destroying Friendship objects and leaving the Friend objects alone.
If you delete that alias and switch to friendship_path and so forth, then REST will actually be doing what it says it is: managing friendship objects.
Hope that helps!

Related

Destroying Friendship in Ruby on Rails

I'm currently having issues with destroying a friendship in ruby on rails. The friendships are being created normally (I tested this using rails console), but deleting the friendship is not working.
Below is my controller code:
class FriendshipsController < ApplicationController
def create
#current_friend = User.find(params[:friend_id])
#friendship = current_user.friendships.build(:friend_id => #current_friend.id)
#friendship_2 = #current_friend.friendships.build(:friend_id => current_user.id)
if #friendship.save && #friendship_2.save
flash[:notice] = "Friend added"
redirect_to current_user
else
flash[:notice] = "Can not add friend"
redirect_to current_user
end
end
def destroy
#friendship = current_user.friendships.find_by(friend_id: params[:id]).first
if #friendship.exists?
#friendship.destroy
end
#friendship_2 = Friendship.where(user_id: params[:id], friend_id: current_user.id).first
if #friendship_2.exists?
#friendship_2.destroy
end
flash[:notice] = "Friendship destroyed"
redirect_to current_user
end
end
Below is my form for deleting the friendship:
<%= form_for(current_user.friendships.find_by(friend_id: #user.id),
html: { method: :delete }) do |f| %>
<%= f.submit "Unfriend", class: "btn" %>
<% end %>
Note that I added the check for the friendship existing since I just kept getting an error stating that the friendship was nil, which is my current problem.
Thanks!!!
In your view you're looking up the friendship with the friend_id (which you're supplying #user.id to), and that Friendship is what you're sending to form_for, so your form will have the :id of the Friendship.
But then in your destroy action you use params[:id] (the friendship id) in your query as the friend_id (which you've previously demonstrated should be a User id not a Friendship id.
Your code should actually be:
#friendship = current_user.friendships.find_by(id: params[:id])
(and you shouldn't be calling .first on that at all because find_by already returns a single record)

Adding users to group in Rails

I have a group and user model joined by a membership.
When I call the code
groups/show.html.erb
<%= link_to "Add to group", group_path(:group_id => #group.id, :user_id => user.id), :method => :put %>
It calls the update method in the groups_controller.rb
def update
#group = Group.find(params[:id])
#user = User.find(params[:user_id])
if !#group.users.find(#user)
#group.users << #user
end
end
But throws an error:
ActiveRecord::RecordNotFound in GroupsController#update
Couldn't find User with 'id'=1 [WHERE "memberships"."group_id" = ?]
I'm building my first rails app and don't know why this is happening. Thanks!
You have two mistakes:
You need to find #group by params[:group_id], because that is what you are sending.
#group.users.find(#user) will throw an error if #user is not already associated with #group, which is not what you want. You want to run #group.users << #user unless #group.users.include? #user to add a user if she isn't already in the group.
Your group path uses :group_id but the controller is looking for :id. Those should probably match.

user only able to vote on own uploads in thumbs_up

I installed the gem 'thumbs_up', '~> 0.6.7' ran the necessary migrations per instructions and now having some issues getting this to function properly. Thanks for bearing with me as I am new with RoR. I'm running rails 4.0.0. and building a simple app where users upload images (pins) and I want the images to be voted on by other users. Problem I am having is that a logged in user is only able to vote on their own images, and not others. Also, once the vote_up or vote_against is clicked on in the view it does nothing, however the vote is being tallied, but the page and the flash notice are both not being rendered.
This is my models/users.rb:
class User < ActiveRecord::Base
# some devise stuff here...
acts_as_voter
end
models/pins.rb:
class Pin < ActiveRecord::Base
acts_as_voteable
end
My pins_controller:
def vote_up
#pin = Pin.find(params[:id])
current_user.vote_for(#pin)
pin.update_vote_count
render root_path
flash[:success] = " You voted Up."
respond_to do |format|
format.js
end
end
def vote_down
#pin = Pin.find(params[:id])
current_user.vote_against(#pin)
#pin.update_vote_count
respond_to do |format|
format.js
redirect_to pins_url, notice: 'You voted Down'
end
end
This is my view:
<strong><%= pin.plusminus %></strong><br/>
<%= link_to "Up Vote", vote_up_pin_path(pin), :method => :post, :remote => true, :class=>'up-vote' %> |
<%= link_to "Down Vote", vote_down_pin_path(pin), :method => :post, :remote => true, :class=>'down-vote' %>
And here is my routes.rb:
resources :pins do
member do
post :vote_up
post :vote_down
post :unvote
end
end
Any help would be very much appreciated, thanks in advance!
Resolved my issue. Was a rookie mistake in that for any user to see the vote option I put the end tag after the option to vote in my view.

build method in create action of controller is creating to the wrong user

I'm trying to create a "review" for a specific "review request", but the way I have it set up now it creates a review for a random review request when I select the "Offer a Review" button.
Here's my reviews_controller:
class ReviewsController < ApplicationController
def create
#review = current_user.reviews.build(params[:review_request_id])
if #review.save
flash[:success] = "Review Created"
redirect_to review_path(#review)
else
flash[:error] = "Review Offer Sent"
redirect_to root_url
end
end
def show
#review_request = ReviewRequest.find(params[:id])
end
end
Here's a section of the partial with the link_to the create action:
<span class="offer_review">
<%= link_to "Offer A Review", reviews_path(:review_request_id), :method => :post %>
</span>
I have
belongs_to :review_request
in the models/review.rb file and
belongs_to :user
in the review_request.rb file.
This is the index action in the review requests controller. The partial with the link is in the index view. May be part of the problem?
def index
#review_requests = ReviewRequest.paginate(page: params[:page])
end
try to use 'puts' statement for 'params[:review_request_id]' and check what value you are getting. It seems that the problem is in the definition of the form field.
There were actually two issues here. I solved the first one (the review wasn't being created with the review_request_id) with:
#review_request = current_user.review_requests.build(params[:review_request])
in the review_requests_controller, and:
<%= link_to "Offer A Review", reviews_path(:review_request_id => review_request), :method => :post %>
in the view.
I had actually solved this issue without realizing it before posting this question (and reverted back to the code above) because the redirect to the Review#show controller was wrong as well, and would show information for the wrong review_request even if the review was created correctly. (It did this because it took reviews/1 to be the review_request_id, not the review_id)
This is the code I got that to work right:
#review = Review.find(params[:id])
#review_request = ReviewRequest.find(#review.review_request_id)

friendship Couldn't find User without an ID error

I am trying to use amistad as a friendship gem.. But i cant get it to work correctly. I use devise as authentication system , my problem when I add click add friend link :
<% unless current_user == #user %>
<%= link_to "Arkadaşlarıma Ekle", friends_path(:friend_id => #user), :method => :post,class: "btn btn-large btn-primary" %>
<%end %>
I get couldn't find User without an ID error. I cant find the correct links.
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 create
#Friend = User.find(params[:user_id])
#friendship_created = current_user.invite(#Friend)
if #friendship_created
flash.now[:notice] = "Une demande d'amiti a t envoye #{#friend.fullname}"
end
end
def approve
#Friend = User.find(params[:user_id])
#friendship_approved = current_user.approve(#Friend)
#friends = current_user.friends
#pending_invited_by = current_user.pending_invited_by
flash.now[:notice] = "La demande d'amiti de #{#friend.fullname} a t approuve"
end
def remove
#Friend = User.find(params[:user_id])
#friendship = current_user.send(:find_any_friendship_with, #Friend)
if #friendship
#friendship.delete
#removed = true
flash.now[:notice] = "Artık #{#friend.fullname} ile arkadaşsınız"
end
end
end
Thank you for your answers.
You can't send HTTP POST requests through normal links (without triggering AJAX requests). Replace the link with a form, either manually created through form_for and the like, or generated with button_to.
I fixed it. I had to use friends_path(:user_id => #user), instead of friends_path(:friend_id => #user),
I still need a good way to solve amistad views.

Resources