spree_myriad_options 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +3 -0
- data/.rspec +2 -0
- data/.rvmrc +1 -0
- data/Gemfile +3 -0
- data/Gemfile.lock +213 -0
- data/Guardfile +19 -0
- data/LICENSE +26 -0
- data/README.md +114 -0
- data/Rakefile +29 -0
- data/Versionfile +12 -0
- data/app/controllers/spree/orders_controller_decorator.rb +31 -0
- data/app/models/spree/line_item_decorator.rb +33 -0
- data/app/models/spree/line_item_option_value.rb +27 -0
- data/app/models/spree/option_value_decorator.rb +4 -0
- data/app/models/spree/order_decorator.rb +30 -0
- data/app/overrides/admin_option_value_fields.rb +23 -0
- data/app/overrides/admin_order_form_line_item_row.rb +6 -0
- data/app/overrides/cart_item_description.rb +5 -0
- data/app/overrides/order_item_description.rb +6 -0
- data/app/overrides/product_cart_form.rb +5 -0
- data/app/views/spree/admin/_order_details_line_item_row.html.erb +6 -0
- data/app/views/spree/admin/option_types/_option_value_adder_fields.html.erb +1 -0
- data/app/views/spree/admin/option_types/_option_value_customization_fields.html.erb +4 -0
- data/app/views/spree/orders/_cart_item_description.html.erb +11 -0
- data/app/views/spree/products/_product_cart_form.html.erb +43 -0
- data/app/views/spree/shared/_order_item_description.html.erb +7 -0
- data/app/views/spree/shared/_order_line_item_options.html.erb +17 -0
- data/config/locales/en.yml +5 -0
- data/db/migrate/20120606023958_add_line_item_option_values_table.rb +14 -0
- data/db/migrate/20120606143114_add_adder_to_option_values.rb +5 -0
- data/db/migrate/20120614192000_add_option_value_customization_to_line_item_option_values.rb +5 -0
- data/db/migrate/20120614192726_add_adder_to_line_item_option_values.rb +5 -0
- data/db/migrate/20120615032058_add_snapshot_cols_to_line_item_option_values.rb +8 -0
- data/db/migrate/20120615173147_add_customization_lines_to_option_value.rb +5 -0
- data/lib/generators/spree_myriad_options/install/install_generator.rb +19 -0
- data/lib/spree_myriad_options/engine.rb +25 -0
- data/lib/spree_myriad_options.rb +2 -0
- data/script/rails +7 -0
- data/spec/controllers/spree/orders_controller_spec.rb +62 -0
- data/spec/models/spree/line_item_option_value_spec.rb +10 -0
- data/spec/models/spree/line_item_spec.rb +79 -0
- data/spec/models/spree/option_value_spec.rb +13 -0
- data/spec/models/spree/order_spec.rb +65 -0
- data/spec/requests/admin_option_types_spec.rb +58 -0
- data/spec/requests/orders_spec.rb +21 -0
- data/spec/requests/products_spec.rb +89 -0
- data/spec/spec_helper.rb +52 -0
- data/spree_myriad_options.gemspec +29 -0
- metadata +184 -0
data/.gitignore
ADDED
data/.rspec
ADDED
data/.rvmrc
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
rvm use 1.9.2-p290@global
|
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
PATH
|
|
2
|
+
remote: .
|
|
3
|
+
specs:
|
|
4
|
+
spree_myriad_options (0.0.2)
|
|
5
|
+
spree_core (~> 1.1)
|
|
6
|
+
|
|
7
|
+
GEM
|
|
8
|
+
remote: http://rubygems.org/
|
|
9
|
+
specs:
|
|
10
|
+
actionmailer (3.2.3)
|
|
11
|
+
actionpack (= 3.2.3)
|
|
12
|
+
mail (~> 2.4.4)
|
|
13
|
+
actionpack (3.2.3)
|
|
14
|
+
activemodel (= 3.2.3)
|
|
15
|
+
activesupport (= 3.2.3)
|
|
16
|
+
builder (~> 3.0.0)
|
|
17
|
+
erubis (~> 2.7.0)
|
|
18
|
+
journey (~> 1.0.1)
|
|
19
|
+
rack (~> 1.4.0)
|
|
20
|
+
rack-cache (~> 1.2)
|
|
21
|
+
rack-test (~> 0.6.1)
|
|
22
|
+
sprockets (~> 2.1.2)
|
|
23
|
+
active_utils (1.0.3)
|
|
24
|
+
activesupport (>= 2.3.11)
|
|
25
|
+
i18n
|
|
26
|
+
activemerchant (1.20.4)
|
|
27
|
+
active_utils (>= 1.0.2)
|
|
28
|
+
activesupport (>= 2.3.11)
|
|
29
|
+
braintree (>= 2.0.0)
|
|
30
|
+
builder (>= 2.0.0)
|
|
31
|
+
i18n
|
|
32
|
+
json (>= 1.5.1)
|
|
33
|
+
money (<= 3.7.1)
|
|
34
|
+
activemodel (3.2.3)
|
|
35
|
+
activesupport (= 3.2.3)
|
|
36
|
+
builder (~> 3.0.0)
|
|
37
|
+
activerecord (3.2.3)
|
|
38
|
+
activemodel (= 3.2.3)
|
|
39
|
+
activesupport (= 3.2.3)
|
|
40
|
+
arel (~> 3.0.2)
|
|
41
|
+
tzinfo (~> 0.3.29)
|
|
42
|
+
activeresource (3.2.3)
|
|
43
|
+
activemodel (= 3.2.3)
|
|
44
|
+
activesupport (= 3.2.3)
|
|
45
|
+
activesupport (3.2.3)
|
|
46
|
+
i18n (~> 0.6)
|
|
47
|
+
multi_json (~> 1.0)
|
|
48
|
+
acts_as_list (0.1.4)
|
|
49
|
+
arel (3.0.2)
|
|
50
|
+
aws-sdk (1.3.9)
|
|
51
|
+
httparty (~> 0.7)
|
|
52
|
+
json (~> 1.4)
|
|
53
|
+
nokogiri (>= 1.4.4)
|
|
54
|
+
uuidtools (~> 2.1)
|
|
55
|
+
braintree (2.16.0)
|
|
56
|
+
builder (>= 2.0.0)
|
|
57
|
+
builder (3.0.0)
|
|
58
|
+
capybara (1.1.2)
|
|
59
|
+
mime-types (>= 1.16)
|
|
60
|
+
nokogiri (>= 1.3.3)
|
|
61
|
+
rack (>= 1.0.0)
|
|
62
|
+
rack-test (>= 0.5.4)
|
|
63
|
+
selenium-webdriver (~> 2.0)
|
|
64
|
+
xpath (~> 0.1.4)
|
|
65
|
+
childprocess (0.3.2)
|
|
66
|
+
ffi (~> 1.0.6)
|
|
67
|
+
cocaine (0.2.1)
|
|
68
|
+
deface (0.9.1)
|
|
69
|
+
nokogiri (~> 1.5.0)
|
|
70
|
+
rails (~> 3.1)
|
|
71
|
+
diff-lcs (1.1.3)
|
|
72
|
+
erubis (2.7.0)
|
|
73
|
+
factory_girl (2.6.4)
|
|
74
|
+
activesupport (>= 2.3.9)
|
|
75
|
+
factory_girl_rails (1.7.0)
|
|
76
|
+
factory_girl (~> 2.6.0)
|
|
77
|
+
railties (>= 3.0.0)
|
|
78
|
+
ffaker (1.12.1)
|
|
79
|
+
ffi (1.0.11)
|
|
80
|
+
guard (1.0.2)
|
|
81
|
+
ffi (>= 0.5.0)
|
|
82
|
+
thor (~> 0.14.6)
|
|
83
|
+
guard-rspec (0.5.11)
|
|
84
|
+
guard (>= 0.8.4)
|
|
85
|
+
highline (1.6.11)
|
|
86
|
+
hike (1.2.1)
|
|
87
|
+
httparty (0.8.3)
|
|
88
|
+
multi_json (~> 1.0)
|
|
89
|
+
multi_xml
|
|
90
|
+
i18n (0.6.0)
|
|
91
|
+
journey (1.0.3)
|
|
92
|
+
jquery-rails (2.0.2)
|
|
93
|
+
railties (>= 3.2.0, < 5.0)
|
|
94
|
+
thor (~> 0.14)
|
|
95
|
+
json (1.7.3)
|
|
96
|
+
kaminari (0.13.0)
|
|
97
|
+
actionpack (>= 3.0.0)
|
|
98
|
+
activesupport (>= 3.0.0)
|
|
99
|
+
railties (>= 3.0.0)
|
|
100
|
+
mail (2.4.4)
|
|
101
|
+
i18n (>= 0.4.0)
|
|
102
|
+
mime-types (~> 1.16)
|
|
103
|
+
treetop (~> 1.4.8)
|
|
104
|
+
mime-types (1.18)
|
|
105
|
+
money (3.7.1)
|
|
106
|
+
i18n (~> 0.4)
|
|
107
|
+
multi_json (1.3.6)
|
|
108
|
+
multi_xml (0.5.1)
|
|
109
|
+
nested_set (1.7.0)
|
|
110
|
+
activerecord (>= 3.0.0)
|
|
111
|
+
railties (>= 3.0.0)
|
|
112
|
+
nokogiri (1.5.3)
|
|
113
|
+
paperclip (2.7.0)
|
|
114
|
+
activerecord (>= 2.3.0)
|
|
115
|
+
activesupport (>= 2.3.2)
|
|
116
|
+
cocaine (>= 0.0.2)
|
|
117
|
+
mime-types
|
|
118
|
+
polyamorous (0.5.0)
|
|
119
|
+
activerecord (~> 3.0)
|
|
120
|
+
polyglot (0.3.3)
|
|
121
|
+
rack (1.4.1)
|
|
122
|
+
rack-cache (1.2)
|
|
123
|
+
rack (>= 0.4)
|
|
124
|
+
rack-ssl (1.3.2)
|
|
125
|
+
rack
|
|
126
|
+
rack-test (0.6.1)
|
|
127
|
+
rack (>= 1.0)
|
|
128
|
+
rails (3.2.3)
|
|
129
|
+
actionmailer (= 3.2.3)
|
|
130
|
+
actionpack (= 3.2.3)
|
|
131
|
+
activerecord (= 3.2.3)
|
|
132
|
+
activeresource (= 3.2.3)
|
|
133
|
+
activesupport (= 3.2.3)
|
|
134
|
+
bundler (~> 1.0)
|
|
135
|
+
railties (= 3.2.3)
|
|
136
|
+
railties (3.2.3)
|
|
137
|
+
actionpack (= 3.2.3)
|
|
138
|
+
activesupport (= 3.2.3)
|
|
139
|
+
rack-ssl (~> 1.3.2)
|
|
140
|
+
rake (>= 0.8.7)
|
|
141
|
+
rdoc (~> 3.4)
|
|
142
|
+
thor (~> 0.14.6)
|
|
143
|
+
rake (0.9.2.2)
|
|
144
|
+
ransack (0.6.0)
|
|
145
|
+
actionpack (~> 3.0)
|
|
146
|
+
activerecord (~> 3.0)
|
|
147
|
+
polyamorous (~> 0.5.0)
|
|
148
|
+
rdoc (3.12)
|
|
149
|
+
json (~> 1.4)
|
|
150
|
+
rspec (2.9.0)
|
|
151
|
+
rspec-core (~> 2.9.0)
|
|
152
|
+
rspec-expectations (~> 2.9.0)
|
|
153
|
+
rspec-mocks (~> 2.9.0)
|
|
154
|
+
rspec-core (2.9.0)
|
|
155
|
+
rspec-expectations (2.9.1)
|
|
156
|
+
diff-lcs (~> 1.1.3)
|
|
157
|
+
rspec-mocks (2.9.0)
|
|
158
|
+
rspec-rails (2.9.0)
|
|
159
|
+
actionpack (>= 3.0)
|
|
160
|
+
activesupport (>= 3.0)
|
|
161
|
+
railties (>= 3.0)
|
|
162
|
+
rspec (~> 2.9.0)
|
|
163
|
+
rubyzip (0.9.8)
|
|
164
|
+
selenium-webdriver (2.20.0)
|
|
165
|
+
childprocess (>= 0.2.5)
|
|
166
|
+
ffi (~> 1.0)
|
|
167
|
+
multi_json (~> 1.0)
|
|
168
|
+
rubyzip
|
|
169
|
+
shoulda-matchers (1.0.0)
|
|
170
|
+
spree_core (1.1.1)
|
|
171
|
+
activemerchant (= 1.20.4)
|
|
172
|
+
acts_as_list (= 0.1.4)
|
|
173
|
+
aws-sdk (~> 1.3.4)
|
|
174
|
+
deface (>= 0.8.0)
|
|
175
|
+
ffaker (~> 1.12.0)
|
|
176
|
+
highline (= 1.6.11)
|
|
177
|
+
jquery-rails (~> 2.0.0)
|
|
178
|
+
kaminari (>= 0.13.0)
|
|
179
|
+
nested_set (= 1.7.0)
|
|
180
|
+
paperclip (~> 2.7)
|
|
181
|
+
rails (>= 3.2.2, <= 3.2.3)
|
|
182
|
+
ransack (~> 0.6.0)
|
|
183
|
+
state_machine (= 1.1.2)
|
|
184
|
+
stringex (~> 1.3.2)
|
|
185
|
+
sprockets (2.1.3)
|
|
186
|
+
hike (~> 1.2)
|
|
187
|
+
rack (~> 1.0)
|
|
188
|
+
tilt (~> 1.1, != 1.3.0)
|
|
189
|
+
sqlite3 (1.3.6)
|
|
190
|
+
state_machine (1.1.2)
|
|
191
|
+
stringex (1.3.3)
|
|
192
|
+
thor (0.14.6)
|
|
193
|
+
tilt (1.3.3)
|
|
194
|
+
treetop (1.4.10)
|
|
195
|
+
polyglot
|
|
196
|
+
polyglot (>= 0.3.1)
|
|
197
|
+
tzinfo (0.3.33)
|
|
198
|
+
uuidtools (2.1.2)
|
|
199
|
+
xpath (0.1.4)
|
|
200
|
+
nokogiri (~> 1.3)
|
|
201
|
+
|
|
202
|
+
PLATFORMS
|
|
203
|
+
ruby
|
|
204
|
+
|
|
205
|
+
DEPENDENCIES
|
|
206
|
+
capybara
|
|
207
|
+
factory_girl_rails (~> 1.7)
|
|
208
|
+
ffaker
|
|
209
|
+
guard-rspec (~> 0.5.0)
|
|
210
|
+
rspec-rails (~> 2.9.0)
|
|
211
|
+
shoulda-matchers (~> 1.0.0)
|
|
212
|
+
spree_myriad_options!
|
|
213
|
+
sqlite3
|
data/Guardfile
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# A sample Guardfile
|
|
2
|
+
# More info at https://github.com/guard/guard#readme
|
|
3
|
+
|
|
4
|
+
guard 'rspec', :version => 2 do
|
|
5
|
+
watch(%r{^spec/.+_spec\.rb$})
|
|
6
|
+
watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
|
|
7
|
+
watch('spec/spec_helper.rb') { "spec" }
|
|
8
|
+
|
|
9
|
+
# Rails example
|
|
10
|
+
watch(%r{^app/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
|
|
11
|
+
watch(%r{^app/(.*)(\.erb|\.haml)$}) { |m| "spec/#{m[1]}#{m[2]}_spec.rb" }
|
|
12
|
+
watch(%r{^app/controllers/(.+)_(controller)\.rb$}) { |m| ["spec/routing/#{m[1]}_routing_spec.rb", "spec/#{m[2]}s/#{m[1]}_#{m[2]}_spec.rb", "spec/acceptance/#{m[1]}_spec.rb"] }
|
|
13
|
+
watch(%r{^spec/support/(.+)\.rb$}) { "spec" }
|
|
14
|
+
watch('config/routes.rb') { "spec/routing" }
|
|
15
|
+
watch('app/controllers/application_controller.rb') { "spec/controllers" }
|
|
16
|
+
# Capybara request specs
|
|
17
|
+
watch(%r{^app/views/(.+)/.*\.(erb|haml)$}) { |m| "spec/requests/#{m[1]}_spec.rb" }
|
|
18
|
+
end
|
|
19
|
+
|
data/LICENSE
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
Copyright (c) 2012 [name of plugin creator]
|
|
2
|
+
All rights reserved.
|
|
3
|
+
|
|
4
|
+
Redistribution and use in source and binary forms, with or without modification,
|
|
5
|
+
are permitted provided that the following conditions are met:
|
|
6
|
+
|
|
7
|
+
* Redistributions of source code must retain the above copyright notice,
|
|
8
|
+
this list of conditions and the following disclaimer.
|
|
9
|
+
* Redistributions in binary form must reproduce the above copyright notice,
|
|
10
|
+
this list of conditions and the following disclaimer in the documentation
|
|
11
|
+
and/or other materials provided with the distribution.
|
|
12
|
+
* Neither the name Spree nor the names of its contributors may be used to
|
|
13
|
+
endorse or promote products derived from this software without specific
|
|
14
|
+
prior written permission.
|
|
15
|
+
|
|
16
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
17
|
+
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
18
|
+
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
19
|
+
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
|
20
|
+
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
|
21
|
+
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
|
22
|
+
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
|
23
|
+
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
|
24
|
+
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
|
25
|
+
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
26
|
+
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
data/README.md
ADDED
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
Spree Myriad Options
|
|
2
|
+
==================
|
|
3
|
+
|
|
4
|
+
This extension makes a few changes to the Spree data model and controller
|
|
5
|
+
logic, to let you create Products with many Option Types/Values, but not have
|
|
6
|
+
to maintain sets of Variants for each combination.
|
|
7
|
+
|
|
8
|
+
In other words, if you have a store where Products have 5 user-selectable
|
|
9
|
+
options, and each option has 10 potential values, and you want to offer every
|
|
10
|
+
combination of those options to customers, in a default Spree installation your
|
|
11
|
+
store admin would be faced with creating and maintaining 97,656,259 Variants -
|
|
12
|
+
just for that product.
|
|
13
|
+
|
|
14
|
+
This extension bypasses the LineItem/Variant/Option Value relationship to make
|
|
15
|
+
that uneccessary. You just create the list of Option Types and Option Values
|
|
16
|
+
normally in Spree, and associate those as needed to Products. A LineItem then
|
|
17
|
+
has many OptionValue's directly, and only is tied to the 'master' variant for
|
|
18
|
+
that product.
|
|
19
|
+
|
|
20
|
+
Of course, with this extension, inventory is no longer tracked on a
|
|
21
|
+
per-option-combination (Variant) basis. It is only tracked per-product (Master
|
|
22
|
+
Variant). The use case would assume that inventory is not important, or that
|
|
23
|
+
products are manufactured to order.
|
|
24
|
+
|
|
25
|
+
Changes to the Product add-to-cart form will list selections for each option as
|
|
26
|
+
a set of radio buttons.
|
|
27
|
+
|
|
28
|
+
In the admin, Option Values also get a new 'adder' field, which is added to the
|
|
29
|
+
line item price when that option is selected and added to the cart.
|
|
30
|
+
|
|
31
|
+
Option Values can also be set up by the admin with a "Customization Lines"
|
|
32
|
+
numeric value, which may be useful for "Engraving Message" or similar
|
|
33
|
+
user-entered text. This should result in the customer seeing the specified
|
|
34
|
+
number of fields below each option value, which they can fill out as needed.
|
|
35
|
+
There is as yet no validation on these user-generated values.
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
Status
|
|
39
|
+
======
|
|
40
|
+
|
|
41
|
+
Version 0.1.0
|
|
42
|
+
|
|
43
|
+
Tests complete and passing.
|
|
44
|
+
|
|
45
|
+
Example
|
|
46
|
+
=======
|
|
47
|
+
|
|
48
|
+
Add to gemfile
|
|
49
|
+
|
|
50
|
+
gem 'spree_myriad_options', :git => 'git://github.com/sbeam/spree_myriad_options.git'
|
|
51
|
+
|
|
52
|
+
Install
|
|
53
|
+
|
|
54
|
+
$ bundle
|
|
55
|
+
$ bundle exec rake railties:install:migrations FROM=spree_myriad_options
|
|
56
|
+
$ bundle exec rake db:migrate
|
|
57
|
+
|
|
58
|
+
Restart Rails, and in your Products admin, add some Option Types and Values to
|
|
59
|
+
a Product (and remove any Variants - only the invisible 'master' Variant should
|
|
60
|
+
exist on a Product for this extension to affect it.
|
|
61
|
+
|
|
62
|
+
Then in the Product detail page you should see sets of radio buttons for each
|
|
63
|
+
configured option. Each cart/order view should display the selected options in
|
|
64
|
+
the line item detail.
|
|
65
|
+
|
|
66
|
+
Note, this extension might not jive with some others, like
|
|
67
|
+
`spree_variant_options` (although it's a great extension, it still would
|
|
68
|
+
require maintaining Variants for each option combination)
|
|
69
|
+
|
|
70
|
+
Similar Gems
|
|
71
|
+
------------
|
|
72
|
+
|
|
73
|
+
You might also want to look at
|
|
74
|
+
[spree_flexi_variants](https://github.com/jsqu99/spree_flexi_variants) which
|
|
75
|
+
has similar goals, and more features than this. Since our needs were simpler,
|
|
76
|
+
this was begun as a total rewrite that would simply provide a way around the
|
|
77
|
+
Variant maintance problem in Spree, no more no less. There are now a few more
|
|
78
|
+
features, but think of this as more a clean, well-tested blank-slate that can
|
|
79
|
+
be built upon to meet your app's needs, rather than a turnkey install-and-go
|
|
80
|
+
extension.
|
|
81
|
+
|
|
82
|
+
TODO
|
|
83
|
+
----
|
|
84
|
+
|
|
85
|
+
* replace simple `option_value.customization_lines` with Customization
|
|
86
|
+
classes, ie includable modules with field definitions and validation
|
|
87
|
+
callbacks
|
|
88
|
+
* (maybe) some JS to auto-update the price on the product detail form
|
|
89
|
+
|
|
90
|
+
Contributions
|
|
91
|
+
-------------
|
|
92
|
+
|
|
93
|
+
feedback, ideas, reports, new features and fixes would be great. Fork and
|
|
94
|
+
create a pull request. Patches should come with green tests.
|
|
95
|
+
|
|
96
|
+
Testing
|
|
97
|
+
-------
|
|
98
|
+
|
|
99
|
+
Be sure to bundle your dependencies and then create a dummy test app for the
|
|
100
|
+
specs to run against.
|
|
101
|
+
|
|
102
|
+
in Spree 1.1.2+, you should be able to do this -
|
|
103
|
+
|
|
104
|
+
$ bundle
|
|
105
|
+
$ bundle exec rake test_app
|
|
106
|
+
$ bundle exec guard
|
|
107
|
+
|
|
108
|
+
But, due to an issue with the dummy app generator and namespacing in
|
|
109
|
+
Spree 1.1.1 (see https://github.com/spree/spree/issues/1580) you will need to
|
|
110
|
+
create a barebones Spree site somewhere else and hook this engine to that for
|
|
111
|
+
testing. See `spec/spec_helper.rb` and change the `path_to_test_store` value.
|
|
112
|
+
|
|
113
|
+
Copyright (c) 2012 [Sam Beam, creator], released under the New BSD License
|
|
114
|
+
|
data/Rakefile
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
require 'rake'
|
|
2
|
+
require 'rake/testtask'
|
|
3
|
+
require 'rake/packagetask'
|
|
4
|
+
require 'rubygems/package_task'
|
|
5
|
+
require 'rspec/core/rake_task'
|
|
6
|
+
require 'spree/core/testing_support/common_rake'
|
|
7
|
+
|
|
8
|
+
RSpec::Core::RakeTask.new
|
|
9
|
+
|
|
10
|
+
task :default => [:spec]
|
|
11
|
+
|
|
12
|
+
spec = eval(File.read('spree_myriad_options.gemspec'))
|
|
13
|
+
|
|
14
|
+
Gem::PackageTask.new(spec) do |p|
|
|
15
|
+
p.gem_spec = spec
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
desc 'Release to gemcutter'
|
|
19
|
+
task :release => :package do
|
|
20
|
+
require 'rake/gemcutter'
|
|
21
|
+
Rake::Gemcutter::Tasks.new(spec).define
|
|
22
|
+
Rake::Task['gem:push'].invoke
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
desc 'Generates a dummy app for testing'
|
|
26
|
+
task :test_app do
|
|
27
|
+
ENV['LIB_NAME'] = 'spree_myriad_options'
|
|
28
|
+
Rake::Task['common:test_app'].invoke
|
|
29
|
+
end
|
data/Versionfile
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
# This file is used to designate compatibilty with different versions of Spree
|
|
2
|
+
# Please see http://spreecommerce.com/documentation/extensions.html#versionfile for details
|
|
3
|
+
|
|
4
|
+
# Examples
|
|
5
|
+
#
|
|
6
|
+
# '1.2.x' => { :branch => 'master' }
|
|
7
|
+
# '1.1.x' => { :branch => '1-1-stable' }
|
|
8
|
+
# '1.0.x' => { :branch => '1-0-stable' }
|
|
9
|
+
# '0.70.x' => { :branch => '0-70-stable' }
|
|
10
|
+
# '0.40.x' => { :tag => 'v1.0.0', :version => '1.0.0' }
|
|
11
|
+
|
|
12
|
+
'1.1.x' => { :branch => 'master' }
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
Spree::OrdersController.class_eval do
|
|
2
|
+
|
|
3
|
+
# prepend to orders#populate to
|
|
4
|
+
# look for params[:options] and attach the option values
|
|
5
|
+
# to the add_variant call
|
|
6
|
+
def populate_with_options
|
|
7
|
+
@order = current_order(true)
|
|
8
|
+
|
|
9
|
+
if params[:options].present? && params[:variants]
|
|
10
|
+
|
|
11
|
+
params[:variants].each do |variant_id, quantity|
|
|
12
|
+
if variant = Spree::Variant.find(variant_id)
|
|
13
|
+
quantity = quantity.to_i
|
|
14
|
+
|
|
15
|
+
option_values = Spree::OptionValue.find(params[:options].values.map(&:to_i))
|
|
16
|
+
|
|
17
|
+
line_item = @order.add_variant(variant, quantity, option_values)
|
|
18
|
+
|
|
19
|
+
line_item.customizations = params[:customizations] if params[:customizations]
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
params.delete(:variants) # prevent populate_orig from adding again
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
populate_without_options
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
alias_method_chain :populate, :options
|
|
30
|
+
|
|
31
|
+
end
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
Spree::LineItem.class_eval do
|
|
2
|
+
|
|
3
|
+
has_many :line_item_option_values, :dependent => :destroy
|
|
4
|
+
has_many :option_values, :through => :line_item_option_values
|
|
5
|
+
|
|
6
|
+
alias_method :options, :line_item_option_values
|
|
7
|
+
|
|
8
|
+
def has_options?
|
|
9
|
+
self.option_values.length > 0
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def copy_price
|
|
13
|
+
self.price = variant.price if variant && price.nil?
|
|
14
|
+
|
|
15
|
+
self.option_values.each do |val|
|
|
16
|
+
self.price += val.adder
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def customizations= params
|
|
21
|
+
params.each do |option_value_id, val|
|
|
22
|
+
if option = self.options.find_by_option_value_id(option_value_id)
|
|
23
|
+
option.customization = val
|
|
24
|
+
option.save
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def customizations
|
|
30
|
+
self.options.each_with_object({}) { |opt, h| h[opt.option_value_id] = opt.customization unless opt.customization.blank? }
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
end
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
module Spree
|
|
2
|
+
class LineItemOptionValue < ActiveRecord::Base
|
|
3
|
+
belongs_to :line_item
|
|
4
|
+
belongs_to :option_value, :class_name => 'Spree::OptionValue'
|
|
5
|
+
|
|
6
|
+
before_save :snapshot_option_values
|
|
7
|
+
|
|
8
|
+
serialize :customization
|
|
9
|
+
|
|
10
|
+
def customizable?
|
|
11
|
+
!self.option_value.customization_lines.blank?
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
private
|
|
15
|
+
|
|
16
|
+
def snapshot_option_values
|
|
17
|
+
if option_value
|
|
18
|
+
self.adder = option_value.adder
|
|
19
|
+
self.value_name = option_value.name
|
|
20
|
+
self.value_presentation = option_value.presentation
|
|
21
|
+
self.type_name = option_value.option_type.name
|
|
22
|
+
self.type_presentation = option_value.option_type.presentation
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
end
|
|
27
|
+
end
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
Spree::Order.class_eval do
|
|
2
|
+
|
|
3
|
+
def contains? variant, options
|
|
4
|
+
options ||= []
|
|
5
|
+
line_items.detect { |line_item| line_item.variant_id == variant.id && line_item.option_values == options }
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def add_variant variant, quantity=1, options=nil
|
|
10
|
+
|
|
11
|
+
current_item = contains?(variant, options)
|
|
12
|
+
|
|
13
|
+
if current_item
|
|
14
|
+
current_item.quantity += quantity
|
|
15
|
+
current_item.save
|
|
16
|
+
else
|
|
17
|
+
current_item = Spree::LineItem.new(:quantity => quantity)
|
|
18
|
+
current_item.variant = variant
|
|
19
|
+
current_item.price = variant.price
|
|
20
|
+
|
|
21
|
+
current_item.option_values = options if options
|
|
22
|
+
|
|
23
|
+
self.line_items << current_item
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
current_item
|
|
27
|
+
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
end
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
Deface::Override.new(:virtual_path => "spree/admin/option_types/_option_value_fields",
|
|
2
|
+
:name => "admin_option_value_fields",
|
|
3
|
+
:insert_after => "tr[data-hook=option_value] td.presentation",
|
|
4
|
+
:partial => "spree/admin/option_types/option_value_adder_fields",
|
|
5
|
+
:disabled => false)
|
|
6
|
+
|
|
7
|
+
Deface::Override.new(:virtual_path => "spree/admin/option_types/edit",
|
|
8
|
+
:name => "admin_option_value_header",
|
|
9
|
+
:insert_after => "thead[data-hook=option_header] th:nth-child(2)",
|
|
10
|
+
:text => '<th>Adder</th>',
|
|
11
|
+
:disabled => false)
|
|
12
|
+
|
|
13
|
+
Deface::Override.new(:virtual_path => "spree/admin/option_types/_option_value_fields",
|
|
14
|
+
:name => "admin_option_value_customization_fields",
|
|
15
|
+
:insert_after => "tr[data-hook=option_value] td.adder",
|
|
16
|
+
:partial => "spree/admin/option_types/option_value_customization_fields",
|
|
17
|
+
:disabled => false)
|
|
18
|
+
|
|
19
|
+
Deface::Override.new(:virtual_path => "spree/admin/option_types/edit",
|
|
20
|
+
:name => "admin_option_value_customization_header",
|
|
21
|
+
:insert_after => "thead[data-hook=option_header] th:nth-child(3)",
|
|
22
|
+
:text => '<th>Customization Lines</th>',
|
|
23
|
+
:disabled => false)
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
Deface::Override.new(:virtual_path => "spree/admin/shared/_order_details",
|
|
2
|
+
:name => "admin_order_details_line_item_row",
|
|
3
|
+
:replace => "tr[data-hook=order_details_line_item_row] td:first-child", # replace the first <td> in the row only
|
|
4
|
+
:partial => "spree/admin/order_details_line_item_row",
|
|
5
|
+
:disabled => false)
|
|
6
|
+
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
<td width="300"><%= item.variant.product.name %>
|
|
2
|
+
<%= "(" + variant_options(item.variant) + ")" unless item.variant.option_values.empty? %>
|
|
3
|
+
<%- if item.has_options? %>
|
|
4
|
+
<%= render :partial => 'spree/shared/order_line_item_options', :locals => { :item => item } %>
|
|
5
|
+
<% end %>
|
|
6
|
+
</td>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<td class="adder"><%= f.text_field :adder, :value => number_to_currency(f.object.adder, :unit => '') %></td>
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
<td data-hook="cart_item_description">
|
|
2
|
+
|
|
3
|
+
<h4><%= link_to variant.product.name, product_path(variant.product) %></h4>
|
|
4
|
+
|
|
5
|
+
<%= truncate(variant.product.description, :length => 100, :omission => "...") %>
|
|
6
|
+
|
|
7
|
+
<%- if line_item.has_options? %>
|
|
8
|
+
<%= render :partial => 'spree/shared/order_line_item_options', :locals => { :item => line_item } %>
|
|
9
|
+
<% end %>
|
|
10
|
+
|
|
11
|
+
</td>
|