Pergunta

Dado o seguinte

class User < ActiveRecord::Base
  has_and_belongs_to_many :companies
end

class Company < ActiveRecord::Base
  has_and_belongs_to_many :users
end

Como você define fábricas para empresas e usuários, incluindo a associação bidirecional? Aqui está a minha tentativa

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

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

Agora eu tento

Factory :user

talvez sem surpresa Isto resulta num ciclo infinito como as fábricas utilizam recursivamente uns aos outros para definir-se.

O mais surpreendente que eu não encontrei uma menção de como fazer isso em qualquer lugar, há um padrão para definir as fábricas necessárias ou estou fazendo algo fundamentalmente errado?

Foi útil?

Solução 2

Factorygirl já foi atualizado e agora inclui retornos de chamada para resolver este problema. Dê uma olhada na http://robots.thoughtbot.com/post / 254496652 / aint-no-calla-back-girl para mais informações.

Outras dicas

Aqui está a solução que funciona para mim.

FactoryGirl.define do

  factory :company do
    #company attributes
  end

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

end

se você vai precisar empresa específica que você pode usar fábrica desta forma

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

Espero que isso será útil para alguém.

Na minha opinião, basta criar duas fábricas diferentes, como:

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

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

Quando você escreve os estudos de casos para o usuário, em seguida, basta escrever como este

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

A esperança que vai funcionar.

Eu não poderia encontrar um exemplo para o caso mencionado acima no site fornecido. (Apenas 1: N e assocations polimórficas, mas não habtm). Eu tive um caso semelhante e minha aparência código como este:

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

O que funcionou para mim foi a criação da associação ao usar a fábrica. Usando o seu exemplo:

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

company.users << user 
company.save! 
  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

Aviso: usuários Mudança: [usuário] para: users => [usuário] para Ruby 1.8.x

Encontrado desta forma agradável e detalhado:

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

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

Primeiro de tudo eu encorajamos você a usar has_many: through em vez de habtm (mais sobre este aqui ), então você vai acabar com algo como:

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

Após isso, você vai ter associação has_many em ambos os lados e pode atribuir a eles em factory_girl da maneira que você fez isso.

Atualização para Rails 5:

Em vez de usar associação has_and_belongs_to_many, você deve considerar:. Associação has_many :through

A fábrica de usuário para esta associação parece com isso:

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

Você pode criar a fábrica da empresa de uma forma similar.

Uma vez que ambas as fábricas estão definidas, você pode criar fábrica user_with_companies com companies_count option. Aqui você pode especificar quantas empresas o usuário pertence: create(:user_with_companies, companies_count: 15)

Você pode encontrar explicação detalhada sobre fábrica associações menina aqui .

Você pode definir nova fábrica e após uso (: criar) de retorno de chamada para criar uma lista de associações. Vamos ver como fazê-lo neste exemplo:

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

Atributo companies_count é um transiente e disponível em atributos da fábrica e no retorno de chamada via o avaliador. Agora, você pode criar um usuário com empresas com a opção para especificar quantas empresas você quer:

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

Para HABTM Eu costumava traços e retornos de chamada .

Digamos que você tenha os seguintes modelos:

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

Você pode definir a fábrica acima :

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
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top