1

我可以实现反向关系,所以如果 UserA 添加了 UserB,那么它会在 B 的配置文件中显示 UserA,反之亦然。但是,如果 UserA 添加了 UserB,我无法弄清楚如何让 UserB 将 UserA 作为朋友删除。我尝试了很多不同的方法,但是每次我更改某些内容时,都会将问题转移到其他地方!我不知道根本问题是否是:

  • 一种。FriendshipsControllerdestroy方法是如何定义的
  • 湾。我是否需要另一个控制器来专门处理 InverseFriendships 破坏
  • C。如果我需要自定义路线
  • d。如果以上所有内容都可以,但是我在视图中的代码(特别是 _suggested_connections 部分)正在调用错误的控制器和/或路由
  • e. 或以上都不是。

下面的代码片段:

class FriendshipsController < ApplicationController

      def destroy
        @friendship = current_user.friendships.find(params[:id])
        @friendship.destroy
        flash[:notice] = "Removed friendship."
        redirect_to current_user
      end

在视图中

        <% @user.inverse_friends.each do |inverse_friendship| %>
      <li>
        <%= inverse_friendship.name %>
        <%= link_to "remove", @user.inverse_friendships, :method => :delete, :class => "btn-small btn-danger" %><br />
        <%= image_tag inverse_friendship.avatar(:thumb) %>

我的模型:

class Friendship < ActiveRecord::Base
  belongs_to :user
  belongs_to :friend, class_name: 'User'
  attr_accessible :friend_id, :user_id
end 

 class User < ActiveRecord::Base

    has_many :friendships, dependent: :destroy
    has_many :friends, through: :friendships
    has_many :inverse_friendships, dependent: :destroy, class_name: "Friendship", foreign_key: "friend_id"
has_many :inverse_friends, through: :inverse_friendships, source: :user

和路线:

    resources :friendships

  authenticated :user do
    root :to => 'home#index'
  end
  root :to => "home#index"
  devise_for :users, :controllers => { :registrations => :registrations }
  resources :users
4

1 回答 1

1

您的主要问题是:

一种。FriendshipsControllerdestroy方法是如何定义的

您正在寻找friendship中的current_user.friendships,但它不存在。它在inverse_friendships

您需要检查这两个关联,或者让控制器知道您正在寻找哪一个。后者可能更可取,因为尽管它们是同一类,但它们不同的资源。可能是这样的:

# In routes, route inverse friendships to the same controller, but with a
# different path (I'm routing everything here, you may not need that.)
resources :friendships
resources :inverse_friendships, :controller => 'friendships'


# Then in your friendships controller, use the path to determine which 
# collection you're working with:
#
def destroy
  @friendship = collection.find(params[:id])
  # ...
end

# the other collection methods would use the same collection, if you needed them,
# for example:
def create
  @friendship = collection.build(params[:friendship])
  # ..
end

protected

# simple case statement here, but you get the idea
def collection
  case request.path
  when /\/inverse_friendships/ then current_user.inverse_friendships
  else current_user.friendships
  end
end

最后,在您看来,您会走向反向友谊,例如:

<%= link_to "remove", inverse_friendship_path(friendship), :method => :delete %>

正常的友谊可以使用较短的形式,或完整的命名路线:

<%= link_to "remove", friendship, :method => :delete %>
OR
<%= link_to "remove", friendship_path(friendship), :method => :delete %>

编辑:搜索两个关联。

当然,如果您想保持简单,并且inverse_friends作为单独的资源没有其他用途,您可以随时...

def destroy
  id, cid = params[:id], current_user.id

  # search both associations (two queries)
  @friendship = current_user.friendships.find_by_id(id) ||
                  current_user.inverse_friendships.find(id)

  # or query friendship looking for both types
  @friendship = Friendship.
                  where("user_id = ? OR friend_id = ?", cid, cid).find(id)

  # ...
end
于 2012-11-23T03:16:42.073 回答