From f2269654ff2fab7ae381e6305bfe8484c3a66aa8 Mon Sep 17 00:00:00 2001 From: Rohan Mitchell Date: Fri, 13 Dec 2013 11:07:57 +1100 Subject: [PATCH] Set option type on product when variant unit changed --- app/models/spree/product_decorator.rb | 22 +++++++ spec/models/spree/product_spec.rb | 91 +++++++++++++++++++++++++++ 2 files changed, 113 insertions(+) diff --git a/app/models/spree/product_decorator.rb b/app/models/spree/product_decorator.rb index f91c3ee41b..c52a858d7f 100644 --- a/app/models/spree/product_decorator.rb +++ b/app/models/spree/product_decorator.rb @@ -17,6 +17,7 @@ Spree::Product.class_eval do if: -> p { p.variant_unit == 'items' } after_initialize :set_available_on_to_now, :if => :new_record? + after_save :update_units # -- Joins @@ -106,4 +107,25 @@ Spree::Product.class_eval do def set_available_on_to_now self.available_on ||= Time.now end + + + def update_units + if variant_unit_changed? + option_types.delete self.class.all_variant_unit_option_types + option_types << option_type_for_variant_unit if variant_unit.present? + end + end + + def option_type_for_variant_unit + option_type_name = "unit_#{variant_unit}" + option_type_presentation = variant_unit.capitalize + + Spree::OptionType.find_by_name(option_type_name) || + Spree::OptionType.create!(name: option_type_name, presentation: option_type_presentation) + end + + def self.all_variant_unit_option_types + Spree::OptionType.where('name LIKE ?', 'unit_%%') + end + end diff --git a/spec/models/spree/product_spec.rb b/spec/models/spree/product_spec.rb index ab3d7cb0f1..f5a5015305 100644 --- a/spec/models/spree/product_spec.rb +++ b/spec/models/spree/product_spec.rb @@ -302,5 +302,96 @@ module Spree p1.should_not be_in_order_cycle oc2 end end + + describe "variant units" do + context "when the product initially has no variant unit" do + let!(:p) { create(:simple_product, + variant_unit: nil, + variant_unit_scale: nil, + variant_unit_name: nil) } + + context "when the required option type does not exist" do + it "creates the option type and assigns it to the product" do + expect { + p.update_attributes!(variant_unit: 'weight', variant_unit_scale: 1000) + }.to change(Spree::OptionType, :count).by(1) + + ot = Spree::OptionType.last + ot.name.should == 'unit_weight' + ot.presentation.should == 'Weight' + + p.option_types.should == [ot] + end + + it "does the same with volume" do + expect { + p.update_attributes!(variant_unit: 'volume', variant_unit_scale: 1000) + }.to change(Spree::OptionType, :count).by(1) + + ot = Spree::OptionType.last + ot.name.should == 'unit_volume' + ot.presentation.should == 'Volume' + + p.option_types.should == [ot] + end + + it "does the same with items" do + expect { + p.update_attributes!(variant_unit: 'items', variant_unit_name: 'packet') + }.to change(Spree::OptionType, :count).by(1) + + ot = Spree::OptionType.last + ot.name.should == 'unit_items' + ot.presentation.should == 'Items' + + p.option_types.should == [ot] + end + end + + context "when the required option type already exists" do + let!(:ot) { create(:option_type, name: 'unit_weight', presentation: 'Weight') } + + it "looks up the option type and assigns it to the product" do + expect { + p.update_attributes!(variant_unit: 'weight', variant_unit_scale: 1000) + }.to change(Spree::OptionType, :count).by(0) + + p.option_types.should == [ot] + end + end + end + + context "when the product already has a variant unit set (and all required option types exist)" do + let!(:p) { create(:simple_product, + variant_unit: 'weight', + variant_unit_scale: 1, + variant_unit_name: nil) } + + let!(:ot_volume) { create(:option_type, name: 'unit_volume', presentation: 'Volume') } + + it "removes the old option type and assigns the new one" do + p.update_attributes!(variant_unit: 'volume', variant_unit_scale: 0.001) + p.option_types.should == [ot_volume] + end + + it "removes the related option values from all its variants" + + it "leaves option type unassigned if none is provided" + + it "does not remove and re-add the option type if it is not changed" do + p.option_types.should_receive(:delete).never + p.update_attributes!(name: 'foo') + end + end + + it "finds all variant unit option types" do + ot1 = create(:option_type, name: 'unit_weight', presentation: 'Weight') + ot2 = create(:option_type, name: 'unit_volume', presentation: 'Volume') + ot3 = create(:option_type, name: 'unit_items', presentation: 'Items') + ot4 = create(:option_type, name: 'foo_unit_bar', presentation: 'Foo') + + Spree::Product.all_variant_unit_option_types.sort.should == [ot1, ot2, ot3].sort + end + end end end