无法让 has_many & belongs_to 在同一模型中工作

Can't get has_many & belongs_to in same model to work

好久没在这里问问题了。 由于我刚开始玩 Ruby,无法解决这个问题,所以我决定回到这里寻求指导。

我现在已经看了很多例子,但是我没有找到解决这个问题的正确路径。

想法如下:

你有:

他们的关系如下:

现在的验证可能无法执行此操作,但想法是没有头的家庭,没有家庭的人。 我试图用以下方式表达它:

Family class

class Family < ActiveRecord::Base

  validates :head_id, presence: true

  belongs_to :head, :class_name => Person, foreign_key: 'head_id'
  has_many :persons
end

Person class

class Person < ActiveRecord::Base

  validates :family_id, presence: true
  validates :first_name, presence: true

  belongs_to :family
end

有好心人能给我一些建议吗?

迁移在 Person-class 端有一个 family_id,该系列包含一个额外的列 person_id。

Family migration

class CreateFamilies < ActiveRecord::Migration
  def change
    create_table :families do |t|
      t.integer :head_id

      t.timestamps null: false
    end
  end
end

Person migration

class CreatePersons < ActiveRecord::Migration
  def change
    create_table :persons do |t|
      t.string :first_name
      t.string :last_name
      t.integer :age
      t.integer :family_id

      t.timestamps null: false
    end
  end
end

我不确定我是否正确理解了您的代码,但请告诉我什么是发布者 class?我认为你应该这样做:

家庭模型:
has_many:人数
has_one :head, :class_name => 人物, foreign_key: 'head_id'
验证:head_id,存在:真

人物模型:
belongs_to:家庭
验证:family_id,存在:真
验证:first_name,存在:真

一家多人人,有一个人头。这个人属于一家人,是不是一家之主对这个人来说并不重要。

迁移和验证等其他内容仍然相同。

更好地验证 :head 的存在而不是 head_id

class Family < ActiveRecord::Base

  validates :head, presence: true

  belongs_to :head, :class_name => Person, foreign_key: 'head_id'

  has_many :persons
end

人与家庭有两种关系,一种是家长,另一种是家庭成员,您必须验证(正如我在示例中所说的那样)如何处理这种关系。

class Person < ActiveRecord::Base

  validates :family, presence: true
  validates :first_name, presence: true

  belongs_to :family
  belongs_to :head, :class_name => 'Family', :foreign_key => 'head_id'
  validate :family_id_is_equal_to_head_id

  def family_id_is_equal_to_head_id 
      self.family = self.head
  end
end

最终迁移错误,必须定义关系

class CreateFamilies < ActiveRecord::Migration
  def change
    create_table :families do |t|
      t.integer :head_id


      t.timestamps null: false
    end
  end
end

class CreatePersons < ActiveRecord::Migration
  def change
    create_table :persons do |t|
      t.string :first_name
      t.string :last_name
      t.integer :age
      t.belongs_to :family
      t.integer :head_family_id


      t.timestamps null: false
    end
  end
end

你在这里有一个循环依赖。你不能创造家庭或人。 循环依赖通常表示缺少第三个元素。 More eloquently and not completely related.

有两种成员资格,头和非头。一旦你在你的代码中让它们变得明显,循环依赖就会被解决。

有几种解决方案,但您需要找到最适合您的解决方案。这是我的。

创建会员加入table

class Family
  validates :memberships, presence: true, on: :update
  has_many :memberships
  has_many :people, through: :membership

  after_create :create_head_membership

  private

  def create_head_membership
    memberships.create role: 'head' # to be filled later
  end
end

class Membership
  belongs_to :family
  belongs_to :person
end

class Person
  has_many :memberships
  has_one :family, through: :membership # has_many, amrite?
  validates :memberships, presence: true, on: :update
end

最重要的是避免Person/Family直接操纵,而是创建一些东西来处理这个过程并将其包装在事务中

class God
  def make_family head_attrs
    fam, head = nil
    Family.transaction do
      fam = Family.create!
      head = Person.create! head_attrs
      fam.memberships.first.update_attribute! :person_id, head.id
    end

    fam
  end
end