2013-07-27 38 views
0

我似乎无法让Amistad友谊正常工作。我收到以下错误:如何创建好友?

ActiveRecord::RecordNotFound in FriendshipsController#update 
Couldn't find Friendship with id=29 

我也使用devise和cancan。我遵循维基页面上的创业板设置,并按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 

我通过以下方式循环检查用户的当前状态并提供适当的操作。

<% 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 %> 

想通了,看看有什么友谊表看起来像在我的架构将是有益的:

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 

我理解的错误只是想不通这应如何改变。我认为我的问题是,我传递了一个朋友ID,它期待着一个友谊ID。这个解决方案唯一的问题是,我可以找到的每个示例或帖子都建议传递user_id,就像上面这个帖子中回答者声明gem开发者提供了他所回答的代码一样。

我想吃什么,我需要在我的更新方法就是更换:

@friend = User.find(params[:id]) 

有了这个:

@friendship = Friendship.find_by_friend_id(params[:id]) 

编辑 我能成功申请的朋友,我还是无法接受或拒绝朋友。我列出了一个用户列表,点击“添加朋友”链接可以正确创建友谊数据库中的记录。如果我以最近请求的用户身份登录,并尝试接受请求,那么我会收到上述错误。如果我试图拒绝请求,也会发生这种情况。

您要求看到的amistad宝石的朋友方法,这里是the code for that method。至于我的Ruby日志,显示错误的部分非常长,所以我将它包含在this gist中。

+0

你可以显示'current_user.friends'的代码,它在那里失败吧?我的意思是,在日志中,ruby抱怨哪一行? – juanpastas

+0

@juanpastas我已更新以证明您的问题的答案 – Thomas

+0

您的'development.log'说'ActiveRecord :: RecordNotFound(无法找到id = 32的友谊)'在您问题'update'正在执行'User.find'你能解释一下吗? – juanpastas

回答

1

查找问题是因为您传递的ID不一致。在其中3个链接中,您直接传递User对象,该对象应该自动将该标识存储在params[:id]中,您可以在该行为中使用该标识作为User.find(params[:id])。但在你的行动中,你从params[:user_id]中提取它,这是空的。不知道如何在错误消息(或32或其他)中获得29的ID,但是...

如果你改变自己的行为,以期望params[:id]和切换“加为好友”路径链接在User对象把别人已经成这个样子,你应该通过正确的数据在正确的参数,并且查找应该理顺自己。

当然,正如Wonky Business指出的那样,您实际上并没有在您的更新方法中调用approve,所以没有任何东西可以实际链接,但至少您应该找到所有模型对象。

顺便说一句,从您的路径看来,您将friendship命名路线重新映射到friend。这是混淆的问题,因为没有一个RESTful路线实际上在做他们的名词/动词组合暗示的内容:如果您用POST调用friends_path(user),当完成时应该有一个新的Friend对象,但是此控制器正在创建并销毁Friendship对象并仅保留Friend对象。

如果您删除该别名并切换到friendship_path等等,那么REST实际上会做它所说的:管理friendship对象。

希望有帮助!

2

鉴于我目前的名誉,我只能发布一个答案,而不是你的问题评论,但据我从您发布的控制器来源看,你是不是您的更新动作叫current_user.approve @friend

我最近在一个项目中使用了这个gem,但没有遇到任何问题。控制器的动作如下所示:

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 

我希望这会有所帮助。