【问题标题】:NotNullViolation on FactoryGirl.create with has_one associationFactoryGirl.create 上的 NotNullViolation 与 has_one 关联
【发布时间】:2015-01-08 21:08:12
【问题描述】:

我遇到了一个问题,在我的 Factory 上调用 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...但似乎并非如此。

我的工厂有问题吗?

【问题讨论】:

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


    【解决方案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.
    

    希望有帮助!

    【讨论】:

      【解决方案2】:

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

      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
      

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2013-07-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-04-19
        • 1970-01-01
        相关资源
        最近更新 更多