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

时间:2009-06-05 17:43:22

标签: ruby-on-rails 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的身份
  • to_character_id =字符B的ID
  • description =一些文字

我编写了各种额外的方法,如character.links_to(返回指向该字符的所有链接的数组)或link.to_character(返回链接指向的字符),或{{1 (返回其他字符的数组,其中包含指向此字符的链接)。我还写了一个回调函数,以确保删除一个字符时,删除所有转到该字符的链接(恢复时也是如此)。

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

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

3 个答案:

答案 0 :(得分:3)

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

答案 1 :(得分:2)

我认为您需要以下内容:

 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关联的所有选项

答案 2 :(得分:0)

我认为你真正想要的是使用连接表的自我参照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

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

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