为什么要使用相互的has_one关系?

时间:2014-05-02 07:51:31

标签: ruby-on-rails ruby database

查看Rails中的ActiveRecord has_one和has_many关系,这可能是一个普遍的(很可能是显而易见的)问题。

如果我有两张桌子,说丈夫和妻子,这是一夫一妻制的所有已婚夫妇数据库,那么每个丈夫都有一个妻子,每个妻子都有一个丈夫。因此,将此视为一对情侣表是有意义的。

为什么有人想要两个表,其中两个表与另一个表具有has_one关系,而不是将它们组合成一个表?

  • 可以提高效率吗?
  • 它可以涵盖一些我无法理解的案例吗?

4 个答案:

答案 0 :(得分:4)

取决于。

如果:

  1. 你只对这对夫妇感兴趣,
  2. 个人不持有任何数据,
  3. 每个人都是配偶,
  4. 然后,是的,使用单个表可能有意义。

    但是,如果上述任何一项是错误的,您将需要使用个别记录。

    您应该声明这样的关联:

    class Person < ActiveRecord::Base
    
      validates :gender, presence: :true
    
      belongs_to :wife, -> { where gender: "F" },
                        foreign_key: :wife_id,
                              class: "Person"
    
    
      has_one :husband, -> { where gender: "M" },
                        foreign_key: :wife_id,
                              class: "Person"
    
    end
    

    但是,如果您希望 couple 记录也包含一些数据,那么使用这种实现可能会更好:

    class Marriage < ActiveRecord::Base
      validates :husband_id, presence: true
      validates :wife_id, presence: true
    
      belongs_to :husband, class: "Person"                
      belongs_to :wife, class: "Person"
    end
    
    
    
    class Person < ActiveRecord::Base
      has_one :marriage
    
      has_one :husband, though: :marriage
      has_one :wife, though: :marriage
    end
    

    虽然你应该知道如果person = Person.find()wife,比如person.wife,而你致电{{1}},它可能会自行返回。

答案 1 :(得分:3)

您可以使用Husband的继承和Wife的{​​{1}},然后使用Person字段,只关联type和{{1通过spouse_id。

Husband

答案 2 :(得分:1)

只需使用belongs_to,它就更简单了。 @Малъ Скрылевъ的答案是对的,但我想告诉你一个简单的方法来实现它:

#app/models/spouse.rb
Class Spouse < ActiveRecord::Base
    belongs_to :spouse, foreign_key: "spouse_id", class_name: "Spouse"
end

这将为您提供一个表格:

spouses
id | spouse_id | name | created_at | updated_at

这将允许您执行:

@person = Spouse.find params[:id]
@person.spouse # -> finds by spouse_id

如果您想由丈夫/妻子确定,请使用Малъ Скрылевъ的{​​{3}}答案

答案 3 :(得分:0)

我从答案中学到了很多,但他们中的大多数人都把我的夫妻实例也用了字面意思。这只是一个例子。问题是任何A has_one B,B has_one A关系。

sevenseacat的第三条评论&#34;实体之间的关系就是 - 一种关系&#34;真的给了我关于我的问题的第二部分的想法,即&#34;有些我无法理解的情况&#34;。

  

虽然丈夫的妻子关系是一种反身关系,但不是每个关系都必须如此。例如,我们可以有这样的关系:A&#34;最被吸引到&#34; B,不一定是反身的。 B可能会发现其他一些人最有吸引力。因此,即使每个A has_one B,并且每个B has_one A,这种关系也不一定会创建对。用简单的英语,&#34;被吸引到&#34;不一定是一种相互关系(许多人很难接受的生活中可悲的事实)。

对于问题的第一部分,就效率而言,在某些答案中暗示的一点是因为你可以将它们放在一个表中并不意味着你必须这样做。

  

如果我们通常只对个人感兴趣,而且很少在配偶中感兴趣,那么拥有一张长行的桌子可能效率低下。另一方面,如果通常我们同时对配偶双方的数据感兴趣,那么组合表可能会更好。

正如其他答案所述,

  

当我们让两个表都相似时,除了性别,然后为人们提供一个表,它有自己的好处,并且给出了许多有趣的方法来实现这个选项。