如何创建“双面” Rails 中的多对多关系?
假设我们有一个摄影网站。任何作者都可以订阅以接收来自任何其他作者的更新。显然,如果作者 A 订阅了作者 B,并不意味着 B 订阅了 A。所以我们构建模型
class Author < ActiveRecord::Base
has_many :subscriptions
has_many :subscribed_by_author, :through => :subscriptions, :source => :subscribed_to
end
class Subscription < ActiveRecord::Base
belongs_to :author
belongs_to :subscribed_to, :class_name => "Author", :foreign_key => "subscribed_to"
end
这样我们就可以使用
- some_author.subscribed_by_author —— some_author 订阅的作者列表。
- 对于任何订阅,我们都可以知道两端(谁订阅了谁),
但问题是如何仅使用rails(不使用普通 SQL)获取订阅某个作者的人员列表,即得到以下问题的答案:“谁订阅了某个作者?”
问题:Rails 是否有能力让双方的关系发挥作用,即不仅编写 some_author.subscribed_BY_author
,而且还拥有 some_author_subscribed_TO_author
?如果有的话,那是什么?
PS 明显的解决方案是
- 更改数据库设计,添加名为“direction”的列
- 每次创建订阅时创建 2 条记录
添加到作者模型
has_many :subscribed_BY_author, :through =>; :订阅,:源=> :subscribed_to, :条件 => “方向=‘按’”
has_many :subscribed_TO_author, :through =>; :订阅,:源=> :subscribed_to, :条件 => "direction = 'to'"
但我想知道是否有一个不改变数据库设计的解决方案。
Suppose we have a photography site. Any author can subscribe to receive updates from any other author. Obviously if author A is subscribed to author B that doesn't mean that B is subscribed to A. So we build models
class Author < ActiveRecord::Base
has_many :subscriptions
has_many :subscribed_by_author, :through => :subscriptions, :source => :subscribed_to
end
class Subscription < ActiveRecord::Base
belongs_to :author
belongs_to :subscribed_to, :class_name => "Author", :foreign_key => "subscribed_to"
end
This way we can use
- some_author.subscribed_by_author -- the list of the authors to whom some_author is subscribed.
- For any subscription we can know both ends (who is subscribed to whom)
But the question is how to get the list of people subscribed to some author using only rails (not using plain SQL) i.e get the answer to :"Who is subscribed to some_author?"
Question: is there any ability in Rails to get the relationship working both sides i.e. not only writing some_author.subscribed_BY_author
but having some_author_subscribed_TO_author
? If there is one, then what is it?
P.S. Obvious solution is to
- Change the database design, adding a column named "direction"
- Create 2 records each time a subscription is created
Add to the author model
has_many :subscribed_BY_author, :through => :subscriptions, :source => :subscribed_to, :conditions => "direction = 'by'"
has_many :subscribed_TO_author, :through => :subscriptions, :source => :subscribed_to, :conditions => "direction = 'to'"
But i wonder if there is a solution without changing the database design.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我会使用普通的 HABTM 来做这样简单的事情,但无论如何你都需要一个连接表。
向作者指出:
如果您确实致力于方法名称:
创建一些连接(我会将 SubscriptionsController 设为 RESTy)
显示名称或其他
I'd use plain HABTM for something simple like this, but you're going to need a join table no matter what.
Point Author to it:
If you're really committed to your method names:
Create some connections (I'd make SubscriptionsController to be RESTy)
Display names, or whatever
据我所知 - 它有效! :)
As far as I know - it works! :)