diff --git a/.gitignore b/.gitignore
index 1ffd740..428eeb0 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1 +1,9 @@
+\#*
+*~
+.#*
+.DS_Store
+.idea
+.project
+tmp
nbproject
+*.swp
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..5800638
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,23 @@
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+ * Neither the name of the Rails Dog LLC nor the names of its
+ contributors may be used to endorse or promote products derived from this
+ software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
\ No newline at end of file
diff --git a/README.markdown b/README.markdown
deleted file mode 100755
index 49eba67..0000000
--- a/README.markdown
+++ /dev/null
@@ -1,117 +0,0 @@
-# Enchanced Option Types
-
-## Description
-
-This extension enchances spree functionality when handling products with
-numerous and complex variants.
-
-Following enchancements are provided:
-
-* Admin side:
- * Selecting order of option types for prototype with drag & drop
- * Optional "modifiers" for option values that can modify price of variant
- * Option to generate set of variants from prototype with option types.
- When option is selected during product creation, variants are created for
- each combination of option values (eg. Sizes: [S,M,L], Colors: [Red, Blue]
- will generate 6 variants), with prices calculated from sum of product base price
- and amount of option_value modifiers.
- * Option to regenerate variants when needed.
- * Option to calculate variant price when creating new variant based on product
- price and sum of modifiers from option values.
-* Client side variant selection:
- * using x select boxes (1 for each option_type)
- * using x sets of radio boxes grouped in fieldsets (one fieldset for each option type)
- * using 2d table of radio boxes (only when there are only 2 option types!)
-* Javascript helpers:
- * Instant updating of price based on variant selected using above methods
- * Instand updating of number of on_hand units
- * enabling/disabling options that don't have corresponding variant.
- * products.js override (edge spree only) for working with variant images
-
-Some of the functionality might not work without javascript, but much work was put
-to make JS as unintrusive as possible, so It should be fairly easy excercise
-to make it completelly JS independent.
-
-## Credits
-
-Created by Marcin Raczkowski (marcin.raczkowski@gmail.com)
-
-2d table was inspired by Stephanie Powell [post](
-http://blog.endpoint.com/2009/12/rails-ecommerce-product-optioning-in.html)
-You can(and should!) read it.
-
-## Examples
-
-
-
-
-
-On first example you can see sets of radio boxes and modifiers in action,
-also notable is separation of base price and current(variant) price, only second one is updatable.
-
-Second one shows selects - it's much more compact then previous example,
- but doesn't instantly show all options.
-
-Thrid shows the 2d table for variant choosing.
-
-## Instalation
-
-For git users:
-git submodule add git://github.com/swistak/spree-enchanced-option-types.git vendor/extensions/enchanced_option_types
-
-for others (or git users that don't like submodules):
-ruby script/extension install git://github.com/swistak/spree-enchanced-option-types.git
-
-## Customization
-
-User interface change is limited only to _cart_form partial from original spree.
-it was separated into several subfiles to make customization and embeding in custom layouts easier.
-
-There are no inline styles (except for 2d table, that absolutelly requires
-some wire frame styles to look sane), you can either use provided _cart_form
-partial as a replacement for generic spree partial, or you can roll your own and
-only include one of variant choosing partials.
-
-There are some special css classes you might be interested in:
-.price.update - price field that should be updated with new price value if variant changes.
-span.
-
-Source is extensivelly documented and I recomend reading it.
-
-## Limitations
-
-- currently there's no way to change order of option types AFTER product is created
-
-## TODO
-
-- gracefull handling non-js users.
-- test under other browsers then FF
-
-## License
-
-Copyright (c) 2009, Marcin Raczkowski
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without modification,
-are permitted provided that the following conditions are met:
-
- * Redistributions of source code must retain the above copyright notice,
- this list of conditions and the following disclaimer.
- * Redistributions in binary form must reproduce the above copyright notice,
- this list of conditions and the following disclaimer in the documentation
- and/or other materials provided with the distribution.
- * Neither the name of the Marcin Raczkowski nor the names of its
- contributors may be used to endorse or promote products derived from this
- software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
-CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
-EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
-PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
-PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
-LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
-NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
\ No newline at end of file
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..0e42e3c
--- /dev/null
+++ b/README.md
@@ -0,0 +1,13 @@
+EnhancedOptionTypes
+===================
+
+Introduction goes here.
+
+
+Example
+=======
+
+Example goes here.
+
+
+Copyright (c) 2010 [name of extension creator], released under the New BSD License
diff --git a/Rakefile b/Rakefile
old mode 100755
new mode 100644
index fba0e9b..70cbc68
--- a/Rakefile
+++ b/Rakefile
@@ -1,120 +1,29 @@
-# I think this is the one that should be moved to the extension Rakefile template
-
-# In rails 1.2, plugins aren't available in the path until they're loaded.
-# Check to see if the rspec plugin is installed first and require
-# it if it is. If not, use the gem version.
-
-# Determine where the RSpec plugin is by loading the boot
-unless defined? SPREE_ROOT
- ENV["RAILS_ENV"] = "test"
- case
- when ENV["SPREE_ENV_FILE"]
- require File.dirname(ENV["SPREE_ENV_FILE"]) + "/boot"
- when File.dirname(__FILE__) =~ %r{vendor/SPREE/vendor/extensions}
- require "#{File.expand_path(File.dirname(__FILE__) + "/../../../../../")}/config/boot"
- else
- require "#{File.expand_path(File.dirname(__FILE__) + "/../../../")}/config/boot"
- end
-end
-
+require 'rubygems'
require 'rake'
-require 'rake/rdoctask'
require 'rake/testtask'
+require 'rake/packagetask'
+require 'rake/gempackagetask'
-rspec_base = File.expand_path(SPREE_ROOT + '/vendor/plugins/rspec/lib')
-$LOAD_PATH.unshift(rspec_base) if File.exist?(rspec_base)
-require 'spec/rake/spectask'
-# require 'spec/translator'
-
-# Cleanup the SPREE_ROOT constant so specs will load the environment
-Object.send(:remove_const, :SPREE_ROOT)
-
-extension_root = File.expand_path(File.dirname(__FILE__))
+spec = eval(File.read('enhanced_option_types.gemspec'))
-task :default => :spec
-task :stats => "spec:statsetup"
-
-desc "Run all specs in spec directory"
-Spec::Rake::SpecTask.new(:spec) do |t|
- t.spec_opts = ['--options', "\"#{extension_root}/spec/spec.opts\""]
- t.spec_files = FileList["#{extension_root}/spec/**/*_spec.rb"]
+Rake::GemPackageTask.new(spec) do |p|
+ p.gem_spec = spec
end
-namespace :spec do
- desc "Run all specs in spec directory with RCov"
- Spec::Rake::SpecTask.new(:rcov) do |t|
- t.spec_opts = ['--options', "\"#{extension_root}/spec/spec.opts\""]
- t.spec_files = FileList['spec/**/*_spec.rb']
- t.rcov = true
- t.rcov_opts = ['--exclude', 'spec', '--rails']
- end
-
- desc "Print Specdoc for all specs"
- Spec::Rake::SpecTask.new(:doc) do |t|
- t.spec_opts = ["--format", "specdoc", "--dry-run"]
- t.spec_files = FileList['spec/**/*_spec.rb']
- end
-
- [:models, :controllers, :views, :helpers].each do |sub|
- desc "Run the specs under spec/#{sub}"
- Spec::Rake::SpecTask.new(sub) do |t|
- t.spec_opts = ['--options', "\"#{extension_root}/spec/spec.opts\""]
- t.spec_files = FileList["spec/#{sub}/**/*_spec.rb"]
- end
- end
-
- # Hopefully no one has written their extensions in pre-0.9 style
- # desc "Translate specs from pre-0.9 to 0.9 style"
- # task :translate do
- # translator = ::Spec::Translator.new
- # dir = RAILS_ROOT + '/spec'
- # translator.translate(dir, dir)
- # end
-
- # Setup specs for stats
- task :statsetup do
- require 'code_statistics'
- ::STATS_DIRECTORIES << %w(Model\ specs spec/models)
- ::STATS_DIRECTORIES << %w(View\ specs spec/views)
- ::STATS_DIRECTORIES << %w(Controller\ specs spec/controllers)
- ::STATS_DIRECTORIES << %w(Helper\ specs spec/views)
- ::CodeStatistics::TEST_TYPES << "Model specs"
- ::CodeStatistics::TEST_TYPES << "View specs"
- ::CodeStatistics::TEST_TYPES << "Controller specs"
- ::CodeStatistics::TEST_TYPES << "Helper specs"
- ::STATS_DIRECTORIES.delete_if {|a| a[0] =~ /test/}
- end
-
- namespace :db do
- namespace :fixtures do
- desc "Load fixtures (from spec/fixtures) into the current environment's database. Load specific fixtures using FIXTURES=x,y"
- task :load => :environment do
- require 'active_record/fixtures'
- ActiveRecord::Base.establish_connection(RAILS_ENV.to_sym)
- (ENV['FIXTURES'] ? ENV['FIXTURES'].split(/,/) : Dir.glob(File.join(RAILS_ROOT, 'spec', 'fixtures', '*.{yml,csv}'))).each do |fixture_file|
- Fixtures.create_fixtures('spec/fixtures', File.basename(fixture_file, '.*'))
- end
- end
- end
- end
+desc "Release to gemcutter"
+task :release => :package do
+ require 'rake/gemcutter'
+ Rake::Gemcutter::Tasks.new(spec).define
+ Rake::Task['gem:push'].invoke
end
-desc 'Generate documentation for the enchanced_option_types extension.'
-Rake::RDocTask.new(:rdoc) do |rdoc|
- rdoc.rdoc_dir = 'rdoc'
- rdoc.title = 'EnchancedOptionTypesExtension'
- rdoc.options << '--line-numbers' << '--inline-source'
- rdoc.rdoc_files.include('README')
- rdoc.rdoc_files.include('lib/**/*.rb')
-end
+desc "Default Task"
+task :default => [ :spec ]
-# For extensions that are in transition
-desc 'Test the enchanced_option_types extension.'
-Rake::TestTask.new(:test) do |t|
- t.libs << 'lib'
- t.pattern = 'test/**/*_test.rb'
- t.verbose = true
-end
+require 'rspec/core/rake_task'
+RSpec::Core::RakeTask.new
-# Load any custom rakefiles for extension
-Dir[File.dirname(__FILE__) + '/tasks/*.rake'].sort.each { |f| require f }
\ No newline at end of file
+require 'cucumber/rake/task'
+Cucumber::Rake::Task.new do |t|
+ t.cucumber_opts = %w{--format pretty}
+end
\ No newline at end of file
diff --git a/app/controllers/admin/prototypes_controller_decorator.rb b/app/controllers/admin/prototypes_controller_decorator.rb
old mode 100755
new mode 100644
diff --git a/app/controllers/admin/variants_controller_decorator.rb b/app/controllers/admin/variants_controller_decorator.rb
old mode 100755
new mode 100644
diff --git a/app/controllers/orders_controller_decorator.rb b/app/controllers/orders_controller_decorator.rb
old mode 100755
new mode 100644
index 966b997..926f7c5
--- a/app/controllers/orders_controller_decorator.rb
+++ b/app/controllers/orders_controller_decorator.rb
@@ -1,58 +1,58 @@
OrdersController.class_eval do
- # This is hack to get extension working with both edge and 0.9.x series
- unless private_instance_methods.include?("create_before")
- create.before :create_before
- create.after.clear
- end
- create.before.reject! {|method_name| method_name == :create_before }
- create.before << :enhanced_option_create_before
+ def populate
+ @order = current_order(true)
- def enhanced_option_create_before
- variant = nil; quantity = nil;
params[:products].each do |product_id,variant_id|
- quantity = params[:quantity].to_i if !params[:quantity].is_a?(Array)
- quantity = params[:quantity][variant_id].to_i if params[:quantity].is_a?(Array)
- variant = Variant.find(variant_id)
+ if !params[:quantity].is_a?(Hash)
+ quantity = params[:quantity].to_i
+ else
+ quantity = params[:quantity][variant_id].to_i
+ end
+ @order.add_variant(Variant.find(variant_id), quantity) if quantity > 0
end if params[:products]
params[:variants].each do |variant_id, quantity|
quantity = quantity.to_i
- variant = Variant.find(variant_id)
+ @order.add_variant(Variant.find(variant_id), quantity) if quantity > 0
end if params[:variants]
params[:option_values].each_pair do |product_id, otov|
- quantity = params[:quantity].to_i if !params[:quantity].is_a?(Array)
- quantity = params[:quantity][variant_id].to_i if params[:quantity].is_a?(Array)
+ if !params[:quantity].is_a?(Array)
+ quantity = params[:quantity].to_i
+ else
+ quantity = params[:quantity][variant_id].to_i
+ end
option_value_ids = otov.map{|option_type_id, option_value_id| option_value_id}
variant = Variant.by_option_value_ids(option_value_ids, product_id).first
+ @order.add_variant(variant, quantity) if quantity > 0
end if params[:option_values]
- if quantity > 0 && variant
- if quantity > variant.on_hand
- flash[:error] = t(:stock_to_small) % [variant.on_hand]
- else
- @order.add_variant(variant, quantity)
- if @order.save
- # store order token in the session
- session[:order_token] = @order.token
- else
- flash[:error] = t(:out_of_stock)
- end
- end
- elsif quantity > 0
- flash[:error] = t(:wrong_combination)
- else
- flash[:error] = t(:wrong_quantity)
- end
- end
+ redirect_to cart_path
- # override the default r_c behavior (remove flash - redirect to edit details instead of show)
- create.wants.html do
- if flash[:error].blank?
- redirect_to edit_order_url(@order)
- else
- redirect_to :back
- end
+ # if quantity > 0 && variant
+ # if quantity > variant.on_hand
+ # flash[:error] = t(:stock_to_small) % [variant.on_hand]
+ # else
+ # @order.add_variant(variant, quantity)
+ # if @order.save
+ # # store order token in the session
+ # session[:order_token] = @order.token
+ # else
+ # flash[:error] = t(:out_of_stock)
+ # end
+ # end
+ # elsif quantity > 0
+ # flash[:error] = t(:wrong_combination)
+ # else
+ # flash[:error] = t(:wrong_quantity)
+ # end
+ # if flash[:error].blank?
+ # # redirect_to edit_order_url(@order)
+ # redirect_to cart_path
+ # else
+ # redirect_to :back
+ # end
end
+
end
diff --git a/app/helpers/variant_selection.rb b/app/helpers/variant_selection.rb
old mode 100755
new mode 100644
index 2aa8992..4da74d5
--- a/app/helpers/variant_selection.rb
+++ b/app/helpers/variant_selection.rb
@@ -2,7 +2,6 @@ module VariantSelection
# Returns array of arrays of ids of option values,
# that represent all possible combinations of option _values
# sorted by option type position in that product.
- #
def options_values_combinations(product)
product.variants.map{|v| # we get all variants from product
# then we take all option_values
@@ -29,10 +28,7 @@ def ov_to_variant_map(product)
# then we take all option_values
key = v.option_values.sort_by{|ov|
# then sort them by position of option value in product
- ProductOptionType.find(:first, :conditions => {
- :option_type_id => ov.option_type_id,
- :product_id => product.id
- }).position
+ ProductOptionType.find(:first, :conditions => { :option_type_id => ov.option_type_id, :product_id => product.id }).position
}.map(&:id)
result[key] = v
}
diff --git a/app/models/option_types_prototype.rb b/app/models/option_types_prototype.rb
index 32588f0..7572d17 100644
--- a/app/models/option_types_prototype.rb
+++ b/app/models/option_types_prototype.rb
@@ -1,3 +1,2 @@
class OptionTypesPrototype < ActiveRecord::Base
-
end
\ No newline at end of file
diff --git a/app/models/option_value_decorator.rb b/app/models/option_value_decorator.rb
old mode 100755
new mode 100644
diff --git a/app/models/product_decorator.rb b/app/models/product_decorator.rb
old mode 100755
new mode 100644
index 17306a0..d357ce6
--- a/app/models/product_decorator.rb
+++ b/app/models/product_decorator.rb
@@ -11,12 +11,16 @@ def do_create_variants(force = false)
:product => self,
:option_values => option_values,
:is_master => false,
- :sku => self.sku.blank? ? "#{self.name.to_url[0..3]}-#{index+1}" : "#{self.sku}-#{index+1}"
+ :sku => self.generate_variant_sku(index)
})
v
end
end
end
+
+ def generate_variant_sku index
+ self.sku.blank? ? "#{self.name.to_url[0..3]}-#{index+1}" : "#{self.sku}-#{index+1}"
+ end
def default_variant
variants.first
diff --git a/app/models/prototype.rb b/app/models/prototype.rb
old mode 100755
new mode 100644
diff --git a/app/models/variant_decorator.rb b/app/models/variant_decorator.rb
old mode 100755
new mode 100644
index 2d28f4b..eb33daa
--- a/app/models/variant_decorator.rb
+++ b/app/models/variant_decorator.rb
@@ -22,8 +22,8 @@ def self.by_option_value_ids(option_value_ids, product_id)
end
def calculate_price(master_price=nil)
- price = (master_price || product.master.price).to_i
- price+= self.option_values.map{|ov| ov.amount.to_i}.sum
+ price = (master_price || product.master.price)
+ price+= self.option_values.map{|ov| ov.amount}.sum
price > 0 ? price : 0
end
diff --git a/app/views/admin/option_types/_form.html.erb b/app/views/admin/option_types/_form.html.erb
deleted file mode 100755
index 67a3f88..0000000
--- a/app/views/admin/option_types/_form.html.erb
+++ /dev/null
@@ -1,34 +0,0 @@
-<% f.field_container :name do %>
- <%= f.label :name, t("name") %>
- <%= f.text_field :name %>
- <%= f.error_message_on :name %>
-<% end %>
-
-<% f.field_container :name do %>
- <%= f.label :presentation, t("presentation") %>
- <%= f.text_field :presentation %>
- <%= f.error_message_on :presentation %>
-<% end %>
-
-
<%= t("name") %> | -<%= t("display") %> | -<%= t("modifier") %> | -- |
---|---|---|---|
<%= @option_type.option_values.empty? ? t("none") : "" %> | -
-<%= f.add_associated_link( icon('add') + ' ' + t("add_option_value"), @option_type.option_values.build, - {:onclick => "$('#none').hide();", :class => 'iconlink'}) %> -
diff --git a/app/views/admin/option_types/_option_value.html.erb b/app/views/admin/option_types/_option_value.html.erb deleted file mode 100755 index 8419e64..0000000 --- a/app/views/admin/option_types/_option_value.html.erb +++ /dev/null @@ -1,10 +0,0 @@ -<% signed_amount = (option_value.amount.to_i > 0 ? "+" : "") + option_value.amount.to_s %> -