FactoryGirl has_many与双向在线验证的关联创建了额外的记录

时间:2015-01-13 18:11:12

标签: ruby-on-rails ruby validation activerecord factory-bot

我是FactoryGirl的新手,我遇到了这个特定用例的问题,这个用例似乎没有在文档中介绍过。

我有两个模特,人和书。一个人有很多书,一本书属于一个人,并且都有一个需要彼此存在的验证。 (一本书必须有一个人,一个人必须至少有一本书。)

class Person < ActiveRecord::Base
  has_many :books, inverse_of: :person
  validates :books, presence: true
end

class Book < ActiveRecord::Base
  belongs_to :person
  validates :person, presence: true
end

我需要满足其模型最低验证要求的Person和Book工厂。 Person工厂应该创建至少一本Book,而Book工厂应该创建一个Person。

这是我的工厂:

FactoryGirl.define do
  factory :person do

    transient do
      books_count 1
    end

    after :build do |person, evaluator|
      person.books << FactoryGirl.build_list(:book, evaluator.books_count, person: person)
    end
  end
end

FactoryGirl.define do
  factory :book do
    association :person
  end
end

此代码适用于FactoryGirl.create(:person)。但是,当我运行FactoryGirl.create(:book)时,会发生以下情况:

  1. 创建了一本书记录
  2. 创建人员记录
  3. 第二个不需要的书籍记录由人工厂创建。
  4. 如果我将Book工厂的人员关联更改为包含books_count为0,如association :person, books_count: 0中所示,那么我会收到错误ActiveRecord::RecordInvalid: Validation failed: Books can't be blank,因为ActiveRecord认为新的人员记录没有书籍。

    我希望图书工厂创作一本书和一个人,让每个人都满足彼此的要求。

    如何更改此代码,以便运行FactoryGirl.create(:book)会创建所需人员然后停在那里?

1 个答案:

答案 0 :(得分:1)

总结@ Anthony对这个问题的评论:

两个对象相互要求是不合逻辑的,因为在另一个对象存在之前必须存在。因此,一个人可能需要书籍:

class Person < ActiveRecord::Base
  has_many :books, inverse_of: :person
  validates :books, presence: true
end

或要求一本书要求一个人:

class Book < ActiveRecord::Base
  belongs_to :person
  validates :person, presence: true
end

但两者并不合理,因此不受Active Record的支持。