【问题标题】:ActiveRecord has_many where two columns in table A are primary keys in table BActiveRecord has_many 其中表 A 中的两列是表 B 中的主键
【发布时间】:2010-01-24 00:57:45
【问题描述】:

我有一个模型Couple,它有两列first_person_idsecond_person_id,还有一个模型Person,它的主键是person_id,列有name

这是我想要的用法:

#including 'Person' model for eager loading, this is crucial for me
c = Couple.find(:all, :include => :persons)[0]
puts "#{c.first_person.name} and #{c.second_person.name}"

那么我该怎么做呢?

【问题讨论】:

  • 如果你使用 Rails,为什么 Person 模型的主键是“person_id”而不仅仅是“id”?
  • 我为这篇文章更改了模型的名称,因为我想让这些名称远离互联网。它应该是id,但这不是一个困难的修复。只需使用set_primary_key

标签: ruby-on-rails ruby activerecord has-many


【解决方案1】:

Couple 中声明的关系应如下所示:

class Couple
  named_scope :with_people, { :include => [:first_person, :second_person] }
  belongs_to :first_person, :class_name => 'Person'
  belongs_to :second_person, :class_name => 'Person'
end

#usage:
Couple.with_people.first
# => <Couple ... @first_person: <Person ...>, @second_person: <Person ...>>

Person 中的那些取决于Person 是否可以是多个Couple 的一部分。如果 Person 只能属于一个 Couple 并且不能是一个上的“第一个”Person 和另一个上的 Second,您可能想要:

class Person
  has_one :couple_as_first_person, :foreign_key => 'first_person_id', :class_name => 'Couple'
  has_one :couple_as_second_person, :foreign_key => 'second_person_id', :class_name => 'Couple'

  def couple
    couple_as_first_person || couple_as_second_person
  end
end

如果Person 可以属于多个Couples,并且无法判断它们是任何给定Couple 中的“第一”还是“第二”,您可能想要:

class Person
  has_many :couples_as_first_person, :foreign_key => 'first_person_id', :class_name => 'Couple'
  has_many :couples_as_second_person, :foreign_key => 'second_person_id', :class_name => 'Couple'

  def couples
    couples_as_first_person + couples_as_second_person
  end
end

【讨论】:

  • 这是一个写得很好的、经过深思熟虑的答案。非常感谢。我会尽快测试并通知您。
  • 还没有测试过,但是你赢了:)
  • 我刚刚使用 AREL 做了这样的事情:def widgets; Widget.where( Wiget.arel_table[:asset1_id].eq(id).or( Widget.arel_table[:asset2_id].eq(id) ) ); end
【解决方案2】:

未经测试,但根据Rails API documentation,可能类似于:

class Couple < ActiveRecord::Base
    has_one :person, :foreign_key => :first_person_id
    has_one :person, :foreign_key => :second_person_id
end

【讨论】:

  • 那些应该是belongs_to,而不是has_one,因为外键在这个模型上。
【解决方案3】:

仅理论,未经测试:

创建两个 Person 子类:

class FirstPerson < Person
   belongs_to :couple

class SecondPerson < Person
   belongs_to :couple

Couple class has_many of each:

class Couple
   has_many :first_persons, :foreign_key => :first_person_id
   has_many :second_persons, :foreign_key => :second_person_id

然后找到:

 Couple.all(:include => [:first_persons, :second_persons])

【讨论】:

  • 不应该是一对has_one :first_person:second_person吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-01
  • 2021-06-27
  • 2015-12-27
  • 1970-01-01
  • 2020-09-12
  • 2012-12-18
相关资源
最近更新 更多