galvinhsiu-active_cart 0.0.19

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,21 @@
1
+ Gem::Specification.new do |s|
2
+ s.name = 'galvinhsiu-active_cart'
3
+ s.summary = "Shopping Cart framework gem. Supports 'storage engines' and order total plugins, forked to use state_machine from active_cart."
4
+ s.description = <<-EOS
5
+ You can use active_cart as the basis of a shopping cart system. It's not a shopping cart application - it's a shopping cart framework.
6
+ EOS
7
+ s.email = 'myles@madpilot.com.au, galvinhsiu@gmail.com'
8
+ s.homepage = "http://gemcutter.org/gems/galvinhsiu-active_cart"
9
+ s.authors = ["Myles Eftos", "Galvin Hsiu"]
10
+ s.version = '0.0.19'
11
+
12
+ s.require_paths = ['lib']
13
+
14
+ s.add_dependency 'state_machine'
15
+ s.add_development_dependency 'shoulda'
16
+ s.add_development_dependency 'mocha'
17
+ s.add_development_dependency 'machinist'
18
+ s.add_development_dependency 'faker'
19
+
20
+ s.files = Dir['lib/**/*', 'galvinhsiu-active_cart.gemspec']
21
+ end
@@ -0,0 +1,189 @@
1
+ module ActiveCart
2
+ # The Cart class is the core class in ActiveCart. It is a singleton (so you can only have one cart per application), that gets setup initially by passing in
3
+ # a storage engine instance. Storage engines abstract away the storage of the cart, and is left as an exercise to the user. See the Storage engine docs
4
+ # for details.
5
+ #
6
+ # The Cart class also takes order_total objects, which will calculate order totals. it may include thinkgs like shipping, or gift vouchers etc. See the Order Total
7
+ # docs for details.
8
+ #
9
+ # The Cart object delegates a number of Array methods:
10
+ # :[], :<<, :[]=, :at, :clear, :collect, :map, :delete, :delete_at, :each, :each_index, :empty?, :eql?, :first, :include?, :index, :inject, :last, :length, :pop, :push, :shift, :size, :unshift
11
+ #
12
+ # The CartEngine object uses a state machine to track the state of the cart. The default states are: shopping, checkout, verifying_payment, completed, failed. It exposed the following transitions:
13
+ # continue_shopping, checkout, check_payment, payment_successful, payment_failed
14
+ #
15
+ # @cart.checkout! # transitions from shopping or verifying_payment to checkout
16
+ # @cart.check_payment! # transistions from checkout to verifying_payment
17
+ # @cart.payment_successful! # transitions from verifying_payment to completed
18
+ # @cart.payment_failed! # transitions from verifying_payment to failed
19
+ # @cart.continue_shopping! # transitions from checkout or verifying_payment to shopping
20
+ #
21
+ class Cart
22
+ attr_accessor :storage_engine, :order_total_calculators, :customer
23
+ include Enumerable
24
+
25
+ # You need to supply a storage engine. An optional block can be given which allows you to add order total items.
26
+ #
27
+ # A typical initialization block might look like this
28
+ #
29
+ # @cart = Cart.new(MyAwesomeStorageEngine.new) do |o|
30
+ # o << ShippingOrderTotal.new
31
+ # o << GstOrderTotal.new
32
+ # end
33
+ #
34
+ def initialize(storage_engine, &block)
35
+ @storage_engine = storage_engine
36
+ @order_total_calculators = OrderTotalCollection.new(self)
37
+
38
+ if block_given?
39
+ yield order_total_calculators
40
+ end
41
+ end
42
+
43
+ extend Forwardable
44
+ # Storage Engine Array delegators
45
+ # TODO: Consolidate - not all of these make sense, and some need overriding so they take the callbacks into account
46
+ #
47
+ # Candidates for removal:
48
+ # delete_at
49
+ # delete_if
50
+ # []=
51
+ # replace
52
+ # insert
53
+ # shift
54
+ # unshift
55
+ # pop
56
+ #
57
+ # Aliases
58
+ # delete => remove_from_cart(obj, 1)
59
+ # << => add_to_cart(obj, 1)
60
+ # push => add_to_cart(obj, 1)
61
+ #
62
+ # Overrides
63
+ # clear => .each { |obj| self.remove_from_cart(obj) }
64
+ #
65
+ def_delegators :@storage_engine, :[], :<<, :[]=, :at, :clear, :collect, :map, :delete, :delete_at, :each, :each_index, :empty?, :eql?, :first, :include?, :index, :inject, :last, :length, :pop, :push, :shift, :size, :unshift
66
+
67
+ # Returns a unique id for the invoice. It's upto the storage engine to generate and track these numbers
68
+ #
69
+ def invoice_id
70
+ @storage_engine.invoice_id
71
+ end
72
+
73
+ # Returns the sub-total of all the items in the cart. Usually returns a float.
74
+ #
75
+ # @cart.sub_total # => 100.00
76
+ #
77
+ def quantity
78
+ @storage_engine.quantity
79
+ end
80
+
81
+ # Returns the subtotal of cart, which is effectively the total of all the items multiplied by their quantites. Does NOT include order_totals
82
+ def sub_total
83
+ @storage_engine.sub_total
84
+ end
85
+
86
+ # Adds an item to the cart. If the item already exists in the cart (identified by the id of the item), then the quantity will be increased but the supplied quantity (default: 1)
87
+ #
88
+ # @cart.add_to_cart(item, 5)
89
+ # @cart.quantity # => 5
90
+ #
91
+ # @cart.add_to_cart(item, 2)
92
+ # @cart.quantity # => 7
93
+ # @cart[0].size # => 7
94
+ # @cart[1] # => nil
95
+ #
96
+ # @cart.add_to_cart(item_2, 4)
97
+ # @cart.quantity => 100
98
+ # @cart[0].size # => 7
99
+ # @cart[1].size # => 4
100
+ #
101
+ # Callbacks:
102
+ #
103
+ # Calls the storage engines before_add_to_cart(item, quantity) and after_add_to_cart(item, quantity) methods (if they exist). If before_add_to_cart returns false, the add will be halted.
104
+ # Calls the items before_add_to_item(quantity) and after_add_to_cart(quantity) methods (if they exist). If before_add_to_cart returns false, the add will be halted.
105
+ #
106
+ def add_to_cart(item, quantity = 1, options = {})
107
+ with_callbacks(:add_to_cart, item, quantity, options) do
108
+ @storage_engine.add_to_cart(item, quantity, options)
109
+ end
110
+ end
111
+
112
+ # Sets the quantity of an item to the supplied value
113
+ #
114
+ # @cart.add_to_cart(item, 5)
115
+ # @cart[0].quantity # => 5
116
+ # @cart.update_cart(item, 15)
117
+ # @cart[0].quantity # => 15
118
+ # @cart.update_cart(item, 2)
119
+ # @cart[0].quantity # => 2
120
+ #
121
+ def update_cart(item, quantity = 1, options = {})
122
+ if @storage_engine.include?(item)
123
+ index = @storage_engine.index(item)
124
+ diff = quantity - @storage_engine.at(index).quantity
125
+
126
+ if diff < 0
127
+ return remove_from_cart(item, -1 * diff, options)
128
+ else
129
+ return add_to_cart(item, diff, options)
130
+ end
131
+ else
132
+ return add_to_cart(item, quantity, options)
133
+ end
134
+ end
135
+
136
+ # Removes an item from the cart (identified by the id of the item). If the supplied quantity is greater than equal to the number in the cart, the item will be removed, otherwise the quantity will simply be decremented by the supplied amount
137
+ #
138
+ # @cart.add_to_cart(item, 5)
139
+ # @cart[0].quantity # => 5
140
+ # @cart.remove_from_cart(item, 3)
141
+ # @cart[0].quantity # => 2
142
+ # @cart.remove_from_cart(item, 2)
143
+ # @cart[0] # => nil
144
+ #
145
+ # Callbacks:
146
+ #
147
+ # Calls the storage engines before_remove_from_cart(item, quantity) and after_remove_from_cart(item, quantity) methods (if they exist). If before_remove_from_cart returns false, the remove will be halted.
148
+ # Calls the items before_remove_from_item(quantity) and after_remove_from_cart(quantity) methods (if they exist). If before_remove_from_cart returns false, the remove will be halted.
149
+ #
150
+ def remove_from_cart(item, quantity = 1, options = {})
151
+ with_callbacks(:remove_from_cart, item, quantity, options) do
152
+ @storage_engine.remove_from_cart(item, quantity, options)
153
+ end
154
+ end
155
+
156
+ # Returns the total of the cart. This includes all the order_total calculations
157
+ #
158
+ def total
159
+ sub_total + order_total_calculators.total
160
+ end
161
+
162
+ # Returns the current state of the cart storage engine
163
+ #
164
+ def state
165
+ storage_engine.state
166
+ end
167
+
168
+ # :nodoc
169
+ def method_missing(symbol, *args)
170
+ # This allows developers to add extra aasm event transaction, and still allow them to called from the cart
171
+ if @storage_engine.state_paths.events.include?(symbol.to_s[0..-2].to_sym)
172
+ @storage_engine.send(symbol)
173
+ else
174
+ super
175
+ end
176
+ end
177
+
178
+ private
179
+ def with_callbacks(type, item, quantity, options, &blk)
180
+ return false unless item.send("before_#{type}".to_sym, quantity, options) if item.respond_to?("before_#{type}".to_sym)
181
+ return false unless @storage_engine.send("before_#{type}".to_sym, item, quantity, options) if @storage_engine.respond_to?("before_#{type}".to_sym)
182
+
183
+ yield
184
+
185
+ @storage_engine.send("after_#{type}".to_sym, item, quantity, options) if @storage_engine.respond_to?("after_#{type}".to_sym)
186
+ item.send("after_#{type}".to_sym, quantity, options) if item.respond_to?("after_#{type}".to_sym)
187
+ end
188
+ end
189
+ end
@@ -0,0 +1,121 @@
1
+ # Mixin this module into the class you want to use as your storage class. Remember to override the invoice_id method
2
+ #
3
+ module ActiveCart
4
+ # The CartStorage object uses a state machine to track the state of the cart. The default states are: shopping, checkout, verifying_payment, completed, failed. It exposed the following transitions:
5
+ # continue_shopping, checkout, check_payment, payment_successful, payment_failed
6
+ #
7
+ # @cart.checkout! # transitions from shopping, verifying_payment or failed to checkout
8
+ # @cart.check_payment! # transistions from checkout to verifying_payment
9
+ # @cart.payment_successful! # transitions from verifying_payment to completed
10
+ # @cart.payment_failed! # transitions from verifying_payment to failed
11
+ # @cart.continue_shopping # transitions from checkout, verifying_payment or failed to shopping
12
+ #
13
+ # It will fire before_ and after callbacks with the same name as the transitions
14
+ #
15
+ module CartStorage
16
+ def self.included(base) #:nodoc:
17
+
18
+ base.state_machine :state, :initial => :shopping do
19
+
20
+ event :continue_shopping do
21
+ transition [ :checkout, :verifying_payment, :failed ] => :shopping
22
+ end
23
+
24
+ event :checkout do
25
+ transition [ :shopping, :verifying_payment, :failed ] => :checkout
26
+ end
27
+
28
+ event :check_payment do
29
+ transition :checkout => :verifying_payment
30
+ end
31
+
32
+ event :payment_successful do
33
+ transition :verifying_payment => :completed
34
+ end
35
+
36
+ event :payment_failed do
37
+ transition :verifying_payment => :failed
38
+ end
39
+
40
+ state :shopping
41
+ state :checkout
42
+ state :verifying_payment
43
+ state :completed
44
+ state :failed
45
+ end
46
+ end
47
+
48
+ # Returns the unique invoice_id for this cart instance. This MUST be overriden by the concrete class this module is mixed into, otherwise you
49
+ # will get a NotImplementedError
50
+ #
51
+ def invoice_id
52
+ raise NotImplementedError
53
+ end
54
+
55
+ # Returns the sub-total of all the items in the cart. Usually returns a float.
56
+ #
57
+ # @cart.sub_total # => 100.00
58
+ #
59
+ def sub_total
60
+ inject(0) { |t, item| t + (item.quantity * item.price.to_f) }
61
+ end
62
+
63
+ # Returns the number of items in the cart. It takes into account the individual quantities of each item, eg if there are 3 items in the cart, each with a quantity of 2, this will return 6
64
+ #
65
+ def quantity
66
+ inject(0) { |t, item| t + item.quantity }
67
+ end
68
+
69
+ # Adds an item to the cart. If the item already exists in the cart (identified by the id of the item), then the quantity will be increased but the supplied quantity (default: 1)
70
+ #
71
+ # @cart.add_to_cart(item, 5)
72
+ # @cart.quantity # => 5
73
+ #
74
+ # @cart.add_to_cart(item, 2)
75
+ # @cart.quantity # => 7
76
+ # @cart[0].quantity # => 7
77
+ # @cart[1] # => nil
78
+ #
79
+ # @cart.add_to_cart(item_2, 4)
80
+ # @cart.quantity => 100
81
+ # @cart[0].quantity # => 7
82
+ # @cart[1].quantity # => 4
83
+ #
84
+ def add_to_cart(item, quantity = 1, options = {})
85
+ if self.include?(item)
86
+ index = self.index(item)
87
+ self.at(index).quantity += quantity
88
+ else
89
+ item.quantity += quantity
90
+ self << item
91
+ end
92
+ end
93
+
94
+ # Removes an item from the cart (identified by the id of the item). If the supplied quantity is greater than equal to the number in the cart, the item will be removed, otherwise the quantity will simply be decremented by the supplied amount
95
+ #
96
+ # @cart.add_to_cart(item, 5)
97
+ # @cart[0].quantity # => 5
98
+ # @cart.remove_from_cart(item, 3)
99
+ # @cart[0].quantity # => 2
100
+ # @cart.remove_from_cart(item, 2)
101
+ # @cart[0] # => nil
102
+ #
103
+ # @cart.add_to_cart(item, 3)
104
+ # @cart[0].quantity # => 3
105
+ # @cart_remove_from_cart(item, :all)
106
+ # @cart[[0].quantity # => 0
107
+ def remove_from_cart(item, quantity = 1, option = {})
108
+ if self.include?(item)
109
+ index = self.index(item)
110
+
111
+ quantity = self.at(index).quantity if quantity == :all
112
+
113
+ if (existing = self.at(index)).quantity - quantity > 0
114
+ existing.quantity = existing.quantity - quantity
115
+ else
116
+ self.delete_at(index)
117
+ end
118
+ end
119
+ end
120
+ end
121
+ end
@@ -0,0 +1,36 @@
1
+ # Mixin this module into the class you want to act as an item
2
+ #
3
+ module ActiveCart
4
+ #
5
+ module Item
6
+ # A unique id for the item. The Mixee needs to implement this or a NotImplementedError will be thrown
7
+ #
8
+ def id
9
+ raise NotImplementedError
10
+ end
11
+
12
+ # A display name for the item. The Mixee needs to implement this or a NotImplementedError will be thrown
13
+ #
14
+ def name
15
+ raise NotImplementedError
16
+ end
17
+
18
+ # Returns the quantity of this item in the context of a cart
19
+ #
20
+ def quantity
21
+ @quantity || 0
22
+ end
23
+
24
+ # Set the quantity of this item in the context of a cart
25
+ #
26
+ def quantity=(quantity)
27
+ @quantity = quantity
28
+ end
29
+
30
+ # Returns the price of this item
31
+ #
32
+ def price
33
+ raise NotImplementedError
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,18 @@
1
+ module ActiveCart
2
+ module Items
3
+ class MemoryItem
4
+ attr_accessor :id, :name, :price
5
+ include ActiveCart::Item
6
+
7
+ def ==(item)
8
+ self.id == item.id
9
+ end
10
+
11
+ def initialize(id, name, price)
12
+ @id = id
13
+ @name = name
14
+ @price = price
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,48 @@
1
+ # Mixin this module into any classes that act as an order_total.
2
+ #
3
+ # You need to overwrite the price, name and description methods
4
+ #
5
+ module ActiveCart
6
+ module OrderTotal
7
+
8
+ # Returns a boolean depending if the order total is active in this particular cart
9
+ #
10
+ # @order_total.active? # => true
11
+ #
12
+ def active?
13
+ @active || false
14
+ end
15
+
16
+ # Make a particular order_total active
17
+ #
18
+ # @order_total.active = true
19
+ # @order_total.active? # => true
20
+ #
21
+ # @order_total.active = false
22
+ # @order_total.active? # => falese
23
+ #
24
+ def active=(active)
25
+ @active = active
26
+ end
27
+
28
+ # Returns the adjustment caused by this order_total object. Takes a cart object as a parameter, allowing the object to interrogate the items in the cart.
29
+ #
30
+ # This must be overriden in the mixee class, otherwise it will throw a NotImplementedError
31
+ #
32
+ # @order.price(@cart) => 2
33
+ #
34
+ def price(cart)
35
+ raise NotImplementedError
36
+ end
37
+
38
+ # Returns the friendly name of the order total. Can be used for display (Such as on an invoices etc)
39
+ #
40
+ # This must be overriden in the mixee class, otherwise it will throw a NotImplementedError
41
+ #
42
+ # @order.name # => 'My awesome order total class'
43
+ #
44
+ def name
45
+ raise NotImplementedError
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,75 @@
1
+ module ActiveCart
2
+ class OrderTotalCollection < Array
3
+ # Returns a new OrderTotalCollection
4
+ #
5
+ # You must pass in an cart object.
6
+ #
7
+ # collection = OrderTotalCollection.new(@cart)
8
+ #
9
+ # You can also pass in an array of order_total objects
10
+ #
11
+ # cart = ActiveCart::Cart.instance
12
+ # collection = OrderTotalCollection.new(cart, order_total_1, order_total_2) # => [ order_total_1, order_total_2 ]
13
+ #
14
+ def initialize(cart, *seed)
15
+ @cart = cart
16
+ seed.each do |s|
17
+ self.push(s)
18
+ end
19
+ end
20
+
21
+ # Concatenation.Returns a new OrderTotalCollection built by concatenating the two OrderTotalCollections together to produce a third OrderTotalCollection. (The supplied collection can be a regular array)
22
+ #
23
+ # [ order_total_1, order_total_2, order_total_3 ] + [ order_total_4, order_total_5 ] #=> [ order_total_1, order_total_2, order_total_3, order_total_4, order_total_5 ]
24
+ #
25
+ def +(order_total_collection)
26
+ tmp = OrderTotalCollection.new(@cart)
27
+ self.each { |s| tmp << s }
28
+ order_total_collection.each { |s| tmp << s }
29
+ tmp
30
+ end
31
+
32
+ # Inserts the items before the item that is currently at the supplied index
33
+ #
34
+ # items = [ order_total_1, order_total_2 ]
35
+ # items.insert_before(1, order_total_2) #=> [ order_total_1, order_total_3, order_total_2 ]
36
+ #
37
+ def insert_before(index, *items)
38
+ items.reverse.each do |item|
39
+ self.insert(index, item)
40
+ end
41
+ self
42
+ end
43
+
44
+ # Inserts the items after the item that is currently at the supplied index
45
+ #
46
+ # items = [ order_total_1, order_total_2 ]
47
+ # items.insert_after(0, order_total_2) #=> [ order_total_1, order_total_3, order_total_2 ]
48
+ #
49
+ def insert_after(index, *items)
50
+ items.each_with_index do |item, i|
51
+ self.insert(index + i + 1, item)
52
+ end
53
+ self
54
+ end
55
+
56
+ # Allows you to reorder the order totals. Moves the item at index <em>from</em> to index <em>to</em>
57
+ #
58
+ # items = [ order_total_1, order_total_2 ]
59
+ # items.move(0, 1) #=> [ order_total_2, order_total_1 ]
60
+ #
61
+ def move(from, to)
62
+ index = self.delete_at(from)
63
+ self.insert(to, index)
64
+ end
65
+
66
+ # Calculates the total price applied by all the order_total objects.
67
+ #
68
+ # order_total_collection = OrderTotalCollection.new(nil, order_total_1, order_total_2)
69
+ # order_total_collection.total # => 10
70
+ #
71
+ def total
72
+ self.inject(0) { |t, calculator| t + (calculator.active? ? calculator.price(@cart) : 0) }
73
+ end
74
+ end
75
+ end
@@ -0,0 +1,14 @@
1
+ module ActiveCart
2
+ module StorageEngines
3
+ # This storage engine is probably only useful as a reference implementation (It would work in a desktop app I guess). Items only exist in memory, so
4
+ # as soon as the thread dies, so does the cart.
5
+ #
6
+ class Memory < Array
7
+ include ActiveCart::CartStorage
8
+
9
+ def invoice_id
10
+ @@last_id = @@last_id ? @@last_id + 1 : 1
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,20 @@
1
+ $:.unshift(File.join(File.dirname(__FILE__), 'active_cart'))
2
+
3
+ require 'rubygems'
4
+ require 'singleton'
5
+ require 'forwardable'
6
+ require 'state_machine'
7
+ require 'item'
8
+ require 'cart_storage'
9
+ require 'order_total'
10
+ require 'order_total_collection'
11
+ require 'cart'
12
+
13
+ require 'exceptions/out_of_stock'
14
+
15
+ require 'storage_engines/memory'
16
+ require 'items/memory_item'
17
+
18
+ module ActiveCart
19
+ VERSION = File.exist?('VERSION') ? File.read('VERSION') : ""
20
+ end
@@ -0,0 +1,4 @@
1
+ module ActiveCart
2
+ class OutOfStock < StandardError
3
+ end
4
+ end
metadata ADDED
@@ -0,0 +1,115 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: galvinhsiu-active_cart
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.19
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Myles Eftos
9
+ - Galvin Hsiu
10
+ autorequire:
11
+ bindir: bin
12
+ cert_chain: []
13
+ date: 2011-12-07 00:00:00.000000000Z
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: state_machine
17
+ requirement: &86400220 !ruby/object:Gem::Requirement
18
+ none: false
19
+ requirements:
20
+ - - ! '>='
21
+ - !ruby/object:Gem::Version
22
+ version: '0'
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: *86400220
26
+ - !ruby/object:Gem::Dependency
27
+ name: shoulda
28
+ requirement: &86400000 !ruby/object:Gem::Requirement
29
+ none: false
30
+ requirements:
31
+ - - ! '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: *86400000
37
+ - !ruby/object:Gem::Dependency
38
+ name: mocha
39
+ requirement: &86399790 !ruby/object:Gem::Requirement
40
+ none: false
41
+ requirements:
42
+ - - ! '>='
43
+ - !ruby/object:Gem::Version
44
+ version: '0'
45
+ type: :development
46
+ prerelease: false
47
+ version_requirements: *86399790
48
+ - !ruby/object:Gem::Dependency
49
+ name: machinist
50
+ requirement: &86399580 !ruby/object:Gem::Requirement
51
+ none: false
52
+ requirements:
53
+ - - ! '>='
54
+ - !ruby/object:Gem::Version
55
+ version: '0'
56
+ type: :development
57
+ prerelease: false
58
+ version_requirements: *86399580
59
+ - !ruby/object:Gem::Dependency
60
+ name: faker
61
+ requirement: &86399370 !ruby/object:Gem::Requirement
62
+ none: false
63
+ requirements:
64
+ - - ! '>='
65
+ - !ruby/object:Gem::Version
66
+ version: '0'
67
+ type: :development
68
+ prerelease: false
69
+ version_requirements: *86399370
70
+ description: ! ' You can use active_cart as the basis of a shopping cart system.
71
+ It''s not a shopping cart application - it''s a shopping cart framework.
72
+
73
+ '
74
+ email: myles@madpilot.com.au, galvinhsiu@gmail.com
75
+ executables: []
76
+ extensions: []
77
+ extra_rdoc_files: []
78
+ files:
79
+ - lib/active_cart.rb
80
+ - lib/exceptions/out_of_stock.rb
81
+ - lib/active_cart/cart.rb
82
+ - lib/active_cart/order_total_collection.rb
83
+ - lib/active_cart/cart_storage.rb
84
+ - lib/active_cart/items/memory_item.rb
85
+ - lib/active_cart/order_total.rb
86
+ - lib/active_cart/storage_engines/memory.rb
87
+ - lib/active_cart/item.rb
88
+ - galvinhsiu-active_cart.gemspec
89
+ homepage: http://gemcutter.org/gems/galvinhsiu-active_cart
90
+ licenses: []
91
+ post_install_message:
92
+ rdoc_options: []
93
+ require_paths:
94
+ - lib
95
+ required_ruby_version: !ruby/object:Gem::Requirement
96
+ none: false
97
+ requirements:
98
+ - - ! '>='
99
+ - !ruby/object:Gem::Version
100
+ version: '0'
101
+ required_rubygems_version: !ruby/object:Gem::Requirement
102
+ none: false
103
+ requirements:
104
+ - - ! '>='
105
+ - !ruby/object:Gem::Version
106
+ version: '0'
107
+ requirements: []
108
+ rubyforge_project:
109
+ rubygems_version: 1.8.12
110
+ signing_key:
111
+ specification_version: 3
112
+ summary: Shopping Cart framework gem. Supports 'storage engines' and order total plugins,
113
+ forked to use state_machine from active_cart.
114
+ test_files: []
115
+ has_rdoc: