连接表的ActiveRecord关系链接同一个表的两个记录?

我有一个角色模型和一个链接模型。 Link模型表示从角色到另一个角色的链接。 链接具有文本“描述”属性。 从字符A到字符B的链接与从B到A的相反链接不同。字符与另一个字符有零个或一个链接。 角色可以具有到不同角色的各种链接。 字符可以通过各种不同的字符链接。

我使用了使用Active Record关系来部分实现Character和Link模型之间的关系:

class Character has_many :links # the links from the character to other characters class Link belongs_to :character # the character from which starts the link to another character 

它给了我有用的方法,如character.links(从这个字符开始的所有链接的数组)或link.character(从中开始链接的字符)

链接模型还有一个to_character_id ,其中包含转到链接的角色的id。 因此,从字符A到字符B的链接是具有以下属性的实例:

  • character_id =角色A的id
  • to_character_id =字符B的id
  • description =一些文字

我写了各种额外的方法,比如character.links_to (返回指向字符的所有链接的数组)或link.to_character (返回指向链接的character.characters_who_link_to ),或者character.characters_who_link_to (返回另一个的数组)带有此角色链接的字符)。 我还写了一个回调函数,以确保删除一个字符时,删除所有转到此字符的链接(恢复时也是如此)。

是否可以使用额外的AR关系声明来为我提供这种额外的方法,这样我就不必自己写那些方法和回调了?

使用Rails的Agile Web开发在“使用模型作为连接表”一节中提供了一个解决方案,但是对于连接两个不同表的连接表。 在我的情况下,我的连接表链接连接单个表的记录,字符。

has_and_belongs_to_many不再使用了; 我会使用has_many :through代替。

 class Character < ActiveRecord::Base has_many :links, :dependent => destroy has_many :characters, :through => :links has_many :source_links, :class_name => "Link", :foreign_key => "to_character_id", :dependent => :destroy has_many :source_characters, :class_name => "Character", :through => :destination_links end class Link < ActiveRecord::Base belongs_to :character belongs_to :source_character, :class_name => "Character", :foreign_key => "to_character_id" end 

注意:dependent => :destroy选项 – 这些将在删除字符时删除链接。 命名是正确的 – 从角色的角度来看, source_links是指向该角色的链接。 所以现在你可以这样做:

 @character.characters # characters I link to @character.links # links I have to other characters @character.source_characters # characters that link to me @character.source_links # links other characters have to me 

我想你想要的东西如下:

  class Character < ActiveRecord::Base has_many :outbound_links, :class_name => "Link", :foreign_key => "from_character_id" has_many :inbound_links, :class_name => "Link", :foreign_key => "to_character_id" end class Link < ActiveRecord::Base belongs_to :from_character, :class_name => "Character", :foreign_key => "from_character_id" belongs_to :to_character, :class_name => "Character", :foreign_key => "to_character_id" end 

您可以在http://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html上阅读有关ActiveRecord协会的所有选项。

我认为你真正想要的是使用连接表的自引用HABTM关系

所以,如果你有一个连接表

 create_table :character_links do |t| t.integer :character_id t.integer :linked_character_id t.timestamps #if you want to know when the relationship was created end 

然后你会的

 class Characters < ActiveRecord::Base has_and_belongs_to_many :linked_characters, :class_name => "Characters", :join_table => :character_links, :foreign_key => "character_id", :associated_foreign_key => "linked_character_id" 

如果您需要传出链接和传入链接,那么您可以这样做

 class Characters < ActiveRecord::Base has_and_belongs_to_many :outgoing_links, :class_name => "Characters", :join_table => :character_links, :foreign_key => "character_id", :associated_foreign_key => "linked_character_id" has_and_belongs_to_many :incoming_links, :class_name => "Characters", :join_table => :character_links, :foreign_key => "linked_character_id", :associated_foreign_key => "character_id" 

刚刚切换了foreign_key和associated_foreign_key

这使您无需拥有单独的Links模型

这是空气代码(未经测试)