125

鉴于以下

class User < ActiveRecord::Base
  has_and_belongs_to_many :companies
end

class Company < ActiveRecord::Base
  has_and_belongs_to_many :users
end

您如何为公司和用户定义工厂,包括双向关联?这是我的尝试

Factory.define :company do |f|
  f.users{ |users| [users.association :company]}
end

Factory.define :user do |f|
  f.companies{ |companies| [companies.association :user]}
end

现在我试试

Factory :user

也许不出所料,这会导致无限循环,因为工厂递归地使用彼此来定义自己。

更令人惊讶的是,我在任何地方都没有提到如何做到这一点,是否有定义必要工厂的模式或者我在做一些根本错误的事情?

4

11 回答 11

135

这是适合我的解决方案。

FactoryGirl.define do

  factory :company do
    #company attributes
  end

  factory :user do
   companies {[FactoryGirl.create(:company)]}
   #user attributes
  end

end

如果您需要特定的公司,您可以通过这种方式使用工厂

company = FactoryGirl.create(:company, #{company attributes})
user = FactoryGirl.create(:user, :companies => [company])

希望这对某人有所帮助。

于 2012-04-18T15:07:24.567 回答
40

Factorygirl 已经更新,现在包括回调来解决这个问题。查看http://robots.thoughtbot.com/post/254496652/aint-no-calla-back-girl了解更多信息。

于 2010-01-16T03:19:32.077 回答
22

在我看来,只需创建两个不同的工厂,例如:

Factory.define :user, :class => 用户做 |u|
  # 只是普通的属性初始化
 结尾

 Factory.define :company, :class => 公司做 |u|
  # 只是普通的属性初始化
 结尾

当您为用户编写测试用例时,只需像这样编写

工厂(:用户,:公司=> [工厂(:公司)])

希望它会奏效。

于 2011-03-03T12:03:33.430 回答
9

我在提供的网站上找不到上述案例的示例。(只有 1:N 和多态关联,但没有 habtm)。我有一个类似的案例,我的代码如下所示:

Factory.define :user do |user|
 user.name "Foo Bar"
 user.after_create { |u| Factory(:company, :users => [u]) }
end

Factory.define :company do |c|
 c.name "Acme"
end
于 2011-03-03T11:30:03.540 回答
5

对我有用的是在使用工厂时设置关联。使用您的示例:

user = Factory(:user)
company = Factory(:company)

company.users << user 
company.save! 
于 2010-03-03T22:58:46.197 回答
4

发现这种方式很好而且很冗长:

FactoryGirl.define do
  factory :foo do
    name "Foo" 
  end

  factory :bar do
    name "Bar"
    foos { |a| [a.association(:foo)] }
  end
end
于 2017-02-14T10:12:34.877 回答
3
  factory :company_with_users, parent: :company do

    ignore do
      users_count 20
    end

    after_create do |company, evaluator|
      FactoryGirl.create_list(:user, evaluator.users_count, users: [user])
    end

  end

警告:对于 ruby​​ 1.8.x,将用户:[user] 更改为 :users => [user]

于 2012-04-02T15:16:17.943 回答
1

对于 HABTM,我使用了 traits 和 callbacks

假设您有以下型号:

class Catalog < ApplicationRecord
  has_and_belongs_to_many :courses
  …
end
class Course < ApplicationRecord
  …
end

您可以在上面定义工厂

FactoryBot.define do
  factory :catalog do
    description "Catalog description"
    …

    trait :with_courses do
      after :create do |catalog|
        courses = FactoryBot.create_list :course, 2

        catalog.courses << courses
        catalog.save
      end
    end
  end
end
于 2018-07-25T18:11:00.963 回答
0

首先,我强烈建议您使用 has_many :through 而不是 habtm(更多关于这里的信息),所以您最终会得到类似的结果:

Employment belongs_to :users
Employment belongs_to :companies

User has_many :employments
User has_many :companies, :through => :employments 

Company has_many :employments
Company has_many :users, :through => :employments

在此之后,您将在双方都有 has_many 关联,并且可以按照您的方式在 factory_girl 中分配给他们。

于 2009-09-28T08:30:07.157 回答
0

Rails 5 更新:

而不是使用has_and_belongs_to_many关联,您应该考虑:has_many :through关联。

此关联的用户工厂如下所示:

FactoryBot.define do
  factory :user do
    # user attributes

    factory :user_with_companies do
      transient do
        companies_count 10 # default number
      end

      after(:create) do |user, evaluator|
         create_list(:companies, evaluator.companies_count, user: user)
      end
    end
  end
end

您可以以类似的方式创建公司工厂。

设置好两个工厂后,您可以user_with_companies使用companies_count option. 您可以在此处指定用户所属的公司数量:create(:user_with_companies, companies_count: 15)

您可以在此处找到有关工厂女孩协会的详细说明。

于 2018-02-26T15:23:45.383 回答
-1

您可以定义新工厂并使用 after(:create) 回调来创建关联列表。让我们看看如何在这个例子中做到这一点:

FactoryBot.define do

  # user factory without associated companies
  factory :user do
    # user attributes

    factory :user_with_companies do
      transient do
        companies_count 10
      end

      after(:create) do |user, evaluator|
        create_list(:companies, evaluator.companies_count, user: user)
      end
    end
  end
end

属性 company_count 是瞬态的,可在工厂的属性和通过评估器的回调中使用。现在,您可以创建一个包含公司的用户,并可以选择指定您想要的公司数量:

create(:user_with_companies).companies.length # 10
create(:user_with_companies, companies_count: 15).companies.length # 15
于 2018-03-14T12:59:15.497 回答