2014-01-17 97 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