diff --git a/Gemfile b/Gemfile index 9a5588f..7a1a322 100644 --- a/Gemfile +++ b/Gemfile @@ -1,13 +1,11 @@ source 'http://rubygems.org' -gem 'spree', '~> 1.3.2' - -if RUBY_VERSION < "1.9" - gem "ruby-debug" -else - gem "ruby-debug19" +group :development, :test do + gem 'spree', github: 'spree/spree', branch: '2-1-stable' + gem 'spree_auth_devise', github: 'spree/spree_auth_devise', branch: '2-1-stable' end +=begin group :test do gem 'rspec-rails', '2.12.0' gem 'sqlite3' @@ -17,8 +15,9 @@ group :test do gem 'launchy' gem 'pry' end - group :assets do gem 'coffee-rails' end +=end + gemspec diff --git a/Rakefile b/Rakefile index 003d82f..8a8c018 100644 --- a/Rakefile +++ b/Rakefile @@ -1,46 +1,15 @@ -require 'rake' -require 'rake/testtask' -require 'rake/packagetask' -require 'rubygems/package_task' -require 'rspec/core/rake_task' -require 'spree/core/testing_support/common_rake' - -gemfile = File.expand_path('../spec/test_app/Gemfile', __FILE__) -if File.exists?(gemfile) && (%w(spec cucumber).include?(ARGV.first.to_s) || ARGV.size == 0) - require 'bundler' - ENV['BUNDLE_GEMFILE'] = gemfile - Bundler.setup - - require 'rspec' - require 'rspec/core/rake_task' - RSpec::Core::RakeTask.new -end - -desc "Default Task" -task :default => [:spec ] +require 'bundler' +Bundler::GemHelper.install_tasks -spec = eval(File.read('spree_flexi_variants.gemspec')) +require 'rspec/core/rake_task' +require 'spree/testing_support/common_rake' -Gem::PackageTask.new(spec) do |p| - p.gem_spec = spec -end +RSpec::Core::RakeTask.new -desc "Release to gemcutter" -task :release => :package do - require 'rake/gemcutter' - Rake::Gemcutter::Tasks.new(spec).define - Rake::Task['gem:push'].invoke -end +task :default => [:spec] -desc "Generates a dummy app for testing" +desc 'Generates a dummy app for testing' task :test_app do ENV['LIB_NAME'] = 'spree_flexi_variants' - Rake::Task['common:test_app'].invoke -end - -namespace :test_app do - desc 'Rebuild test database' - task :rebuild_dbs do - system("cd spec/test_app && bundle exec rake db:drop db:migrate RAILS_ENV=test") - end + Rake::Task['common:test_app'].invoke 'Spree::User' end diff --git a/app/assets/javascripts/admin/spree_flexi_variants.js b/app/assets/javascripts/admin/spree_flexi_variants.js index 2b4d67f..162b7a0 100644 --- a/app/assets/javascripts/admin/spree_flexi_variants.js +++ b/app/assets/javascripts/admin/spree_flexi_variants.js @@ -1,4 +1,4 @@ -//= require admin/spree_core +//= require spree/backend //= require jquery.formatCurrency-1.4.0.min //= require i18n/jquery.formatCurrency.all //= require_tree diff --git a/app/assets/javascripts/store/spree_flexi_variants.js b/app/assets/javascripts/store/spree_flexi_variants.js index 25f6225..db7cab8 100644 --- a/app/assets/javascripts/store/spree_flexi_variants.js +++ b/app/assets/javascripts/store/spree_flexi_variants.js @@ -1,4 +1,4 @@ -//= require store/spree_core +//= require spree/frontend //= require jquery.formatCurrency-1.4.0.min //= require i18n/jquery.formatCurrency.all //= require_self diff --git a/app/controllers/spree/admin/ad_hoc_option_values_controller.rb b/app/controllers/spree/admin/ad_hoc_option_values_controller.rb index 3153939..7420fe5 100644 --- a/app/controllers/spree/admin/ad_hoc_option_values_controller.rb +++ b/app/controllers/spree/admin/ad_hoc_option_values_controller.rb @@ -13,7 +13,9 @@ def update_positions def destroy ad_hoc_option_value = AdHocOptionValue.find(params[:id]) ad_hoc_option_value.destroy - render :text => nil + redirect_to edit_admin_product_ad_hoc_option_type_path( + ad_hoc_option_value.ad_hoc_option_type.product_id, + ad_hoc_option_value.ad_hoc_option_type_id) end end end diff --git a/app/controllers/spree/admin/ad_hoc_variant_exclusions_controller.rb b/app/controllers/spree/admin/ad_hoc_variant_exclusions_controller.rb index 9cf4bf7..8cd339c 100644 --- a/app/controllers/spree/admin/ad_hoc_variant_exclusions_controller.rb +++ b/app/controllers/spree/admin/ad_hoc_variant_exclusions_controller.rb @@ -16,7 +16,7 @@ def create ave.product=@product ave.save - redirect_to admin_product_ad_hoc_variant_exclusions_url(@product) + redirect_to admin_product_ad_hoc_variant_exclusions_path(@product) end # TODO how is this different than the default 'destroy'. maybe I don't need this method @@ -24,7 +24,7 @@ def remove @product=@ad_hoc_variant_exclusion.product @ad_hoc_variant_exclusion.destroy flash.notice = I18n.t("notice_messages.ad_hoc_variant_exclusion_removed") - redirect_to admin_product_ad_hoc_variant_exclusions_url(@product) + redirect_to admin_product_ad_hoc_variant_exclusions_path(@product) end protected diff --git a/app/controllers/spree/orders_controller_decorator.rb b/app/controllers/spree/orders_controller_decorator.rb index 3f3df43..c9e187b 100644 --- a/app/controllers/spree/orders_controller_decorator.rb +++ b/app/controllers/spree/orders_controller_decorator.rb @@ -9,25 +9,20 @@ module Spree # Currently, we are assuming the inbound ad_hoc_option_values and customizations apply to the entire inbound product/variant 'group', as more surgery # needs to occur in the cart partial for this to be done 'right' # + # Adds a new item to the order (creating a new order if none already exists) def populate - @order = current_order(true) + populator = Spree::OrderPopulator.new(current_order(create_order_if_necessary: true), current_currency) - params[:products].each do |product_id,variant_id| - quantity = params[:quantity].to_i if !params[:quantity].is_a?(Hash) - quantity = params[:quantity][variant_id].to_i if params[:quantity].is_a?(Hash) - @order.add_variant(Variant.find(variant_id), quantity, ad_hoc_option_value_ids, product_customizations) if quantity > 0 - end if params[:products] + if populator.populate(params[:variant_id], params[:quantity], ad_hoc_option_value_ids, product_customizations) + current_order.ensure_updated_shipments - params[:variants].each do |variant_id, quantity| - quantity = quantity.to_i - @order.add_variant(Variant.find(variant_id), quantity, ad_hoc_option_value_ids, product_customizations) if quantity > 0 - end if params[:variants] - - fire_event('spree.cart.add') - fire_event('spree.order.contents_changed') - - redirect_to cart_path if request.format.html? + respond_with(@order) do |format| + format.html { redirect_to cart_path } + end + else + flash[:error] = populator.errors.full_messages.join(" ") + redirect_to :back + end end - end end diff --git a/app/helpers/spree/admin/base_helper_decorator.rb b/app/helpers/spree/admin/base_helper_decorator.rb index c0ad053..e69de29 100644 --- a/app/helpers/spree/admin/base_helper_decorator.rb +++ b/app/helpers/spree/admin/base_helper_decorator.rb @@ -1,15 +0,0 @@ -module Spree - module Admin - BaseHelper.module_eval do - #renders hidden field and link to remove record using nested_attributes - def link_to_remove_nested_fields(name, f, options = {}) - name = '' if options[:no_text] - options[:class] = '' unless options[:class] - options[:class] += 'no-text with-tip' if options[:no_text] - options[:nest] = '' unless options[:nest] - url = f.object.persisted? ? [:admin, options[:nest], f.object] : '#' - link_to_with_icon('icon-trash', name, url, :class => "remove_fields #{options[:class]}", :data => {:action => 'remove'}, :title => t(:remove)) + f.hidden_field(:_destroy) - end - end - end -end \ No newline at end of file diff --git a/app/models/spree/ad_hoc_option_type.rb b/app/models/spree/ad_hoc_option_type.rb index e277bd3..086dcae 100644 --- a/app/models/spree/ad_hoc_option_type.rb +++ b/app/models/spree/ad_hoc_option_type.rb @@ -8,7 +8,7 @@ class AdHocOptionType < ActiveRecord::Base accepts_nested_attributes_for :ad_hoc_option_values, :allow_destroy => true # currently no controller for normal users present - attr_accessible :is_required, :ad_hoc_option_values_attributes, :product_id, :option_type_id, :position + #attr_accessible :is_required, :ad_hoc_option_values_attributes, :product_id, :option_type_id, :position default_scope order(:position) diff --git a/app/models/spree/ad_hoc_option_value.rb b/app/models/spree/ad_hoc_option_value.rb index 4720d40..0428444 100644 --- a/app/models/spree/ad_hoc_option_value.rb +++ b/app/models/spree/ad_hoc_option_value.rb @@ -6,7 +6,7 @@ class AdHocOptionValue < ActiveRecord::Base has_many :excluded_ad_hoc_option_values, :dependent => :destroy # currently no controller for normal users present - attr_accessible :price_modifier, :ad_hoc_option_type_id, :option_value_id, :selected, :cost_price_modifier + #attr_accessible :price_modifier, :ad_hoc_option_type_id, :option_value_id, :selected, :cost_price_modifier # this opens up a can of worms..deleting option values and having historical data still intact...ugh...what to do?...add 'deleted_at' somewhere along the chain? # has_many :ad_hoc_option_values_line_items, :dependent => :destroy diff --git a/app/models/spree/calculator/amount_times_constant.rb b/app/models/spree/calculator/amount_times_constant.rb index caf2d28..aa8efcb 100644 --- a/app/models/spree/calculator/amount_times_constant.rb +++ b/app/models/spree/calculator/amount_times_constant.rb @@ -5,7 +5,7 @@ class Calculator::AmountTimesConstant < Calculator preference :min_amount, :integer, :default=>0 preference :max_amount, :integer, :default=>100 - attr_accessible :preferred_multiplier, :preferred_min_amount, :preferred_max_amount + #attr_accessible :preferred_multiplier, :preferred_min_amount, :preferred_max_amount def self.description "Amount Times Constant Calculator" diff --git a/app/models/spree/calculator/customization_image.rb b/app/models/spree/calculator/customization_image.rb index 4525879..9c95df2 100644 --- a/app/models/spree/calculator/customization_image.rb +++ b/app/models/spree/calculator/customization_image.rb @@ -1,7 +1,9 @@ +require_dependency 'spree/calculator' + module Spree class Calculator::CustomizationImage < Calculator preference :price, :decimal - attr_accessible :preferred_price, :decimal + #attr_accessible :preferred_price, :decimal def self.description "Product Customization Image Calculator" diff --git a/app/models/spree/calculator/engraving.rb b/app/models/spree/calculator/engraving.rb index 61b63da..d62067e 100644 --- a/app/models/spree/calculator/engraving.rb +++ b/app/models/spree/calculator/engraving.rb @@ -1,7 +1,9 @@ +require_dependency 'spree/calculator' + module Spree class Calculator::Engraving < Calculator preference :price_per_letter, :decimal - attr_accessible :preferred_price_per_letter + #attr_accessible :preferred_price_per_letter def self.description "Engraving Calculator" @@ -24,7 +26,7 @@ def compute(product_customization, variant=nil) # expecting only one CustomizedProductOption opt = product_customization.customized_product_options.detect {|cpo| cpo.customizable_product_option.name == "inscription" } rescue '' - opt.value.length * preferred_price_per_letter + opt.value.length * (preferred_price_per_letter || 0) end def valid_configuration?(product_customization) diff --git a/app/models/spree/calculator/no_charge.rb b/app/models/spree/calculator/no_charge.rb new file mode 100644 index 0000000..d5f5ae6 --- /dev/null +++ b/app/models/spree/calculator/no_charge.rb @@ -0,0 +1,28 @@ +require_dependency 'spree/calculator' + +module Spree + class Calculator::NoCharge < Calculator + def self.description + "This customization has no charge" + end + + def self.register + super + ProductCustomizationType.register_calculator(self) + end + + def create_options + # This calculator knows that it needs one CustomizableOption named amount + [ + ] + end + + def compute(product_customization, variant=nil) + return 0 + end + + def valid_configuration?(product_customization) + true + end + end +end diff --git a/app/models/spree/calculator/product_area.rb b/app/models/spree/calculator/product_area.rb index 657f49e..09ce075 100644 --- a/app/models/spree/calculator/product_area.rb +++ b/app/models/spree/calculator/product_area.rb @@ -10,7 +10,7 @@ class Calculator::ProductArea < Calculator preference :min_height, :integer, :default => 0 preference :max_height, :integer, :default => 100 - attr_accessible :preferred_multiplier, :preferred_min_pricing_area, :preferred_min_width, :preferred_max_width,:preferred_min_height, :preferred_max_height + #attr_accessible :preferred_multiplier, :preferred_min_pricing_area, :preferred_min_width, :preferred_max_width,:preferred_min_height, :preferred_max_height # preference :min_area, :integer # the minimum sized frame we'll sell diff --git a/app/models/spree/customizable_product_option.rb b/app/models/spree/customizable_product_option.rb index 039cef1..ee98c39 100644 --- a/app/models/spree/customizable_product_option.rb +++ b/app/models/spree/customizable_product_option.rb @@ -2,6 +2,6 @@ module Spree class CustomizableProductOption < ActiveRecord::Base belongs_to :product_customization_type delegate :calculator, :to => :product_customization_type - attr_accessible :name, :presentation, :description, :product_customization_type_id + #attr_accessible :name, :presentation, :description, :product_customization_type_id end end diff --git a/app/models/spree/excluded_ad_hoc_option_value.rb b/app/models/spree/excluded_ad_hoc_option_value.rb index 46259d4..f150bf7 100644 --- a/app/models/spree/excluded_ad_hoc_option_value.rb +++ b/app/models/spree/excluded_ad_hoc_option_value.rb @@ -3,6 +3,6 @@ class ExcludedAdHocOptionValue < ActiveRecord::Base belongs_to :ad_hoc_variant_exclusion belongs_to :ad_hoc_option_value - attr_accessible :ad_hoc_variant_exclusion, :ad_hoc_option_value_id + #attr_accessible :ad_hoc_variant_exclusion, :ad_hoc_option_value_id end end diff --git a/app/models/spree/line_item_decorator.rb b/app/models/spree/line_item_decorator.rb index ace9380..e28a8a8 100644 --- a/app/models/spree/line_item_decorator.rb +++ b/app/models/spree/line_item_decorator.rb @@ -34,7 +34,7 @@ def options_text end def cost_price - variant.cost_price + ad_hoc_option_values.map(&:cost_price).inject(0, :+) + (variant.cost_price || 0) + ad_hoc_option_values.map(&:cost_price).inject(0, :+) end def cost_money diff --git a/app/models/spree/order_contents_decorator.rb b/app/models/spree/order_contents_decorator.rb new file mode 100644 index 0000000..9086cbb --- /dev/null +++ b/app/models/spree/order_contents_decorator.rb @@ -0,0 +1,63 @@ +module Spree + OrderContents.class_eval do + # Get current line item for variant if exists + # Add variant qty to line_item + def add(variant, quantity = 1, currency = nil, shipment = nil, ad_hoc_option_value_ids = [], product_customizations = []) + line_item = add_to_line_item(variant, quantity, currency, shipment, ad_hoc_option_value_ids, product_customizations) + reload_totals + PromotionHandler::Cart.new(order, line_item).activate + ItemAdjustments.new(line_item).update + reload_totals + line_item + end + + private + def add_to_line_item(variant, quantity, currency=nil, shipment=nil, ad_hoc_option_value_ids = [], product_customizations = []) + line_item = grab_line_item_by_variant(variant, false, ad_hoc_option_value_ids, product_customizations) + + if line_item + line_item.target_shipment = shipment + line_item.quantity += quantity.to_i + line_item.currency = currency unless currency.nil? + else + line_item = order.line_items.new(quantity: quantity, variant: variant) + line_item.target_shipment = shipment + + line_item.product_customizations = product_customizations + product_customizations.each {|pc| pc.line_item = line_item} + + product_customizations.map(&:save) # it is now safe to save the customizations we built + + # find, and add the configurations, if any. these have not been fetched from the db yet. line_items.first.variant_id + # we postponed it (performance reasons) until we actaully knew we needed them + povs=[] + ad_hoc_option_value_ids.each do |cid| + povs << AdHocOptionValue.find(cid) + end + line_item.ad_hoc_option_values = povs + + offset_price = povs.map(&:price_modifier).compact.sum + product_customizations.map {|pc| pc.price(variant)}.sum + + if currency + line_item.currency = currency unless currency.nil? + line_item.price = variant.price_in(currency).amount + offset_price + else + line_item.price = variant.price + offset_price + end + end + + line_item.save + line_item + end + + def grab_line_item_by_variant(variant, raise_error = false, ad_hoc_option_value_ids = [], product_customizations = []) + line_item = order.find_line_item_by_variant(variant, ad_hoc_option_value_ids, product_customizations) + + if !line_item.present? && raise_error + raise ActiveRecord::RecordNotFound, "Line item not found for variant #{variant.sku}" + end + + line_item + end + end +end diff --git a/app/models/spree/order_decorator.rb b/app/models/spree/order_decorator.rb index 8d86490..08b5567 100644 --- a/app/models/spree/order_decorator.rb +++ b/app/models/spree/order_decorator.rb @@ -1,7 +1,7 @@ module Spree Order.class_eval do def add_variant(variant, quantity = 1, ad_hoc_option_value_ids=[], product_customizations=[]) - current_item = contains?(variant, ad_hoc_option_value_ids, product_customizations) + current_item = find_line_item_by_variant(variant, ad_hoc_option_value_ids, product_customizations) if current_item current_item.quantity += quantity current_item.save @@ -30,6 +30,10 @@ def add_variant(variant, quantity = 1, ad_hoc_option_value_ids=[], product_custo end def contains?(variant, ad_hoc_option_value_ids, product_customizations) + find_line_item_by_variant(variant, ad_hoc_option_value_ids, product_customizations).present? + end + + def find_line_item_by_variant(variant, ad_hoc_option_value_ids, product_customizations) line_items.detect do |li| li.variant_id == variant.id && matching_configurations(li.ad_hoc_option_values,ad_hoc_option_value_ids) && @@ -37,10 +41,15 @@ def contains?(variant, ad_hoc_option_value_ids, product_customizations) end end - def merge!(order) + def merge!(order, user = nil) order.line_items.each do |line_item| self.add_variant(line_item.variant, line_item.quantity, line_item.ad_hoc_option_value_ids, line_item.product_customizations) end + + self.associate_user!(user) if !self.user && !user.blank? + + # So that the destroy doesn't take out line items which may have been re-assigned + order.line_items.reload order.destroy end diff --git a/app/models/spree/order_populator_decorator.rb b/app/models/spree/order_populator_decorator.rb new file mode 100644 index 0000000..98d43a3 --- /dev/null +++ b/app/models/spree/order_populator_decorator.rb @@ -0,0 +1,30 @@ +module Spree + OrderPopulator.class_eval do + + def populate(variant_id, quantity, ad_hoc_option_value_ids = [], product_customizations = []) + attempt_cart_add(variant_id, quantity, ad_hoc_option_value_ids, product_customizations) + valid? + end + + private + + def attempt_cart_add(variant_id, quantity, ad_hoc_option_value_ids, product_customizations) + quantity = quantity.to_i + # 2,147,483,647 is crazy. + # See issue #2695. + if quantity > 2_147_483_647 + errors.add(:base, Spree.t(:please_enter_reasonable_quantity, :scope => :order_populator)) + return false + end + + variant = Spree::Variant.find(variant_id) + if quantity > 0 + line_item = @order.contents.add(variant, quantity, currency, nil, ad_hoc_option_value_ids, product_customizations) + unless line_item.valid? + errors.add(:base, line_item.errors.messages.values.join(" ")) + return false + end + end + end + end +end diff --git a/app/models/spree/product_customization.rb b/app/models/spree/product_customization.rb index 77cbbfe..a88ee40 100644 --- a/app/models/spree/product_customization.rb +++ b/app/models/spree/product_customization.rb @@ -3,7 +3,7 @@ class ProductCustomization < ActiveRecord::Base belongs_to :product_customization_type belongs_to :line_item has_many :customized_product_options, :dependent => :destroy - attr_accessible :product_customization_type_id, :line_item_id + #attr_accessible :product_customization_type_id, :line_item_id # TODO: Jeff, add 'required' # price might depend on something contained in the variant (like product property value)a diff --git a/app/models/spree/product_customization_type.rb b/app/models/spree/product_customization_type.rb index c81b4c2..48d02c3 100644 --- a/app/models/spree/product_customization_type.rb +++ b/app/models/spree/product_customization_type.rb @@ -1,9 +1,9 @@ module Spree class ProductCustomizationType < ActiveRecord::Base - calculated_adjustments # does this just need to be changed to has_one :calculator? + include Spree::Core::CalculatedAdjustments has_and_belongs_to_many :products has_many :customizable_product_options, :dependent => :destroy accepts_nested_attributes_for :customizable_product_options, :allow_destroy => true - attr_accessible :name, :presentation, :description, :customizable_product_options_attributes + #attr_accessible :name, :presentation, :description, :customizable_product_options_attributes end end diff --git a/app/models/spree/product_decorator.rb b/app/models/spree/product_decorator.rb index 3acb838..0732df7 100644 --- a/app/models/spree/product_decorator.rb +++ b/app/models/spree/product_decorator.rb @@ -9,6 +9,11 @@ module Spree # allowed customizations has_and_belongs_to_many :product_customization_types + make_permalink field: :slug + + def permalink + slug + end private diff --git a/app/overrides/add_ad_hoc_option_types_to_cart_form.rb b/app/overrides/add_ad_hoc_option_types_to_cart_form.rb index caa99af..e3ebda3 100644 --- a/app/overrides/add_ad_hoc_option_types_to_cart_form.rb +++ b/app/overrides/add_ad_hoc_option_types_to_cart_form.rb @@ -1,4 +1,4 @@ Deface::Override.new(:virtual_path => "spree/products/_cart_form", :name => "converted_product_price_733808074", - :insert_after => "[data-hook='product_price'], #product_price[data-hook]", + :insert_before => "[data-hook='product_price'], #product_price[data-hook]", :partial => "spree/products/ad_hoc_option_types") diff --git a/app/overrides/add_customizations_to_cart_form.rb b/app/overrides/add_customizations_to_cart_form.rb index 6fc675c..0a07074 100644 --- a/app/overrides/add_customizations_to_cart_form.rb +++ b/app/overrides/add_customizations_to_cart_form.rb @@ -1,4 +1,4 @@ Deface::Override.new(:virtual_path => "spree/products/_cart_form", :name => "converted_product_price_290656527", - :insert_after => "[data-hook='product_price'], #product_price[data-hook]", + :insert_before => "[data-hook='product_price'], #product_price[data-hook]", :partial => "spree/products/customizations") diff --git a/app/overrides/fix_cart_form_columnization.rb b/app/overrides/fix_cart_form_columnization.rb new file mode 100644 index 0000000..25c8f93 --- /dev/null +++ b/app/overrides/fix_cart_form_columnization.rb @@ -0,0 +1,4 @@ +Deface::Override.new(:virtual_path => "spree/products/_cart_form", + :name => "fix_cart_form_columnization_remove_column_classes", + :remove_from_attributes => '#product-variants, [data-hook=product_price]', + :attributes => {:class => 'columns'}) \ No newline at end of file diff --git a/app/views/spree/admin/ad_hoc_option_types/_option_value_fields.html.erb b/app/views/spree/admin/ad_hoc_option_types/_option_value_fields.html.erb index c0c4308..8ba37c6 100644 --- a/app/views/spree/admin/ad_hoc_option_types/_option_value_fields.html.erb +++ b/app/views/spree/admin/ad_hoc_option_types/_option_value_fields.html.erb @@ -4,5 +4,15 @@
<%= product_customization_type.description %>
- <% end %> - - <% param_prefix = "product_customizations[#{product_customization_type.id}]" %> -<%= option.customizable_product_option.presentation %> = <%= option.value %>
+ <%= option.customizable_product_option.presentation %> = <%= option.value %> <% end %> <% end %> diff --git a/config/routes.rb b/config/routes.rb index 1953e94..35eed6c 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,7 +1,7 @@ -Spree::Core::Engine.routes.prepend do - match 'product_customizations/price', :to => 'product_customizations#price' +Spree::Core::Engine.add_routes do + match 'product_customizations/price', :to => 'product_customizations#price', :via => [:get, :post] - match 'customize/:product_id', :to => 'products#customize', :as => 'customize' + match 'customize/:product_id', :to => 'products#customize', :as => 'customize', :via => [:get, :post] namespace :admin do @@ -77,5 +77,5 @@ end # namespace :admin - match 'admin/variant_configurations/:variant_id', :to => 'admin/variant_configurations#configure' + match 'admin/variant_configurations/:variant_id', :to => 'admin/variant_configurations#configure', :via => [:get, :post] end diff --git a/db/migrate/20131018202202_rename_product_customization_types_products_to_spree_namespace.rb b/db/migrate/20131018202202_rename_product_customization_types_products_to_spree_namespace.rb new file mode 100644 index 0000000..22c487b --- /dev/null +++ b/db/migrate/20131018202202_rename_product_customization_types_products_to_spree_namespace.rb @@ -0,0 +1,5 @@ +class RenameProductCustomizationTypesProductsToSpreeNamespace < ActiveRecord::Migration + def change + rename_table :product_customization_types_products, :spree_product_customization_types_products + end +end diff --git a/lib/spree_flexi_variants/engine.rb b/lib/spree_flexi_variants/engine.rb index 55b7000..14d7cff 100644 --- a/lib/spree_flexi_variants/engine.rb +++ b/lib/spree_flexi_variants/engine.rb @@ -28,20 +28,16 @@ def self.activate initializer "spree.flexi_variants.assets.precompile" do |app| app.config.assets.precompile += ['store/spree_flexi_variants_exclusions.js','admin/orders/flexi_configuration.js','store/spree-flexi-variants.*'] end - # Had a good reason for this rescue below, and wish I'd commented it better when I wrote it - # TODO - figure this out and de-ugly - begin - initializer "spree.register.calculators" do |app| - app.config.spree.calculators.add_class('product_customization_types') - app.config.spree.calculators.product_customization_types = [ + + initializer "spree.flexi_variants.register.calculators" do |app| + app.config.spree.calculators.add_class('product_customization_types') unless app.config.spree.calculators.respond_to?(:product_customization_types) + app.config.spree.calculators.product_customization_types += [ Spree::Calculator::Engraving, Spree::Calculator::AmountTimesConstant, Spree::Calculator::ProductArea, - Spree::Calculator::CustomizationImage + Spree::Calculator::CustomizationImage, + Spree::Calculator::NoCharge ] - end - rescue => problem - puts "intentionally ignoring problem in calculator registration #{problem}" end end end diff --git a/lib/spree_flexi_variants/factories.rb b/lib/spree_flexi_variants/factories.rb new file mode 100644 index 0000000..892e161 --- /dev/null +++ b/lib/spree_flexi_variants/factories.rb @@ -0,0 +1,76 @@ +FactoryGirl.define do + factory :no_charge_calculator, :class => Spree::Calculator::NoCharge do + end +end + +FactoryGirl.define do + factory :product_customization_type, :class => Spree::ProductCustomizationType do + sequence(:name) { |n| "Product Customization Type ##{n} - #{Kernel.rand(9999)}" } + sequence(:presentation) { |n| "Product Customization Type Presentation ##{n} - #{Kernel.rand(9999)}" } + + calculator { |p| p.association(:no_charge_calculator) } + end +end + +FactoryGirl.define do + factory :product_customization, :class => Spree::ProductCustomization do + product_customization_type { |p| p.association(:product_customization_type) } + line_item { |p| p.association(:line_item) } + end +end + +FactoryGirl.define do + factory :customizable_product_option, :class => Spree::CustomizableProductOption do + sequence(:name) { |n| "Customizable Product Option ##{n} - #{Kernel.rand(9999)}" } + sequence(:presentation) { |n| "Customizable Product Option Presentation ##{n} - #{Kernel.rand(9999)}" } + sequence(:description) { |n| "Customizable Product Option Description ##{n} - #{Kernel.rand(9999)}" } + + product_customization_type { |p| p.association(:product_customization_type) } + + end +end + +FactoryGirl.define do + factory :customized_product_option, :class => Spree::CustomizedProductOption do + product_customization { |p| p.association(:product_customization) } + customizable_product_option { |p| p.association(:customizable_product_option) } + sequence(:value) { |n| "Customizaed Product Option Value ##{n} - #{Kernel.rand(9999)}" } + end +end + +FactoryGirl.define do + factory :ad_hoc_option_type, :class => Spree::AdHocOptionType do + product { |p| p.association(:product) } + option_type { |p| p.association(:option_type) } + end +end + + +FactoryGirl.define do + factory :ad_hoc_option_value, :class => Spree::AdHocOptionValue do + ad_hoc_option_type { |p| p.association(:ad_hoc_option_type) } + option_value { |p| p.association(:option_value) } + end +end + +FactoryGirl.define do + factory :customizable_product, :parent => :base_product do + after(:create) do |p| + p.product_customization_types << FactoryGirl.create(:product_customization_type) + end + end +end + +FactoryGirl.define do + factory :ad_hoc_variant_exclusion, :class => Spree::AdHocVariantExclusion do + product { |p| p.association(:product) } + end +end + +FactoryGirl.define do + factory :excluded_ad_hoc_option_value, :class => Spree::ExcludedAdHocOptionValue do + ad_hoc_variant_exclusion { |p| p.association(:ad_hoc_variant_exclusion) } + ad_hoc_option_value { |p| p.association(:ad_hoc_option_value) } + end +end + diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index ffc8d79..30f515d 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -1,38 +1,34 @@ +require 'coveralls' +Coveralls.wear! + # Configure Rails Environment ENV['RAILS_ENV'] = 'test' require File.expand_path('../dummy/config/environment.rb', __FILE__) require 'rspec/rails' - +require 'database_cleaner' +require 'factory_girl' +FactoryGirl.find_definitions require 'ffaker' - -#include spree's factories -require 'spree_core' - -# need this b/c of controllers/spree/admin/users_controller. -# it has a reference to User::DestroyWithOrdersError, and we only have a spree_core dependency in our gemspec. This smells...must bring this up on spree group -#class Spree::User::DestroyWithOrdersError < StandardError; end -#require 'spree_core/testing_support/factories' - -# include local factories -Dir["#{File.dirname(__FILE__)}/factories/**/*.rb"].each do |f| - fp = File.expand_path(f) - require fp -end +require 'shoulda-matchers' # Requires supporting ruby files with custom matchers and macros, etc, # in spec/support/ and its subdirectories. Dir[File.join(File.dirname(__FILE__), 'support/**/*.rb')].each { |f| require f } # Requires factories defined in spree_core -require 'spree/core/testing_support/factories' -require 'spree/core/testing_support/authorization_helpers' +require 'spree/testing_support/factories' +require 'spree/testing_support/authorization_helpers' +require 'spree/testing_support/capybara_ext' +require 'spree/testing_support/controller_requests' +require 'spree/testing_support/url_helpers' -require 'spree/core/url_helpers' +require 'spree_flexi_variants/factories' RSpec.configure do |config| config.include FactoryGirl::Syntax::Methods + config.include IntegrationHelpers # == URL Helpers # @@ -40,24 +36,32 @@ # # visit spree.admin_path # current_path.should eql(spree.products_path) - config.include Spree::Core::UrlHelpers - - # == Mock Framework - # - # If you prefer to use mocha, flexmock or RR, uncomment the appropriate line: - # - # config.mock_with :mocha - # config.mock_with :flexmock - # config.mock_with :rr - config.mock_with :rspec + config.include Spree::TestingSupport::UrlHelpers + config.include Spree::TestingSupport::ControllerRequests + + # Capybara javascript drivers require transactional fixtures set to false, and we use DatabaseCleaner + # to cleanup after each test instead. Without transactional fixtures set to false the records created + # to setup a test will be unavailable to the browser, which runs under a seperate server instance. + config.use_transactional_fixtures = false + + # Ensure Suite is set to use transactions for speed. + config.before :suite do + DatabaseCleaner.strategy = :transaction + DatabaseCleaner.clean_with :truncation + end - # Remove this line if you're not using ActiveRecord or ActiveRecord fixtures - config.fixture_path = "#{::Rails.root}/spec/fixtures" + # Before each spec check if it is a Javascript test and switch between using database transactions or not where necessary. + config.before :each do + DatabaseCleaner.strategy = example.metadata[:js] ? :truncation : :transaction + DatabaseCleaner.start + # Set some configuration defaults. + ActionMailer::Base.default_url_options[:host] = 'localhost' + end - # If you're not using ActiveRecord, or you'd prefer not to run each of your - # examples within a transaction, remove the following line or assign false - # instead of true. - config.use_transactional_fixtures = true + # After each spec clean the database. + config.after :each do + DatabaseCleaner.clean + end # If true, the base class of anonymous controllers will be inferred # automatically. This will be the default behavior in future versions of @@ -68,19 +72,6 @@ # order dependency and want to debug it, you can fix the order by providing # the seed, which is printed after each run. # --seed 1234 - config.order = "random" -end - -# from http://blog.plataformatec.com.br/2011/12/three-tips-to-improve-the-performance-of-your-test-suite/ -class ActiveRecord::Base - mattr_accessor :shared_connection - @@shared_connection = nil - - def self.connection - @@shared_connection || retrieve_connection - end + # config.order = "random" + config.color = true end - -# Forces all threads to share the same connection. This works on -# Capybara because it starts the web server in a thread. -ActiveRecord::Base.shared_connection = ActiveRecord::Base.connection diff --git a/spec/support/integration_helpers.rb b/spec/support/integration_helpers.rb new file mode 100644 index 0000000..a420aec --- /dev/null +++ b/spec/support/integration_helpers.rb @@ -0,0 +1,15 @@ +module IntegrationHelpers + + def login_user(user = nil, options = {}) + options[:password] ||= 'secret' + user ||= create(:user) + + visit spree.root_path + click_link 'Login' + fill_in 'spree_user[email]', with: user.email + fill_in 'spree_user[password]', with: options[:password] + click_button 'Login' + page.should_not have_content 'Login' + end + +end diff --git a/spree_flexi_variants.gemspec b/spree_flexi_variants.gemspec index 2f4cf7d..be5dc95 100644 --- a/spree_flexi_variants.gemspec +++ b/spree_flexi_variants.gemspec @@ -1,10 +1,10 @@ Gem::Specification.new do |s| s.platform = Gem::Platform::RUBY s.name = 'spree_flexi_variants' - s.version = '1.0.0' + s.version = '2.1.0' s.summary = 'Add gem summary here' #s.description = 'Add (optional) gem description here' - s.required_ruby_version = '>= 1.8.7' + s.required_ruby_version = '>= 1.9.3' s.author = 'Jeff Squires' s.email = 'jeff.squires@gmail.com' @@ -18,5 +18,20 @@ Gem::Specification.new do |s| s.add_dependency('carrierwave') s.add_dependency('mini_magick') - s.add_dependency 'spree_core', '~> 1.3' -end + s.add_dependency 'spree', '>= 2.1' + + s.add_development_dependency 'capybara', '~> 2.1' + s.add_development_dependency 'coffee-rails' + s.add_development_dependency 'coveralls' + s.add_development_dependency 'database_cleaner', '~> 1.0.1' + s.add_development_dependency 'factory_girl_rails', '~> 4.2' + s.add_development_dependency 'ffaker' + s.add_development_dependency 'rspec-rails', '~> 2.13' + s.add_development_dependency 'sass-rails' + s.add_development_dependency 'selenium-webdriver' + s.add_development_dependency 'shoulda-matchers' + s.add_development_dependency 'spree_auth_devise' + + s.add_development_dependency 'sqlite3' + +end \ No newline at end of file