accepts_nested_attributes_forとRoR Factoryの関連付けを作成するにはどうすればよいですか?
-
06-07-2019 - |
質問
Antonが指摘するように(Antonに感謝!)私の問題はテストでのアソシエーションキャッシングであり、Factoryでnested_attributeを正しく作成したようです。正しい構文は次のとおりです。
Factory.define :job do |f|
...
f.vehicles_attributes [{:vin => "1", :model => "ford", :make => "escort"},{:vin => "1", :model => "ford", :make => "escort" }]
end
ジョブモデルで accepts_nested__attributes_for
を使用していますが、ビー玉の「フィクスチャーダイビング」をほぼ失った後、ファクトリーガールに移行しようとしています。モデルを変更するたびに。
以下に一連のコードを投稿しましたが、私の質問は簡単です:
ファクトリを使用してnested_attributesを作成するにはどうすればよいですか
以下のコードを使用してジョブインスタンスを作成できますが、単体テストで車両の作成を作成できません。 f.vehicles_attributes ...
がなければ、ジョブテストは検証に失敗します。
単体テストでは次の結果が生成されます。
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
解決
すべてはアソシエーションキャッシングです。
その仕組みは次のとおりです。
1. Factory(:vehicle)
は vehicle
オブジェクトをビルドし、 job
レコードを作成します
2.その後、 vehicle.job_id
を埋めて保存します
ただし、 vehicle.job
は、ステップ1の job
オブジェクトを指しています。
したがって、必要なのは job
:
vehicle = Factory(:vehicle)
vehicle.job.reload.vehicles.size # => 2
所属していません StackOverflow