对称的,自我指涉的HABTM关系

在我的架构中,我有一个名为Imprintables的模型。 在这个模型中,我有这种自我指涉关系:

class Imprintable < ActiveRecord::Base has_and_belongs_to_many :coordinates, class_name: 'Imprintable', association_foreign_key: 'coordinate_id', join_table: 'coordinates_imprintables' ... end 

在可打印的创建/编辑表单中,我有一个选择字段,用户可以在其中选择坐标imprintables(坐标用于标识与正在创建/编辑的imprintables类似的imprintables)。 我的问题是,如果我有一个可以打印的A和可打印的B,当我创建A并将列表B作为一个可以打印的坐标时,我希望能够查看B的编辑表单并查看A也列为坐标。

我已经尝试修改控制器的更新并创建操作以将两对id插入到链接器表(coordinates_imprintables)中。 例如,如果A.id = 1且B.id = 2,则执行一些sql,如:

 INSERT INTO coordinates_imprintables (imprintable_id, coordinate_id) VALUES (1, 2) INSERT INTO coordinates_imprintables (imprintable_id, coordinate_id) VALUES (2, 1) 

但我无法让它工作,因为我不知道如何知道用户何时尝试删除或插入坐标,我甚至不确定这是否是正确的答案。 Railscasts略有帮助,这似乎是一个棘手的案例,因为我有一个具有自我指涉关系的模型也是对称的。 谢谢你的时间!

你在这里寻找的是模型回调 。 它们在对象生命周期中的操作之前,之后或期间执行。

为了在您的情况下使用这些,您可以为CoordinatedImprintable表添加模型。 然后,无论何时创建,更新或销毁coordinate_imprintable ,您都需要为其镜像执行相同的操作。

 class CoordinateImprintable < ActiveRecord::Base belongs_to :imprintable belongs_to :coordinate, class_name: 'Imprintable', foreign_key 'imprintable_id' after_create :add_mirror after_update :update_mirror after_destroy :destroy_mirror def add_mirror self.class.find_or_create(imprintable: coordinate, coordinate: imprintable) end def update_mirror if self.changed? mirror = self.class.find(imprintable: coordinate_was, coordinate: imprintable_was) mirror.update_attributes(imprintable: coordinate, coordinate: imprintable) end end def destroy_mirror mirror = self.class.find(imprintable: coordinate, coordinate: imprintable) mirror.destroy if mirror && !mirror.destroyed end end 

您还需要将has_and_belongs_to_many关系更改为两个has_many :through关系。

 class Imprintable has_many :coordinate_imprintables has_many :coordinate, through: :coordinate_imprintables has_many :mirrored_coordinate_imprintables, class_name: 'CoordinateImprintable', foreign_key: 'coordinate_id' has_many :mirrored_coordinates, through: :mirrored_coordinate_imprintables, source: :imprintable end 

希望这有帮助! 如有任何问题,请随时发表评论。