我正在尝试从Product及其关联创建Variant。如果产品具有一些关联的边,尺寸和选项,则以下代码有效,但情况并非总是如此。如果没有提供其中任何一个,则#product生成nil。
def self.create_from_product_attrs(product_id, sides, sizes, options)
sides.product(sizes, options).collect do |side, size, option|
Variant.create(product_side_id: side.id, product_size_id: size.id, product_option_id: option.id, product_id: product_id)
end
end
我也尝试过:
array = [sides, sizes, options]
array.first.product(*array[1..-1]).map(&:flatten).collect do |side, size, option|
Variant.create(product_side_id: side.id, product_size_id: size.id, product_option_id: option.id, product_id: product_id)
end
试图排除传递给#product的任何空值。
我在以下方面取得了更大的成功,但仍未通过一些测试:
array = [sides, sizes, options]
array.reject! { |c| c.empty? }
if array.empty?
Variant.create(product_id: product_id)
else
array.first.product(*array.drop(1)).map(&:flatten).collect do |side, size, option|
variant = Variant.new
variant.assign_attributes(product_side_id: side.id) if side.present?
variant.assign_attributes(product_size_id: size.id) if size.present?
variant.assign_attributes(product_option_id: option.id) if option.present?
variant.assign_attributes(product_id: product_id)
variant.save
end
end
更新以包含Rspec测试:
before do
@product_side = Fabricate(:product_side)
@product_side_2 = Fabricate(:product_side, name: '2 Sides')
@product_size = Fabricate(:product_size)
@product_size_2 = Fabricate(:product_size, name: 'A3')
end
it "should create a product variant when the product is created" do
@product = Fabricate(:product)
@product.variants.count.should == 1
end
it "should create 2 variants for a product with 2 sides" do
@product = Fabricate(:product, product_side_ids: ["#{@product_side.id}", "#{@product_side_2.id}"])
@product.variants.count.should == 2
end
it "should create 2 variants for a product with 2 sizes" do
@product = Fabricate(:product, product_size_ids: ["#{@product_size.id}", "#{@product_size_2.id}"])
@product.variants.count.should == 2
end
it "should create 2 variants for a product with 2 options" do
@product = Fabricate.build(:product)
@product_option = Fabricate(:product_option, product_id: @product.id)
@product_option_2 = Fabricate(:product_option, name: 'None', product_id: @product.id)
@product.save
@product.variants.count.should == 2
end
it "should create 4 variants for a product with 2 sides and 2 options" do
@product = Fabricate.build(:product, product_side_ids: ["#{@product_side.id}", "#{@product_side_2.id}"])
@product_option = Fabricate(:product_option, product_id: @product.id)
@product_option_2 = Fabricate(:product_option, name: 'None', product_id: @product.id)
@product.save
@product.variants.count.should == 4
end
it "should create 8 variants for a product with 2 sides and 2 options and 2 sizes" do
@product = Fabricate(:product, product_side_ids: ["#{@product_side.id}", "#{@product_side_2.id}"], product_size_ids: ["#{@product_size.id}", "#{@product_size_2.id}"])
@product_option = @product.product_options.create(name: 'Rounded', description: 'Add a round edge')
@product_option_2 = @product.product_options.create(name: 'None', description: 'Nothing')
@product.save
@product.variants.count.should == 8
end
答案 0 :(得分:0)
您要做的是为每个空集构建一个带有nil
元素的数组,并迭代这些集合。而不是分配id,只需直接分配对象(在ActiveRecord中也可以正常工作)。
def self.create_from_product_attrs(product_id, sides, sizes, options)
sides = [nil] if sides.blank?
sizes = [nil] if sizes.blank?
options = [nil] if options.blank?
sides.product(sizes, options).each do |side, size, option|
Variant.create(product_id: product_id, product_side: side, product_size: size, product_option: option)
end
end