当试图破坏/拒绝友谊关系时,未定义的方法'销毁'

时间:2012-03-30 05:44:48

标签: ruby-on-rails ruby-on-rails-3 relationship

我已经建立了一个自引用关系模型,让用户彼此成为朋友。我可以创建一个朋友请求(我的数据库中的两个条目,一个用于友谊,一个用于反向友谊),没有任何问题。

我在拒绝朋友请求时遇到了麻烦。当我按下让我进行破坏行动的拒绝时,我不断收到这个错误:

NoMethodError in FriendshipsController#destroy
undefined method `destroy' for nil:NilClass

即使我收到上述错误,其中一个数据库记录(正在等待友谊)也会被销毁,如果我注释掉@friendship2 = @user.friendships.find_by_friend_id(params[:id]).destroy,则其他记录也会被销毁。所以看起来这两行都是单独工作的,但是会返回上面的错误。

解决方案:看起来我的两个destroy语句引用了相同的记录。我在控制器中注释掉了错误的代码并添加了适合我的代码。

这是我的友谊控制器:

class FriendshipsController < ApplicationController
  before_filter :authenticate, :only => [:update, :create, :destroy]

def create
  @user = User.find(current_user)
  @friend = User.find(params[:friend_id])
  params[:friendship1] = {:user_id => @user.id, :friend_id => @friend.id, :status => 'requested'}
  params[:friendship2] = {:user_id => @friend.id, :friend_id => @user.id, :status => 'pending'}
  @friendship1 = Friendship.create(params[:friendship1])
  @friendship2 = Friendship.create(params[:friendship2])
  redirect_to @friend
 end  
end

  def destroy
    @user = User.find(params[:user_id])
    @friend = User.find(params[:id])
    #@friendship2 = @user.friendships.find_by_friend_id(params[:id]).destroy
    #@friendship1 = @friend.friendships.find_by_id(params[:user_id]).destroy  
    @friendship1 = @user.friendships.find_by_friend_id(@friend.id).destroy #removes the requested friendship
    @friendship2 = @friend.friendships.find_by_friend_id(@user.id).destroy #removes the pending friendship

    flash[:success] = "Removed."
    redirect_to @user   
  end 
end

这是我的用户模型:

class User < ActiveRecord::Base
  has_many :friendships, :dependent => :destroy

  has_many :friends, 
     :through => :friendships, 
     :conditions => "status = 'accepted'", 
     :source => :friend 

  has_many :pending_friends, 
     :through => :friendships, 
     :conditions => "status = 'pending'", 
     :foreign_key => "user_id", 
     :source => :friend

  has_many :requested_friends, 
     :through => :friendships,
     :source => :friend, 
     :conditions => "status = 'requested'"    
end

这是我的观点(users / show.html.erb):

<% if signed_in? && @user == current_user %>
  <% unless current_user.pending_friends.empty? %>
    <h2>Pending</h2>
    <% current_user.pending_friends.each do |pending| %>
       <%= pending.name %>
       <%= link_to '[Accept]', friendship_path(:user_id => current_user, :id => pending), :method => :put, :confirm => "Accept?" %>
       <%= link_to '[Decline]', friendship_path(:user_id => current_user, :id => pending), :method => :delete, :confirm => "Decline?" %>
    <% end %>
  <% end %>
<% end %>

我有两个问题。

  1. 我从一些有关the use of inverse_friendships的教程/讨论中看到过,但这是否真的有必要?到目前为止,我还没有看到对此的需要,但话说回来,我只是编写了我的创建和破坏动作。

  2. 未定义的方法'destroy'错误是什么?

  3. 感谢您浏览这一文字墙! :d

2 个答案:

答案 0 :(得分:1)

关于第一个问题,取决于您和您的系统。创建不同的变量以保持每种类型的友谊可能有点硬核,但它为您提供了完整的信息,更多的控制以及数据库中没有数据重复。

关于第二个,您应该检查您的查询是否返回结果。因为你的例外:

  

未定义的方法`destroy'为nil:NilClass

说NilClass中没有“破坏”方法(不是友谊)。只需检查:id参数以及find_by_friend_id是否返回任何内容。

答案 1 :(得分:1)

在销毁之前进行检查。

friendship = @friend.friendships.find_by_id(params[:user_id])
@friendship1 = friendship.destroy if !friendship.nil?

并且使用可以在callbacks的帮助下将其破坏到模型中。