FactoryGirl嵌套瞬态has_many与验证的关联

时间:2016-03-31 01:32:22

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

我的问题是FactoryGirl has_many association with validation的问题,关联的复杂性增加了“瞬态”属性,并且是非常嵌套的

即。我的课程是(我正在使用mongoid,假设Mongoid::Document包含在所有模型中)

class User
  has_many :company_admin_profiles
end

class CompanyAdminProfile
  belongs_to :company
  belongs_to :user # Cannot exist standalone
end

class Company
  has_many :company_admin_profiles

  validate :has_at_least_one_admin
end

到目前为止,我已经写了FactoryGirl

FactoryGirl.define do
  factory :user do
    ...

    trait(:company_admin) do
      transient do
        company_admins_count 1
        company { create(:company, admins_count: 0) }
      end

      after(:build) do |user, evaluator|
        create_list(:company_admin_profile, evaluator.company_admins_count,
          company: evaluator.company,
          user: user,
          first_name: user.first_name,
          last_name: user.last_name,
          email: user.email)
      end
    end

    factory :company_admin_user, traits: [:company_admin]

  end
end

FactoryGirl.define do
  factory :company_admin_profile, class: Company::Admin do
    company
  end
end


FactoryGirl.define do
  factory :company do

    transient do
      admins_count 1 # need one admin to pass validation
    end

    after(:build) do |company, evaluator|
      build_list(:company_admin_user, evaluator.admins_count,
          company: company)

    end
  end
end

我已经尝试了几种变体,最后一个错误是

* company - Attribute already defined: company (FactoryGirl::AttributeDefinitionError)
* company_admin_profile - Attribute already defined: company (FactoryGirl::AttributeDefinitionError)
* company_admin_user - Attribute already defined: company (FactoryGirl::AttributeDefinitionError)

1 个答案:

答案 0 :(得分:0)

我刚刚看到了这个问题的支持,所以也许有人真的对我现在的解决方案感兴趣。

我不记得问题究竟在哪里,但这里有一段有效的代码:

# factories/company.rb
FactoryGirl.define do
  factory :company do
    ...

    transient do
      admins_count 1 # need one admin to pass validation
    end

    after(:build) do |comp, evaluator|
      if evaluator.admins_count == 1
        build(:company_admin_user, company: comp)
      end
    end
  end
end

# factories/user.rb
FactoryGirl.define do
  factory :user do
    ...

    after(:build) do |user|
      user.skip_confirmation!
    end

    # Company admin
    trait(:company_admin) do
      transient do
        company_admins_count 1
        company { build(:company, admins_count: 0) }
      end

      after(:build) do |user, evaluator|
        create_list(:company_admin_profile, evaluator.company_admins_count,
          company: evaluator.company,
          user: user)
        evaluator.company.save
      end
    end

    factory :company_admin_user, traits: [:company_admin]
  end
end

# factories/company_admin_profile.rb
FactoryGirl.define do
  factory :company_admin_profile, class: CompanyAdminProfile do
    ...
    company
  end
end