Comment créez-vous des associations RoR Factory avec includes_nested_attributes_for?
-
06-07-2019 - |
Question
Comme Anton le fait remarquer (merci Anton!), mon problème est l’association Caching dans les tests et il semble que j’ai correctement créé l’attribut nested_attribute dans l’usine. La syntaxe correcte est la suivante:
Factory.define :job do |f|
...
f.vehicles_attributes [{:vin => "1", :model => "ford", :make => "escort"},{:vin => "1", :model => "ford", :make => "escort" }]
end
J'utilise includes_nested__attributes_for
dans mon modèle Job et j'essaie de migrer vers Factory Girl après avoir failli perdre mes billes. chaque fois que je change de modèle.
J'ai posté un tas de code ci-dessous mais ma question est simple:
Comment utiliser les usines pour créer des attributs imbriqués?
Je peux créer une instance de tâche à l'aide du code ci-dessous, mais je ne peux pas créer de véhicules dans mes tests unitaires. Sans f.vehicles_attributes ...
, la validation des tests de mon travail échoue.
Mes tests unitaires produisent les résultats suivants:
test "factory" do
job = Factory(:job)
assert(job.valid?) # => true
assert(job.vehicles.first.valid?) # => true
vehicle = Factory(:vehicle)
assert(vehicle.job.vehicles.size == 1) # => true
assert_equal(vehicle.job.vehicles.first.vin, "2") # => FALSE. <"1"> expected but was <"2">
end
Factory.define :job do |f|
...
f.vehicles_attributes [:vin => "1", :model => "ford", :make => "escort" ]
end
Factory.define :vehicle do |f|
f.vin "2"
f.model "ford"
f.make "escort"
f.association :job
end
class Job < ActiveRecord::Base
has_many :vehicles, :dependent => :destroy
validate :job_must_have_at_least_one_vehicle
accepts_nested_attributes_for :vehicles, :allow_destroy => :true, :reject_if => proc { |vehicle_attributes| Job.insufficient_vehicle_input?(vehicle_attributes) }
def job_must_have_at_least_one_vehicle
errors.add(:vehicles, "need to be added") if self.vehicles.empty?
end
def self.insufficient_vehicle_input?(vehicle_attributes)
vehicle_property_keys = vehicle_attributes.keys
vehicle_property_keys.delete('_delete')
vehicle_property_keys.delete('is_operational')
vehicle_property_keys.delete('has_keys')
vehicle_property_keys.each do |attribute_to_validate|
if(!vehicle_attributes[attribute_to_validate].nil? && !vehicle_attributes[attribute_to_validate].empty?)
return false
end
end
return true
end
end
La solution
Tout est question de mise en cache des associations .
Voici comment cela fonctionne:
1. Usine (: véhicule)
crée un objet véhicule
et crée un enregistrement travail
2. Après cela, il remplit vehicle.job_job
et le sauvegarde
Mais vehicle.job
indique un objet travail
à l'étape 1.
Donc, tout ce dont vous avez besoin est de recharger travail
:
vehicle = Factory(:vehicle)
vehicle.job.reload.vehicles.size # => 2