¿Alguien puede decirme si estoy haciendo la configuración de manera incorrecta?
Tengo los siguientes modelos que tienen asociaciones has_many.through:
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 verificación básica de cordura de rspec rspec para la :listing
fábrica:
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 fábricas :listing_feature
y :feature
están configuradas de manera similar.
Si association :features
se comenta la línea, todas mis pruebas pasan.
Cuando es
association :features, :factory => :feature
el mensaje de error es
undefined method 'each' for #<Feature>
lo que pensé que tenía sentido para mí 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 todos y cada uno de los aportes!
Alternativamente, puede usar un bloque y omitir la
association
palabra clave. Esto hace posible construir objetos sin guardar en la base de datos (de lo contrario, una asociación has_many guardará sus registros en la base de datos, incluso si usa labuild
función en lugar decreate
).FactoryGirl.define do factory :listing_with_features, :parent => :listing do |listing| features { build_list :feature, 3 } end end
fuente
build
y locreate
convierte en el patrón más versátil. Luego use esta estrategia de compilación de FG personalizada gist.github.com/Bartuz/74ee5834a36803d712b7 parapost nested_attributes_for
probar las acciones del controlador queaccepts_nested_attributes_for
association
palabra clave usa la misma estrategia de compilación para padre e hijo. Entonces, puede construir objetos sin guardar en la base de datos.Podrías usar
trait
:FactoryGirl.define do factory :listing do ... trait :with_features do features { build_list :feature, 3 } end end end
Con
callback
, si necesita la creación de una base de datos:... trait :with_features do after(:create) do |listing| create_list(:feature, 3, listing: listing) end end
Úselo 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
fuente
Probé algunos enfoques diferentes y este es el que me funcionó de manera más confiable (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
fuente
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.
fuente