使用多态多对多自引用关系以及 Rails 中关系上的属性
我想在 Rails 中创建自引用关系。我有一个 Person 模型,该人应该有具有相同 Person 对象的大师和学生。
到目前为止,我尝试过:
class Person <ActiveRecord::Base
has_many :relationships, :dependent => :destroy
has_many :masters, :through => :relationships, :conditions => "status='master'"
has_many :pupils, :through => :relationships, :conditions => "status='pupil'"
has_many :inverse_relationships, :class_name => "Relationship",
:foreign_key => "related_id"
has_many :inverse_masters, :through => :inverse_relationships,
:source => :person, :conditions => "status='master'"
has_many :inverse_pupils, :through => :inverse_relationships,
:source => :person, :conditions => "status='pupil'"
end
class Relationship < ActiveRecord::Base
belongs_to :person
belongs_to :master, :class_name => "Person", :foreign_key => 'related_id'
belongs_to :pupil, :class_name => "Person", :foreign_key => 'related_id'
end
当我尝试选择时,它似乎有效:
@a = Person.find(:first)
@a.masters
但是当我尝试推送到主控时,它会保存关系,而不会将状态设置为主控。它会保存 null。有没有一种简单的方法可以在我推入大师时保存 status=master
并在推入学生时保存 status=pupil
?
谢谢
I'd like to create a self referencing relation in rails. I have a Person model, and the person should have masters and pupils with same Person object.
So far I tried:
class Person <ActiveRecord::Base
has_many :relationships, :dependent => :destroy
has_many :masters, :through => :relationships, :conditions => "status='master'"
has_many :pupils, :through => :relationships, :conditions => "status='pupil'"
has_many :inverse_relationships, :class_name => "Relationship",
:foreign_key => "related_id"
has_many :inverse_masters, :through => :inverse_relationships,
:source => :person, :conditions => "status='master'"
has_many :inverse_pupils, :through => :inverse_relationships,
:source => :person, :conditions => "status='pupil'"
end
class Relationship < ActiveRecord::Base
belongs_to :person
belongs_to :master, :class_name => "Person", :foreign_key => 'related_id'
belongs_to :pupil, :class_name => "Person", :foreign_key => 'related_id'
end
It seems to work when I am trying to select:
@a = Person.find(:first)
@a.masters
but when I try to do a push into masters, it saves the relationship without the status set to master. It saves null instead. Is there an easy way to save status=master
when I push into masters and status=pupil
when I push into pupils?
Thanks
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
简而言之,解决方案是:关联回调(更多信息请参见关联回调部分:http://railsapi.com/doc/rails-v3.0.0/classes/ActiveRecord/Associations/ClassMethods.html)
为了更详细一点,我对您的示例进行了一些调整位,但基本上结构是相同的,这里是代码:
RelationShip 模型包含一个类型列,它相当于您的状态列,但如果我以后想做 STI 并声明 MasterPupil/PupilMaster 关系模型,类型会更好。
RelationShip 还有一个 set_type before_validation ,它将类型设置为 OpenRelationship ,这应该是临时的,然后在每个关联中的 Person 模型中定义的 after_add 回调将事情搞清楚(并设置 MasterPupil 或 PupilMaster 类型)
,现在:
To make it short the solution is: association callbacks (more here under the Association Callback section: http://railsapi.com/doc/rails-v3.0.0/classes/ActiveRecord/Associations/ClassMethods.html)
To be a little more detailed I have adapted your example a little bit, but basically the structure is the same, here is the code:
The RelationShip model contains a type column which is the equivalent of your status column, but type is nicer if I later want to do an STI and declare MasterPupil/PupilMaster relationship models.
RelationShip also has a set_type before_validation that will set the type to OpenRelationship which should be temporary before the after_add callback defined in the Person model in each association will set things clear (and set either a MasterPupil or PupilMaster type)
and now: