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.
Related
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)
I'm new to rails and have stuck with a simple thing.
I have a method to add new members to the team:
def add_member
#team = Team.find(params[:id])
#team.members << User.find(params[:user_id])
redirect_to #team
end
Every team has its author. I want the author to add a registered user to his team like this:
My add button:
= link_to 'Add member', add_member_team_path(#team, user_id: user.id)
So if user with the email exists, he should be added to #team.members.
How to pass user.id from email_field_tag to my link button?
Sorry, if the question is silly. Many thanks in advance!
UPDATE
Now the code look this way:
Controller:
def add_member_by_email
#team = Team.find(params[:id])
#user = User.find_by_email(params[:email])
if #user.nil?
render text: "No user found with that email" and return
else
#team.members << #user
redirect_to #team
end
end
In my view:
= email_field_tag :user_email
= link_to 'Add to team', add_member_by_email_team_path(#team, email: :user_email)
In routes.rb:
resources :teams do
member do
get :add_member_by_email
end
end
But keeps saying, there is no such user.
In your view, use a form helper, which will render an html form tag:
= form_for User.new, url: add_member_path(#team) do |f|
= f.text_field :email
= f.submit "Add new member"
In the controller, you can access the user email like this:
params[:user][:email]
Note: please excuse any typos or syntax errors in my post for now as I am writing this from the mobile app.
You should pass the email address from your email_field_tag, and in your add_member action:
def add_member
#team = Team.find(params[:id])
user = User.find_by_email(params[:email])
if !user.nil?
#team.members << user
#team.save
redirect_to #team
else
# Cannot find the user with the email address, do something here based on your design
end
end
You probably want to create a new path for this (and not just scab it on to the existing add_member path), something like:
def add_member_by_email
#team = Team.find(params[:id])
#user = User.find_by_email(params[:user_email])
if #user.nil?
render :text => "No user found with that email" and return
end
#team.members << #user
redirect_to #team
end
And update your form:
= link_to 'Add member', add_member_by_email_team_path(#team)
Making sure that the email text field gives a user_email parameter.
This is a followup to this thread: Ruby on Rails: found unpermitted parameters: _method, authenticity_token
I have the following line: <%= button_to 'Message me', conversations_path(sender_id: current_user.id, recipient_id: #user.id), class: 'btn btn-primary m-t' %>
But when I click on the button, I get the error: param is missing or the value is empty: conversation.
I can see that conversation is not in the params hash: {"authenticity_token"=>"r5pwStXl6NwEgqqq0GT0RQxCqsGHrTVsh4Q7HviX+re5k+XOs2ioRv9kZqvDGz9Ch/6O6D1nOMjscquHQJlB+g==", "recipient_id"=>"1", "sender_id"=>"2", "controller"=>"conversations", "action"=>"create"}
As suggested in the other thread, it was helpful to add require(:conversation) to the controller:
class ConversationsController < ApplicationController
before_action :authenticate_user!
# GET /conversations
# GET /conversations.json
def index
#users = User.all
# Restrict to conversations with at least one message and sort by last updated
#conversations = Conversation.joins(:messages).uniq.order('updated_at DESC')
end
# POST /conversations
# POST /conversations.json
def create
if Conversation.between(params[:sender_id], params[:recipient_id]).present?
#conversation = Conversation.between(params[:sender_id], params[:recipient_id]).first
else
#conversation = Conversation.create!(conversation_params)
end
redirect_to conversation_messages_path(#conversation)
end
private
# Use callbacks to share common setup or constraints between actions.
def conversation_params
params.require(:conversation).permit(:sender_id, :recipient_id)
end
end
This worked for a while, but it has for some reason stopped working. How should I fix this? And why did it stop working?
Adding 'conversation' manually to the hash seems to work: <%= button_to 'Message me', conversations_path(conversation: { sender_id: current_user.id, recipient_id: #user.id }), class: 'btn btn-primary m-t' %>.
I also had to fix the controller to take into account the nesting:
def create
if Conversation.between(params[:conversation][:sender_id], params[:conversation][:recipient_id]).present?
#conversation = Conversation.between(params[:conversation][:sender_id], params[:conversation][:recipient_id]).first
else
#conversation = Conversation.create!(conversation_params)
end
redirect_to conversation_messages_path(#conversation)
end
Probably a very simple problem I'm overlooking. I'm building a feature similar to Facebook's "home" page for logged in users. A user can post topics in one form, and that form works perfectly.
There is a comment form under each posted topic. When a user enters a comment and clicks the submit button the comment is created, but it is not shown unless I manually refresh the page. I can't see what I'm doing wrong here.
_form.html.haml
= form_for [topic, Comment.new], remote: true do |f|
.form-group
= f.text_area :body, rows: 2, class: 'form-control', placeholder: "Make a comment"
= f.submit "Post", class: 'f-button primary f-fw-bold post-btn'
I have tried using #topic for this form as well but get the error: undefined method `comments_path'
comments_controller.rb
class CommentsController < ApplicationController
def create
puts "TOPICS PARAMS",params[:topic_id]
#topic = Topic.find(params[:topic_id])
#comments = #topic.comments
#comment = current_user.comments.build( comment_params )
#comment.topic = #topic
#new_comment = Comment.new
if #comment.save
flash[:notice] = "Comment was created."
redirect_to topics_path
else
flash[:error] = "There was an error saving the comment. Please try again."
redirect_to topics_path
end
end
private
def comment_params
params.require(:comment).permit(:body, :topic_id)
end
end
All of this is rendered in the topics#index path, so here is the topics controller as well.
topics_controller.rb
class TopicsController < ApplicationController
def index
#topics = Topic.order(created_at: :desc)
#comments = Comment.all
#limited_partners = LimitedPartner.all
#users = User.all
#comment = Comment.new
end
def show
#topic = Topic.find(params[:id])
end
def create
#topic = Topic.new(topic_params)
#topic.user_id = current_user.id if current_user
#topic.limited_partner_id = current_user.limited_partner_id if current_user
if #topic.save
flash[:notice] = "Topic was saved successfully."
redirect_to topics_path
else
flash[:error] = "Error creating topic. Please try again."
render :new
end
end
def new
end
def edit
end
def update
end
private
def topic_params
params.require(:topic).permit(:body, :liked, :limited_partner_id, :user_id, :comment_id)
end
end
In the index.html.haml file I call the partial like this:
= render partial: 'comments/form', locals: { topic: topic, comment: #comment}
You are using remote: true for your form. So the submit will trigger an Ajax request. A javascript response will be returned, but no HTML will be updated by default.
You will need to sprinkle some javascript to update the HTML yourself: bind a callback to the ajax:success event, or use a js view (e.g. app/views/comments/create.js.erb).
Have also a look at Turbolinks 3 (still in development), which can reduce the amount of custom javascript required for partial page updates.
Your problem likely lies here ...
= form_for [topic, Comment.new], remote: true do |f|
Try this instead
= form_for #new_comment, url: {controller: 'comments', action: 'create'}, method: "post", remote: true do
and be sure your config/routes.rb looks something like this
get "/some-path", to: "comments#create"
post "/some-path", to: "comments#create"
I had to use javascript to get better control over the form and data. So I made a topic.coffee file with this:
$ ->
$('.new_comment').on 'submit', (event) =>
form = $(event.target).closest('form')
topicCommentsId = form.attr('action').replace(/\//g, '_').substring(1)
owningCommentsSection = $('#' + topicCommentsId)
formData = form.serialize()
$.post form.attr('action'), formData, (data) =>
extractedBody = $(data.substring(data.indexOf('<body')))
topicComments = extractedBody.find('#' + topicCommentsId)
owningCommentsSection.html(topicComments.html())
form.find('[name="comment[body]"]').val('')
location.reload();
return false
I removed the remote: true from my form as well and identify each topic in my index.html.haml with this:
.f-grid-row.topic_comments{id: "topics_#{topic.id}_comments"}
- topic.comments.each do |comment|
- if comment.topic_id == topic.id || comment.post_id == topic.id
...
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!