具有has_one关联的FactoryGirl.create上的NotNullViolation

时间:2015-01-08 21:08:12

标签: ruby-on-rails ruby-on-rails-4 associations factory-bot

我遇到问题,在我的工厂调用create时出现Null违规错误。

这是我的两个模特:

# 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 ......但似乎并非如此。

我的工厂有问题吗?

2 个答案:

答案 0 :(得分:1)

您的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.

希望有所帮助!

答案 1 :(得分:0)

我最终找到了一种使用after build回调创建一个带有默认slave的主工厂的方法...(同时保留了unraveler的解决方案) 现在,以下工厂在我的规范中给了我足够的灵活性:

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,感谢替代解决方案。它指出了我正确的方向。)