簡體   English   中英

Ruby-on-Rails:多個has_many:通過可能嗎?

[英]Ruby-on-Rails: Multiple has_many :through possible?

是否有可能有多個has_many :through在Rails中相互傳遞的關系? 我收到了這樣的建議,作為我發布的另一個問題的解決方案,但一直無法讓它工作。

好友是通過聯接表的循環關聯 目標是為friends_comments創建一個has_many :through ,這樣我就可以帶一個User並執行類似user.friends_comments ,以便在一個查詢中獲取他的朋友發表的所有評論。

class User
  has_many :friendships
  has_many :friends, 
           :through => :friendships,
           :conditions => "status = #{Friendship::FULL}"
  has_many :comments
  has_many :friends_comments, :through => :friends, :source => :comments
end

class Friendship < ActiveRecord::Base
  belongs_to :user
  belongs_to :friend, :class_name => "User", :foreign_key => "friend_id"
end

這看起來很棒,而且很有意義,但不適合我。 當我嘗試訪問用戶的friends_comments時,這是我在相關部分中遇到的錯誤:
ERROR: column users.user_id does not exist
: SELECT "comments".* FROM "comments" INNER JOIN "users" ON "comments".user_id = "users".id WHERE (("users".user_id = 1) AND ((status = 2)))

當我輸入有效的user.friends時,這是它執行的查詢:
: SELECT "users".* FROM "users" INNER JOIN "friendships" ON "users".id = "friendships".friend_id WHERE (("friendships".user_id = 1) AND ((status = 2)))

因此,它似乎完全忘記了原始的has_many通過友誼關系,然后不恰當地嘗試將User類用作連接表。

我做錯了什么,或者這根本不可能?

編輯:

Rails 3.1支持嵌套關聯。 例如:

has_many :tasks
has_many :assigments, :through => :tasks
has_many :users, :through => :assignments

不需要下面給出的解決方案。 有關詳細信息,請參閱截屏視頻。

原始答案

您正在傳遞has_many :through關聯作為另一個has_many :through來源的關聯。 我認為它不會起作用。

  has_many :friends, 
           :through => :friendships,
           :conditions => "status = #{Friendship::FULL}"
  has_many :friends_comments, :through => :friends, :source => :comments

您有三種方法可以解決此問題。

1)寫一個關聯擴展名

 has_many  :friends, 
           :through => :friendships,
           :conditions => "status = #{Friendship::FULL}" do
     def comments(reload=false)
       @comments = nil if reload 
       @comments ||=Comment.find_all_by_user_id(map(&:id))
     end
 end

現在您可以獲得以下朋友評論:

user.friends.comments

2)向User類添加方法。

  def friends_comments(reload=false)
    @friends_comments = nil if reload 
    @friends_comments ||=Comment.find_all_by_user_id(self.friend_ids)
  end

現在您可以獲得以下朋友評論:

user.friends_comments

3)如果您希望這更有效,那么:

  def friends_comments(reload=false)
    @friends_comments = nil if reload 
    @friends_comments ||=Comment.all( 
             :joins => "JOIN (SELECT friend_id AS user_id 
                              FROM   friendships 
                              WHERE  user_id = #{self.id}
                        ) AS friends ON comments.user_id = friends.user_id")
  end

現在您可以獲得以下朋友評論:

user.friends_comments

所有方法都緩存結果。 如果要重新加載結果,請執行以下操作:

user.friends_comments(true)
user.friends.comments(true)

或者更好的是:

user.friends_comments(:reload)
user.friends.comments(:reload)

有一個插件可以解決您的問題,看看這個博客

你安裝插件

script/plugin install git://github.com/ianwhite/nested_has_many_through.git

雖然這在過去不起作用,但它現在在Rails 3.1中運行良好。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM