为什么我的工厂不承认我的泳池协会?

时间:2015-08-15 00:14:27

标签: ruby-on-rails ruby rspec factory-bot

我们定义了以下模型

  class UserPool < ActiveRecord::Base
    belongs_to :pool
    belongs_to :user
    validates :pool, presence: true
    validates :user, presence: true

    def self.created(date)
      where("DATE(created_at) = ?", date)
    end
  end

以及以下的Factroy

  FactoryGirl.define do
    factory :user_pool do
      pool
      user

      factory :paid_user_pool do
        money_on_pool 10
      end
    end
  end

当我运行以下测试时,我发现错误

  describe "obtain users_pools created at specifict time" do
    before do
      users = create_list :user, 3, active: false
      user4 = create :user

      @pool = create :pool
      users.each do |user|
        create :user_pool, user: user, pool: @pool, created_at: 1.days.ago
      end
      create :user_pool, user: user4, pool: @pool
    end

    it "should return just users_pools created at specifict time" do
      users_pools = @pool.user_pools.created( 1.days.ago )
      users_pools.count.should eq 3
    end
  end

错误:

  ActiveRecord::RecordInvalid:
    The validation failed: Pool can’t be blank 

为什么我的工厂不承认我的泳池协会?

2 个答案:

答案 0 :(得分:0)

因为,您的关联对象未正确创建。因此,验证失败。

请勿保存关联的对象,请在工厂中指定strategy: :build

factory :user_pool do
  association :pool, factory: :pool, strategy: :build
  association : user, factory: :user, strategy: :build
end

然后,使用build代替create

pool = build(:pool)
. . . 
. . .

阅读this discussion,可以为您提供有关该问题的更多见解。

答案 1 :(得分:0)

创建工厂时,列出具有预定义值的属性。否则,您可以从工厂中省略它们并在测试中明确说明它(在创建期间)。

# Example for :user
factory :user do
  sequence(:name)    { |n| "Test User #{n}" }
end

现在,当您致电create(:user)时,默认名称将包含为每个创建的用户增加1的数字。有关详细信息,请参阅#sequence"Sequences"

现在进入您的具体示例。您可以通过以下两种方式之一创建user_pool工厂。

# No default attributes, requires explicit assignment
factory :user_pool do
end
create(:user_pool, user: user, pool: @pool)

# Default attributes can be overridden during test
# Requires you to create :user and :pool factories
factory :user_pool do
  after(:build) do |user_pool|
    user_pool.user = create(:user)
    user_pool.pool = create(:pool)
  end
end

当您build一个ActiveRecord对象时,它不会提交给数据库。您可以省略所需的属性。构建对象后,将创建两个(userpool),并将其分配给正确的user_pool属性。有关详细信息,请参阅文档中的"Callbacks"

如果您想在测试中创建@pool,您仍然可以执行以下操作。它将覆盖默认的pooluser属性。

user_pool = create(:user_pool, user: user, pool: @pool)