如何在Factory girl中创建has_and_belongs_to_many关联

时间:2009-09-27 20:17:36

标签: ruby-on-rails associations has-and-belongs-to-many factory-bot

鉴于以下内容

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

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

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

10 个答案:

答案 0 :(得分:126)

这是适用于我的解决方案。

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])

希望这会对某人有所帮助。

答案 1 :(得分:40)

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

答案 2 :(得分:22)

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

 Factory.define :user, :class => User do |u|
  # Just normal attributes initialization
 end

 Factory.define :company, :class => Company do |u|
  # Just normal attributes initialization
 end

当你为用户编写测试用例时,就像这样写

 Factory(:user, :companies => [Factory(:company)])

希望它能奏效。

答案 3 :(得分: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

答案 4 :(得分:5)

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

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

company.users << user 
company.save! 

答案 5 :(得分: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

警告:将用户:[user]更改为:users =&gt; [用户]为ruby 1.8.x

答案 6 :(得分:3)

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

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

  factory :bar do
    name "Bar"
    foos { |a| [a.association(:foo)] }
  end
end

答案 7 :(得分:0)

首先,我强烈建议你使用has_many:through而不是habtm(更多关于这个here),所以你最终会得到类似的东西:

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中分配给他们。

答案 8 :(得分:0)

您可以定义新工厂并使用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

属性companies_count是一个瞬态的,​​可以在工厂的属性中使用,也可以通过求值程序在回调中使用。现在,您可以创建一个公司用户,可以选择指定您想要的公司数量:

create(:user_with_companies).companies.length # 10
create(:user_with_companies, companies_count: 15).companies.length # 15

答案 9 :(得分:0)

对于HABTM,我使用了特征和回调

假设您有以下型号:

public static boolean isServiceRunning(String serviceClassName,Context context) {
        final ActivityManager activityManager = (ActivityManager)context.getSystemService(Context.ACTIVITY_SERVICE);

您可以在上方定义工厂

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