51

レールに比較的新しく、名前、性別、father_id、mother_id (2 つの親) を持つ単一の Person モデルで非常に単純な家系の「ツリー」をモデル化しようとしています。以下は基本的に私がやりたいことですが、明らかに has_many で :children を繰り返すことはできません (最初のものは上書きされます)。

class Person < ActiveRecord::Base
  belongs_to :father, :class_name => 'Person'
  belongs_to :mother, :class_name => 'Person'
  has_many :children, :class_name => 'Person', :foreign_key => 'mother_id'
  has_many :children, :class_name => 'Person', :foreign_key => 'father_id'
end

2 つの外部キーで has_many を使用する簡単な方法はありますか、またはオブジェクトの性別に基づいて外部キーを変更する方法はありますか? または、別の/より良い方法がありますか?

ありがとう!

4

8 に答える 8

46

IRC で動作するように見える簡単な回答を見つけました (Radar のおかげです):

class Person < ActiveRecord::Base
  belongs_to :father, :class_name => 'Person'
  belongs_to :mother, :class_name => 'Person'
  has_many :children_of_father, :class_name => 'Person', :foreign_key => 'father_id'
  has_many :children_of_mother, :class_name => 'Person', :foreign_key => 'mother_id'
  def children
     children_of_mother + children_of_father
  end
end
于 2008-11-21T03:22:34.887 に答える
17

Kenzieの回答を改善するには、次のPerson#childrenように定義して ActiveRecord Relation を実現できます。

def children
   children_of_mother.merge(children_of_father)
end

詳細については、この回答を参照してください

于 2014-08-16T18:10:48.007 に答える
9

Personモデルでnamed_scopesを使用すると、次のようになります。

class Person < ActiveRecord::Base

    def children
      Person.with_parent(id)
    end

    named_scope :with_parent, lambda{ |pid| 

       { :conditions=>["father_id = ? or mother_id=?", pid, pid]}
    }
 end
于 2010-03-27T14:13:30.043 に答える
6

:has_one を使用して、必要な関係を実現できると思います。

class Person < ActiveRecord::Base
  has_one :father, :class_name => 'Person', :foreign_key => 'father_id'
  has_one :mother, :class_name => 'Person', :foreign_key => 'mother_id'
  has_many :children, :class_name => 'Person'
end

仕事の後にこの回答を確認して編集します。)

于 2008-11-21T02:44:13.887 に答える
4

Associations and (multiple) Foreign keys in rails (3.2)に対する私の答え: モデルでそれらを記述し、移行を記述する方法はあなただけのものです!

あなたのコードに関しては、ここに私の変更があります

class Person < ActiveRecord::Base
  belongs_to :father, :class_name => 'Person'
  belongs_to :mother, :class_name => 'Person'
  has_many :children, ->(person) { unscope(where: :person_id).where("father_id = ? OR mother_id = ?", person.id, person.id) }, class_name: 'Person'
end

質問はありますか?

于 2016-11-04T16:56:20.910 に答える
3

私は同じ機能を探していました。配列ではなく を返したくない場合は、 の代わりにActiveRecord::AssociationRelation使用できます。( ActiveRecord のドキュメントを参照してください)<<+

class Person < ActiveRecord::Base
  belongs_to :father, :class_name => 'Person'
  belongs_to :mother, :class_name => 'Person'

  has_many :children_of_father, :class_name => 'Person', :foreign_key => 'father_id'
  has_many :children_of_mother, :class_name => 'Person', :foreign_key => 'mother_id'

  def children
     children_of_mother << children_of_father
  end
end
于 2016-06-07T20:05:10.423 に答える