piggybak_simple_variants 0.1.2
Sign up to get free protection for your applications and to get access to all the features.
- data/MIT-LICENSE +20 -0
- data/Rakefile +34 -0
- data/app/assets/javascripts/piggybak_simple_variants/piggybak_simple_variants-application.js +1 -0
- data/app/assets/javascripts/piggybak_simple_variants/piggybak_simple_variants.js +46 -0
- data/app/assets/stylesheets/piggybak_simple_variants/application.css +0 -0
- data/app/helpers/piggybak_simple_variants_helper.rb +17 -0
- data/app/models/piggybak_simple_variants/option.rb +9 -0
- data/app/models/piggybak_simple_variants/option_value.rb +14 -0
- data/app/models/piggybak_simple_variants/variant.rb +7 -0
- data/app/models/piggybak_simple_variants/variant_option.rb +6 -0
- data/app/views/piggybak_simple_variants/cart/_radio_buttons_form.html.erb +44 -0
- data/config/routes.rb +2 -0
- data/db/migrate/20140511185627_create_piggybak_simple_variants_options.rb +9 -0
- data/db/migrate/20140511185729_create_piggybak_simple_variants_option_values.rb +10 -0
- data/db/migrate/20140511185906_create_piggybak_simple_variants_variants.rb +9 -0
- data/db/migrate/20140511193145_update_piggybak_sellables.rb +9 -0
- data/db/migrate/20140513200039_create_piggybak_simple_variants_variant_options.rb +15 -0
- data/lib/acts_as_sellable_with_simple_variants.rb +14 -0
- data/lib/piggybak_simple_variants.rb +5 -0
- data/lib/piggybak_simple_variants/engine.rb +118 -0
- data/lib/piggybak_simple_variants/version.rb +3 -0
- data/lib/tasks/piggybak_simple_variants_tasks.rake +4 -0
- data/test/dummy/README.rdoc +28 -0
- data/test/dummy/Rakefile +6 -0
- data/test/dummy/app/assets/javascripts/application.js +13 -0
- data/test/dummy/app/assets/stylesheets/application.css +15 -0
- data/test/dummy/app/controllers/application_controller.rb +5 -0
- data/test/dummy/app/helpers/application_helper.rb +2 -0
- data/test/dummy/app/views/layouts/application.html.erb +14 -0
- data/test/dummy/bin/bundle +3 -0
- data/test/dummy/bin/rails +4 -0
- data/test/dummy/bin/rake +4 -0
- data/test/dummy/config.ru +4 -0
- data/test/dummy/config/application.rb +23 -0
- data/test/dummy/config/boot.rb +5 -0
- data/test/dummy/config/database.yml +54 -0
- data/test/dummy/config/environment.rb +5 -0
- data/test/dummy/config/environments/development.rb +37 -0
- data/test/dummy/config/environments/production.rb +83 -0
- data/test/dummy/config/environments/test.rb +39 -0
- data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/test/dummy/config/initializers/cookies_serializer.rb +3 -0
- data/test/dummy/config/initializers/filter_parameter_logging.rb +4 -0
- data/test/dummy/config/initializers/inflections.rb +16 -0
- data/test/dummy/config/initializers/mime_types.rb +4 -0
- data/test/dummy/config/initializers/session_store.rb +3 -0
- data/test/dummy/config/initializers/wrap_parameters.rb +14 -0
- data/test/dummy/config/locales/en.yml +23 -0
- data/test/dummy/config/routes.rb +4 -0
- data/test/dummy/config/secrets.yml +22 -0
- data/test/dummy/public/404.html +67 -0
- data/test/dummy/public/422.html +67 -0
- data/test/dummy/public/500.html +66 -0
- data/test/dummy/public/favicon.ico +0 -0
- data/test/fixtures/piggybak_simple_variants/option_configurations.yml +11 -0
- data/test/fixtures/piggybak_simple_variants/option_values.yml +11 -0
- data/test/fixtures/piggybak_simple_variants/options.yml +11 -0
- data/test/fixtures/piggybak_simple_variants/variants.yml +11 -0
- data/test/integration/navigation_test.rb +10 -0
- data/test/models/piggybak_simple_variants/option_configuration_test.rb +9 -0
- data/test/models/piggybak_simple_variants/option_test.rb +9 -0
- data/test/models/piggybak_simple_variants/option_value_test.rb +9 -0
- data/test/models/piggybak_simple_variants/variant_test.rb +9 -0
- data/test/piggybak_simple_variants_test.rb +7 -0
- data/test/test_helper.rb +15 -0
- metadata +186 -0
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright 2014 YOURNAME
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/Rakefile
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
begin
|
2
|
+
require 'bundler/setup'
|
3
|
+
rescue LoadError
|
4
|
+
puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
|
5
|
+
end
|
6
|
+
|
7
|
+
require 'rdoc/task'
|
8
|
+
|
9
|
+
RDoc::Task.new(:rdoc) do |rdoc|
|
10
|
+
rdoc.rdoc_dir = 'rdoc'
|
11
|
+
rdoc.title = 'PiggybakSimpleVariants'
|
12
|
+
rdoc.options << '--line-numbers'
|
13
|
+
rdoc.rdoc_files.include('README.rdoc')
|
14
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
15
|
+
end
|
16
|
+
|
17
|
+
APP_RAKEFILE = File.expand_path("../test/dummy/Rakefile", __FILE__)
|
18
|
+
load 'rails/tasks/engine.rake'
|
19
|
+
|
20
|
+
|
21
|
+
|
22
|
+
Bundler::GemHelper.install_tasks
|
23
|
+
|
24
|
+
require 'rake/testtask'
|
25
|
+
|
26
|
+
Rake::TestTask.new(:test) do |t|
|
27
|
+
t.libs << 'lib'
|
28
|
+
t.libs << 'test'
|
29
|
+
t.pattern = 'test/**/*_test.rb'
|
30
|
+
t.verbose = false
|
31
|
+
end
|
32
|
+
|
33
|
+
|
34
|
+
task default: :test
|
@@ -0,0 +1 @@
|
|
1
|
+
//= require piggybak_simple_variants/piggybak_simple_variants
|
@@ -0,0 +1,46 @@
|
|
1
|
+
var piggybak_simple_variants = {
|
2
|
+
refreshControls : function(data) {
|
3
|
+
if(data.all_selected) { // if all selected
|
4
|
+
var selected_key = data.selected.sort(function (a, b) { return a - b }).join('_');
|
5
|
+
console.log(selected_key);
|
6
|
+
if(simple_variant_map[selected_key]) {
|
7
|
+
$('.simple_variant_options form').show();
|
8
|
+
$('#sellable_id').val(simple_variant_map[selected_key].id);
|
9
|
+
$('#variant_price span').html(simple_variant_map[selected_key].price);
|
10
|
+
} else { // if variant not available
|
11
|
+
$('.simple_variant_options form').hide();
|
12
|
+
$('.unavailable').show();
|
13
|
+
}
|
14
|
+
} else { // if not all selected
|
15
|
+
$('.all_selected').show();
|
16
|
+
$('.simple_variant_options form').hide();
|
17
|
+
}
|
18
|
+
},
|
19
|
+
extractRadioButtonValues: function() {
|
20
|
+
var all_selected = true;
|
21
|
+
var selected = new Array();
|
22
|
+
$.each($('.option'), function(i, j) {
|
23
|
+
var option_id = $(j).attr('id');
|
24
|
+
if($('input[name=' + option_id + ']:checked').length) {
|
25
|
+
selected.push($('input[name=' + option_id + ']:checked').val());
|
26
|
+
} else {
|
27
|
+
all_selected = false;
|
28
|
+
}
|
29
|
+
});
|
30
|
+
return { all_selected: all_selected, selected: selected };
|
31
|
+
},
|
32
|
+
toggleVariantForm: function() {
|
33
|
+
$('.unavailable, .all_selected').hide();
|
34
|
+
var data;
|
35
|
+
data = piggybak_simple_variants.extractRadioButtonValues();
|
36
|
+
piggybak_simple_variants.refreshControls(data);
|
37
|
+
}
|
38
|
+
}
|
39
|
+
|
40
|
+
$(function() {
|
41
|
+
$('.simple_variant_options input[type=radio]').click(function() { piggybak_simple_variants.toggleVariantForm(); });
|
42
|
+
if($('.simple_variant_options').size() > 0) {
|
43
|
+
piggybak_simple_variants.toggleVariantForm();
|
44
|
+
}
|
45
|
+
});
|
46
|
+
|
File without changes
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module PiggybakSimpleVariantsHelper
|
2
|
+
def variant_cart_form(object, options = {:controls => 'radio_buttons'})
|
3
|
+
render "piggybak_simple_variants/cart/#{options[:controls]}_form", :object => object
|
4
|
+
end
|
5
|
+
|
6
|
+
def options_for_variant(variant)
|
7
|
+
PiggybakSimpleVariants::Option.select("DISTINCT piggybak_simple_variants_options.*").joins(:option_values => [:variant_options => :variant]).where("piggybak_simple_variants_variants.klass = '#{variant.klass}'")
|
8
|
+
end
|
9
|
+
|
10
|
+
def simple_variant_map(object)
|
11
|
+
map = {}
|
12
|
+
object.piggybak_sellable.each do |sellable|
|
13
|
+
map[sellable.variant.option_values.hash_ordered.map { |ov| ov.id }.join('_')] = { :id => sellable.id, :price => number_to_currency(sellable.price) }
|
14
|
+
end
|
15
|
+
map.to_json
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,9 @@
|
|
1
|
+
module PiggybakSimpleVariants
|
2
|
+
class Option < ActiveRecord::Base
|
3
|
+
has_many :option_values, -> { order(:position) }, :dependent => :destroy
|
4
|
+
|
5
|
+
default_scope { order('position ASC') }
|
6
|
+
|
7
|
+
accepts_nested_attributes_for :option_values, :allow_destroy => true
|
8
|
+
end
|
9
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module PiggybakSimpleVariants
|
2
|
+
class OptionValue < ActiveRecord::Base
|
3
|
+
has_many :variant_options
|
4
|
+
has_many :variants, through: :variant_options
|
5
|
+
belongs_to :option, :inverse_of => :option_values
|
6
|
+
|
7
|
+
def admin_label
|
8
|
+
"#{self.option.name}: #{self.name}"
|
9
|
+
end
|
10
|
+
|
11
|
+
scope :hash_ordered, -> { includes(:option).order("piggybak_simple_variants_options.position ASC, piggybak_simple_variants_option_values.position ASC") }
|
12
|
+
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,7 @@
|
|
1
|
+
module PiggybakSimpleVariants
|
2
|
+
class Variant < ActiveRecord::Base
|
3
|
+
has_many :piggybak_sellables, class_name: "Piggybak::Sellable"
|
4
|
+
has_many :variant_options
|
5
|
+
has_many :option_values, through: :variant_options, class_name: "::PiggybakSimpleVariants::OptionValue"
|
6
|
+
end
|
7
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
<div class="simple_variant_options">
|
2
|
+
<% if object.reflections.keys.include?(:piggybak_sellable) -%>
|
3
|
+
<% optionArray = Hash.new -%>
|
4
|
+
<% object.piggybak_sellable.each do |sellable| -%>
|
5
|
+
<% if sellable.active -%>
|
6
|
+
<% if sellable.quantity > 0 || sellable.unlimited_inventory -%>
|
7
|
+
<% sellable.variant.option_values.each do |option_value| -%>
|
8
|
+
<% if optionArray.empty? || optionArray[option_value.option].blank? -%>
|
9
|
+
<% optionArray[option_value.option] = [] -%>
|
10
|
+
<% optionArray[option_value.option] << option_value -%>
|
11
|
+
<% else -%>
|
12
|
+
<% if !optionArray[option_value.option].include? option_value -%>
|
13
|
+
<% optionArray[option_value.option] << option_value -%>
|
14
|
+
<% end -%>
|
15
|
+
<% end -%>
|
16
|
+
<% end -%>
|
17
|
+
<% end -%>
|
18
|
+
<% end -%>
|
19
|
+
<% end -%>
|
20
|
+
|
21
|
+
<script type="text/javascript">
|
22
|
+
var simple_variant_map = <%= raw simple_variant_map(object) %>;
|
23
|
+
</script>
|
24
|
+
|
25
|
+
<% optionArray.each do |option, option_values| -%>
|
26
|
+
<div class="option" id="option_<%= option.id %>">
|
27
|
+
<h4><%= option.name %></h4>
|
28
|
+
<% option_values.each do |option_value| -%>
|
29
|
+
<input type="radio" name="option_<%= option.id %>" value="<%= option_value.id %>" class="piggybak-cart-option" />
|
30
|
+
<%= option_value.name %><br />
|
31
|
+
<% end -%>
|
32
|
+
</div>
|
33
|
+
<% end -%>
|
34
|
+
<span class="all_selected">You must select an choice from each option.</span>
|
35
|
+
<span class="unavailable">This combination is not available.</span>
|
36
|
+
<%= form_tag piggybak.cart_add_url do -%>
|
37
|
+
<input type="hidden" id="sellable_id" name="sellable_id" />
|
38
|
+
<div id="variant_price">Price: <span></span></div>
|
39
|
+
<label for="quantity">Quantity</label>
|
40
|
+
<%= text_field_tag :quantity, 1 %>
|
41
|
+
<%= submit_tag "Add to Cart", :id => "submit" %>
|
42
|
+
<% end -%>
|
43
|
+
<% end -%>
|
44
|
+
</div>
|
data/config/routes.rb
ADDED
@@ -0,0 +1,10 @@
|
|
1
|
+
class CreatePiggybakSimpleVariantsOptionValues < ActiveRecord::Migration
|
2
|
+
def change
|
3
|
+
create_table :piggybak_simple_variants_option_values do |t|
|
4
|
+
t.integer :option_id, null: false
|
5
|
+
t.string :name, null: false
|
6
|
+
t.integer :position
|
7
|
+
t.timestamps
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
class CreatePiggybakSimpleVariantsVariantOptions < ActiveRecord::Migration
|
2
|
+
def up
|
3
|
+
create_table :piggybak_simple_variants_variant_options do |t|
|
4
|
+
t.integer :variant_id, null: false
|
5
|
+
t.integer :option_value_id, null: false
|
6
|
+
t.timestamps
|
7
|
+
end
|
8
|
+
add_index :piggybak_simple_variants_variant_options, :variant_id, :name => 'piggybak_sv_variant_options_option_value_id'
|
9
|
+
add_index :piggybak_simple_variants_variant_options, :option_value_id, :name => 'piggybak_sv_variant_options_option_value_id'
|
10
|
+
end
|
11
|
+
|
12
|
+
def down
|
13
|
+
drop_table :piggybak_simple_variants_variant_options
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module Piggybak
|
2
|
+
module ActsAsSellableWithSimpleVariants
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
|
5
|
+
module ClassMethods
|
6
|
+
def acts_as_sellable_with_simple_variants
|
7
|
+
has_many :piggybak_sellable, :as => "item", :class_name => "::Piggybak::Sellable", :inverse_of => :item
|
8
|
+
accepts_nested_attributes_for :piggybak_sellable, :allow_destroy => true
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
::ActiveRecord::Base.send :include, Piggybak::ActsAsSellableWithSimpleVariants
|
@@ -0,0 +1,118 @@
|
|
1
|
+
module PiggybakSimpleVariants
|
2
|
+
class Engine < ::Rails::Engine
|
3
|
+
isolate_namespace PiggybakSimpleVariants
|
4
|
+
|
5
|
+
config.to_prepare do
|
6
|
+
ApplicationController.class_eval do
|
7
|
+
helper :piggybak_simple_variants
|
8
|
+
end
|
9
|
+
RailsAdmin::ApplicationController.class_eval do
|
10
|
+
helper :piggybak_simple_variants
|
11
|
+
end
|
12
|
+
Piggybak::Sellable.class_eval do
|
13
|
+
belongs_to :variant, class_name: "PiggybakSimpleVariants::Variant"
|
14
|
+
def available?
|
15
|
+
if active && quantity > 0 || unlimited_inventory
|
16
|
+
true
|
17
|
+
else
|
18
|
+
false
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
config.before_initialize do
|
25
|
+
Piggybak.config do |config|
|
26
|
+
config.manage_classes += ["::PiggybakSimpleVariants::Option",
|
27
|
+
"::PiggybakSimpleVariants::Variant",
|
28
|
+
"::PiggybakSimpleVariants::VariantOption",
|
29
|
+
"::PiggybakSimpleVariants::OptionValue"]
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
initializer "piggybak_simple_variants.assets.precompile" do |app|
|
34
|
+
app.config.assets.precompile += ['piggybak_simple_variants/piggybak_simple_variants-application.js']
|
35
|
+
end
|
36
|
+
|
37
|
+
# TODO: Figure out of we can have this only in to_prepare or here
|
38
|
+
initializer "piggybak_simple_variants.add_helper" do |app|
|
39
|
+
ApplicationController.class_eval do
|
40
|
+
helper :piggybak_simple_variants
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
initializer "piggybak.rails_admin_config" do |app|
|
45
|
+
RailsAdmin.config do |config|
|
46
|
+
config.model PiggybakSimpleVariants::OptionValue do
|
47
|
+
visible false
|
48
|
+
edit do
|
49
|
+
field :name
|
50
|
+
field :position
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
config.model PiggybakSimpleVariants::Option do
|
55
|
+
navigation_label "Extensions"
|
56
|
+
list do
|
57
|
+
field :name
|
58
|
+
field :position
|
59
|
+
field :option_values
|
60
|
+
end
|
61
|
+
edit do
|
62
|
+
field :name
|
63
|
+
field :position
|
64
|
+
field :option_values do
|
65
|
+
active true
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
config.model PiggybakSimpleVariants::Variant do
|
71
|
+
label "Define variants"
|
72
|
+
show do
|
73
|
+
field :name do
|
74
|
+
visible true
|
75
|
+
end
|
76
|
+
field :klass
|
77
|
+
field :option_values do
|
78
|
+
visible true
|
79
|
+
end
|
80
|
+
end
|
81
|
+
edit do
|
82
|
+
field :name do
|
83
|
+
active true
|
84
|
+
end
|
85
|
+
field :klass do
|
86
|
+
visible :true
|
87
|
+
help "Add the name of your class for this variant."
|
88
|
+
end
|
89
|
+
field :option_values do
|
90
|
+
visible true
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
config.model PiggybakSimpleVariants::VariantOption do
|
96
|
+
label "Options for variants"
|
97
|
+
visible false
|
98
|
+
end
|
99
|
+
|
100
|
+
config.model Piggybak::Sellable do
|
101
|
+
label "Sellable"
|
102
|
+
visible false
|
103
|
+
edit do
|
104
|
+
field :sku
|
105
|
+
field :description
|
106
|
+
field :price
|
107
|
+
field :active
|
108
|
+
field :quantity
|
109
|
+
field :unlimited_inventory do
|
110
|
+
help "If true, backorders on this variant will be allowed, regardless of quantity on hand."
|
111
|
+
end
|
112
|
+
field :variant
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
== README
|
2
|
+
|
3
|
+
This README would normally document whatever steps are necessary to get the
|
4
|
+
application up and running.
|
5
|
+
|
6
|
+
Things you may want to cover:
|
7
|
+
|
8
|
+
* Ruby version
|
9
|
+
|
10
|
+
* System dependencies
|
11
|
+
|
12
|
+
* Configuration
|
13
|
+
|
14
|
+
* Database creation
|
15
|
+
|
16
|
+
* Database initialization
|
17
|
+
|
18
|
+
* How to run the test suite
|
19
|
+
|
20
|
+
* Services (job queues, cache servers, search engines, etc.)
|
21
|
+
|
22
|
+
* Deployment instructions
|
23
|
+
|
24
|
+
* ...
|
25
|
+
|
26
|
+
|
27
|
+
Please feel free to use a different markup language if you do not plan to run
|
28
|
+
<tt>rake doc:app</tt>.
|