无法获得has_many& belongs_to在同一个模型中工作

时间:2015-03-20 20:28:41

标签: ruby-on-rails-4 rails-activerecord

我问过这里的事情已经有一段时间了。 由于我刚开始玩Ruby,并且无法理解这一点,所以我决定回到这里寻求指导。

我现在已经阅读了很多例子,但我找不到合适的路径来解决这个问题。

这个想法如下:

你有:

  • 一个家庭
  • 一个人

他们的关系如下:

  • 有一个人是家庭的“头”
  • 每个人都是一个家庭的一部分(无论是多人还是只有他自己)

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

  

家庭班

class Family < ActiveRecord::Base

  validates :head_id, presence: true

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

人类

class Person < ActiveRecord::Base

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

  belongs_to :family
end

任何灵魂都会如此友好地向我提供一些建议吗?

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

  

家庭移民

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.integer :family_id

      t.timestamps null: false
    end
  end
end

3 个答案:

答案 0 :(得分:1)

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

有两种成员,头部和非头部。一旦你的代码中显而易见,循环依赖就会得到解决。

有一些解决方案,但你需要找到最适合你的解决方案。这是我的。

创建会员加入表

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

答案 1 :(得分:0)

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

家庭模式:
has_many:人士 has_one:head,:class_name =&gt;人,foreign_key:'head_id'
验证:head_id,存在:真实

人物模型:
belongs_to:family
验证:family_id,在场:真实 验证:first_name,presence:true

家庭有很多人,有一个头。 属于家庭,如果该人是家长,则无关紧要。

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

答案 2 :(得分:0)

更好地验证存在:头部不是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