2014-01-17 98 views
0

我试图从产品及其关联创建变体。如果产品有一些相关的边,尺寸和选项,则以下代码有效,但情况并非总是如此。如果其中任何一个没有提供,那么#产品产生零。从可变数量的数组产品动态创建对象

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

'product(sizes,options)'做了什么 - 它是如何定义的? – PinnyM

+0

它产生一个组合关闭所有的数组。 它由Ruby定义。 http://www.ruby-doc.org/core-2.1.0/Array.html#method-i-product – Jack

回答

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 
+0

不幸的是,如果一个或多个关联是零,这仍然不起作用。例如,一个有2个边的产品应该返回2个变体,但返回0. – Jack

+0

@Jack - 更新来处理为任何属性集传递一个空集合(即使不是'nil')的情况。这对你有用吗? – PinnyM

+0

我现在写的6个测试中有3个通过了,我已经编辑了包含测试的问题。 – Jack