1

逆の関係を実装できるので、UserAがUserBを追加すると、BのプロファイルにUserAが表示され、その逆も同様です。しかし、UserAがUserBを追加した場合、UserBにUserAを友達として削除させる方法がわかりません。私はさまざまな方法を試しましたが、何かを変更するたびに問題が別の場所に移動します。基本的な問題が次のとおりかどうかはわかりません。

  • a。FriendshipsControllerdestroyメソッドの定義方法
  • b。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

あなたの主な問題は次のとおりです。

を。FriendshipsController destroy メソッドの定義方法

でを探していますがfriendshipcurrent_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 に答える