FactoryGirl.create 上的 NotNullViolation 与 has_one 关联

NotNullViolation on FactoryGirl.create with has_one association

我在调用 Factory 上的 create 时遇到 Null violation 错误。

这是我的两个模型:

# Table name: test_masters
#  id         :integer          not null, primary key
class TestMaster < ActiveRecord::Base
  has_one :test_slave, dependent: :destroy
end

# Table name: test_slave
#  id             :integer          not null, primary key
#  test_master_id :integer          not null
class TestSlave < ActiveRecord::Base
  belongs_to :test_master, dependent: :destroy
end

以及以下工厂:

FactoryGirl.define do
  factory :test_master do
    test_slave
  end
end

FactoryGirl.define do
  factory :test_slave do
  end
end

当我在 rails 控制台中运行 FactoryGirl.create(:test_master) 时,出现以下错误:

PG::NotNullViolation: ERROR:  null value in column "test_master_id" violates not-null constraint
ActiveRecord::StatementInvalid: PG::NotNullViolation: ERROR:  null value in column "test_master_id" violates not-null constraint

我以为从 test_master 工厂调用 test_slave 工厂会自动提供 test_master_id... 但事实似乎并非如此。

我的工厂有问题吗?

您的 test_slave 工厂应该定义创建有效记录所需的属性。由于您的 TestSlave 需要 TestMaster,您需要在 test_slave 工厂中定义它。

简而言之,您在错误的方向指定了工厂中的关联。试试这个:

FactoryGirl.define do
  factory :test_master do
  end
end

FactoryGirl.define do
  factory :test_slave do
    test_master
  end
end

然后,当您执行 FactoryGirl.create(:test_slave) 时,您可以指定其 TestMaster:

master = FactoryGirl.create(:test_master)
FactoryGirl.create(:test_slave, test_master: test_master)

或者如果不指定该属性,它将为您生成一个:

FactoryGirl.create(:test_slave) # Generates a new TestMaster and uses that.

希望对您有所帮助!

我最终找到了一种使用构建后回调创建带有默认从属工厂的主工厂的方法...(同时保留 theunraveler 的解决方案) 以下工厂现在为我提供了我在规格中所需的足够灵活性:

FactoryGirl.define do
  factory :test_master do
    factory :test_master_with_slave do
      after(:build) do |master|
        master.test_slave = FactoryGirl.build(:test_slave,
                                              test_master: master)
      end
    end
  end
end

FactoryGirl.define do
  factory :test_slave do
    test_master
  end
end

(theunraveler,感谢您提供替代解决方案。它为我指明了正确的方向。)