Rails 中是否可以有多个互相传递的 has_many :through
关系?我收到了这样做的建议,作为我发布的另一个问题的解决方案,但一直无法让它发挥作用。
朋友是通过连接表循环关联。目标是为 friends_comments
创建一个 has_many :through
,这样我就可以使用 User
并执行类似 user.friends_comments< 的操作/code> 在单个查询中获取他的朋友发表的所有评论。
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 时在相关部分遇到的错误:
错误:列 users.user_id 不存在
: 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 类作为连接表。
我做错了什么,还是这根本不可能?
Is it possible to have multiple has_many :through
relationships that pass through each other in Rails? I received the suggestion to do so as a solution for another question I posted, but have been unable to get it to work.
Friends are a cyclic association through a join table. The goal is to create a has_many :through
for friends_comments
, so I can take a User
and do something like user.friends_comments
to get all comments made by his friends in a single query.
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
This looks great, and makes sense, but isn't working for me. This is the error I'm getting in relevant part when I try to access a user's 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)))
When I just enter user.friends, which works, this is the query it executes:
: SELECT "users".* FROM "users" INNER JOIN "friendships" ON "users".id = "friendships".friend_id WHERE (("friendships".user_id = 1) AND ((status = 2)))
So it seems like it's entirely forgetting about the original has_many
through friendship relationship, and then is inappropriately trying to use the User class as a join table.
Am I doing something wrong, or is this simply not possible?
发布评论
评论(4)
编辑:
Rails 3.1 支持嵌套关联。例如:
不需要下面给出的解决方案。请参阅此截屏视频了解更多详细信息。
原始答案
您正在传递一个
has_many :through
关联作为另一个has_many :through
的源协会。我认为这不会起作用。
您可以使用三种方法来解决此问题。
1) 编写关联扩展
现在您可以获取好友评论,如下所示:
2) 在
User
类中添加一个方法。现在您可以按如下方式获取好友评论:
3) 如果您希望这样做更加高效,那么:
现在您可以按如下方式获取好友评论:
所有方法都会缓存结果。如果您想重新加载结果,请执行以下操作:
或者更好:
Edit:
Rails 3.1 supports nested associations. E.g:
There is no need for the solution given below. Refer to this screencast for more details.
Original Answer
You are passing a
has_many :through
association as a source for anotherhas_many :through
association. I don't think it will work.
You have three approaches to solving this issue.
1) Write an association extension
Now you can get the friends comments as follows:
2) Add a method to the
User
class.Now you can get the friends comments as follows:
3) If you want this to be even more efficient then:
Now you can get the friends comments as follows:
All methods cache the results. If you want to reload the results do the following:
OR better still:
有一个插件可以解决您的问题,请查看 此博客。
你安装插件
There is a plugin that solves your problem, take a look at this blog.
You install the plugin with
虽然这在过去不起作用,但现在在 Rails 3.1 中工作得很好。
Although this didn't work in the past, it works fine in Rails 3.1 now.
我发现此博客条目很有用: http://geoff.evason.name/2010/04/23/nested-has_many-through-in-rails-or-how-to-do-a-3 -表连接/
I found this blog entry to be useful: http://geoff.evason.name/2010/04/23/nested-has_many-through-in-rails-or-how-to-do-a-3-table-join/