rspec ruby-on-rails-3.1 has-many-through factory-bot

rspec - Cómo configurar una fábrica en FactoryGirl con la asociación has_many



ruby-on-rails-3.1 has-many-through (5)

¿Alguien puede decirme si estoy haciendo la instalación de la manera incorrecta?

Tengo los siguientes modelos que tienen has_many.through asociaciones:

class Listing < ActiveRecord::Base attr_accessible ... has_many :listing_features has_many :features, :through => :listing_features validates_presence_of ... ... end class Feature < ActiveRecord::Base attr_accessible ... validates_presence_of ... validates_uniqueness_of ... has_many :listing_features has_many :listings, :through => :listing_features end class ListingFeature < ActiveRecord::Base attr_accessible :feature_id, :listing_id belongs_to :feature belongs_to :listing end

Estoy usando Rails 3.1.rc4, FactoryGirl 2.0.2, factory_girl_rails 1.1.0 y rspec. Aquí está mi comprobación de cordura rspec rspec básica para la :listing fábrica de :listing :

it "creates a valid listing from factory" do Factory(:listing).should be_valid end

Aquí está la fábrica (: listado)

FactoryGirl.define do factory :listing do headline ''headline'' home_desc ''this is the home description'' association :user, :factory => :user association :layout, :factory => :layout association :features, :factory => :feature end end

Las :listing_feature y :feature tienen una configuración similar.
Si la association :features line está comentada, todas mis pruebas pasan.
Cuando es

association :features, :factory => :feature

el mensaje de error es undefined method ''each'' for #<Feature> que pensé que tenía sentido para mí porque porque listing.features devuelve una matriz. Así que lo cambié a

association :features, [:factory => :feature]

y el error que obtengo ahora es ArgumentError: Not registered: features ¿No es sensato generar objetos de fábrica de esta manera, o qué me estoy perdiendo? Muchas gracias por cualquier entrada!


Alternativamente, puede usar un bloque y omitir la palabra clave de association . Esto hace que sea posible construir objetos sin guardarlos en la base de datos (de lo contrario, una asociación has_many guardará sus registros en el archivo db, incluso si usa la función de build lugar de create ).

FactoryGirl.define do factory :listing_with_features, :parent => :listing do |listing| features { build_list :feature, 3 } end end


Así es como configuré el mío:

# Model 1 PreferenceSet class PreferenceSet < ActiveRecord::Base belongs_to :user has_many :preferences, dependent: :destroy end #Model 2 Preference class Preference < ActiveRecord::Base belongs_to :preference_set end # factories/preference_set.rb FactoryGirl.define do factory :preference_set do user factory: :user filter_name "market, filter_structure" factory :preference_set_with_preferences do after(:create) do |preference| create(:preference, preference_set: preference) create(:filter_structure_preference, preference_set: preference) end end end end # factories/preference.rb FactoryGirl.define do factory :preference do |p| filter_name "market" filter_value "12" end factory :filter_structure_preference, parent: :preference do filter_name "structure" filter_value "7" end end

Y luego en tus pruebas puedes hacer:

@preference_set = FactoryGirl.create(:preference_set_with_preferences)

Espero que ayude.


Crear este tipo de asociaciones requiere utilizar las devoluciones de llamada de FactoryGirl.

Un conjunto perfecto de ejemplos se puede encontrar aquí.

http://robots.thoughtbot.com/post/254496652/aint-no-calla-back-girl

Para llevarlo a casa a tu ejemplo.

Factory.define :listing_with_features, :parent => :listing do |listing| listing.after_create { |l| Factory(:feature, :listing => l) } #or some for loop to generate X features end


Intenté algunos enfoques diferentes y este es el que mejor funcionó para mí (adaptado a su caso)

FactoryGirl.define do factory :user do # some details end factory :layout do # some details end factory :feature do # some details end factory :listing do headline ''headline'' home_desc ''this is the home description'' association :user, factory: :user association :layout, factory: :layout after(:create) do |liztng| FactoryGirl.create_list(:feature, 1, listing: liztng) end end end


Puedes usar el trait :

FactoryGirl.define do factory :listing do ... trait :with_features do features { build_list :feature, 3 } end end end

Con callback , si necesita creación de DB:

... trait :with_features do after(:create) do |listing| create_list(:feature, 3, listing: listing) end end

Use en sus especificaciones de esta manera:

let(:listing) { create(:listing, :with_features) }

Esto eliminará la duplicación en sus fábricas y será más reutilizable.

https://robots.thoughtbot.com/remove-duplication-with-factorygirls-traits