cartman 0.2.0 → 0.3.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/.travis.yml +5 -0
- data/README.md +10 -2
- data/lib/cartman.rb +2 -1
- data/lib/cartman/cart.rb +14 -11
- data/lib/cartman/configuration.rb +4 -2
- data/lib/cartman/item.rb +34 -0
- data/lib/cartman/version.rb +1 -1
- data/spec/cart_spec.rb +24 -28
- data/spec/item_spec.rb +39 -0
- metadata +8 -4
data/.travis.yml
ADDED
data/README.md
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
# Cartman
|
2
|
+
[](http://travis-ci.org/willcosgrove/cartman)
|
2
3
|
|
3
4
|

|
4
5
|
|
@@ -26,19 +27,26 @@ Cartman has a few (read 3) configuration options you can set, most likely in an
|
|
26
27
|
# config/initializers/cartman.rb
|
27
28
|
Cartman.config do
|
28
29
|
cart_expires_in 604800 # one week, in seconds. This is the default
|
29
|
-
return_items_as :openstruct # vs a :hash
|
30
30
|
cost_field :cost # for cart totaling
|
31
|
+
redis Redis.new # set the redis connection here
|
31
32
|
end
|
32
33
|
```
|
33
34
|
|
34
35
|
- The `cart_expires_in` setting will let you set how long a cart should live. If no items are added to the cart before the time expires, the cart will be cleared. If you want to disable cart expiration, set this to `-1`.
|
35
|
-
- `return_items_as` lets you set how you want Cartman to return your items as. You can choose either an `OpenStruct` or a `Hash`.
|
36
36
|
- `cost_field` lets you tell Cartman where you're storing the "cost" of each item, so that when you call `cart.total` it knows which values to sum.
|
37
37
|
|
38
38
|
## Usage
|
39
39
|
|
40
40
|
To create a new shopping cart, just call `Cartman::Cart.new(user.id)`. The parameter for `Cart.new()` is a unique id. If you don't want a user to have more than one cart at a time, it's generally best to set this to the user's id. Then to add an item to the cart, just call `cart.add_item(data)` which takes a hash of data that you want to store. Then to retrieve the items, you just call `cart.items` which will give you an array of all the items they've added.
|
41
41
|
|
42
|
+
The returned Items come back as `Cartman::Item` instances, which have a few special methods to be aware of:
|
43
|
+
|
44
|
+
- `remove` - which will remove the item from the cart
|
45
|
+
- `cart` - which will return the parent cart, think ActiveRecord association
|
46
|
+
- `_id` - which will return the id of the item, if you need that for whatever reason
|
47
|
+
- `_key` - which will return the redis key the data is stored in. Probably won't need that, but it's there.
|
48
|
+
- `#{attribute}=` - this is a setter defined for all of the items attributes that you gave it. It will instantly save to redis also, so no need to call `save` (which is why there isn't a `save`).
|
49
|
+
|
42
50
|
Lets walk through an example implementation with a Rails app that has a User model and a Product model.
|
43
51
|
|
44
52
|
```ruby
|
data/lib/cartman.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
require "cartman/version"
|
2
2
|
require "cartman/configuration"
|
3
3
|
require "cartman/cart"
|
4
|
+
require "cartman/item"
|
4
5
|
require 'redis'
|
5
6
|
require 'ostruct'
|
6
7
|
|
@@ -10,7 +11,7 @@ module Cartman
|
|
10
11
|
if block_given?
|
11
12
|
@config = Configuration.new(&block)
|
12
13
|
else
|
13
|
-
@config
|
14
|
+
@config ||= Configuration.new
|
14
15
|
end
|
15
16
|
end
|
16
17
|
end
|
data/lib/cartman/cart.rb
CHANGED
@@ -18,23 +18,22 @@ module Cartman
|
|
18
18
|
@@redis.expire item, Cartman::Configuration.cart_expires_in
|
19
19
|
end
|
20
20
|
end
|
21
|
+
get_item(line_item_id)
|
21
22
|
end
|
22
23
|
|
23
|
-
def
|
24
|
-
|
25
|
-
|
24
|
+
def remove_item(item)
|
25
|
+
@@redis.del "cartman:line_item:#{item._id}"
|
26
|
+
@@redis.srem key, item._id
|
27
|
+
end
|
28
|
+
|
29
|
+
def items
|
30
|
+
items = line_item_ids.collect { |item_id|
|
31
|
+
get_item(item_id)
|
26
32
|
}
|
27
|
-
if return_as == :openstruct
|
28
|
-
items.collect { |item|
|
29
|
-
OpenStruct.new(item)
|
30
|
-
}
|
31
|
-
else
|
32
|
-
items
|
33
|
-
end
|
34
33
|
end
|
35
34
|
|
36
35
|
def total
|
37
|
-
items
|
36
|
+
items.collect { |item|
|
38
37
|
(item.send(Cartman::Configuration.cost_field).to_f * 100).to_i
|
39
38
|
}.inject{|sum,cost| sum += cost} / 100.0
|
40
39
|
end
|
@@ -56,5 +55,9 @@ module Cartman
|
|
56
55
|
def line_item_keys
|
57
56
|
line_item_ids.collect{ |id| "cartman:line_item:#{id}" }
|
58
57
|
end
|
58
|
+
|
59
|
+
def get_item(id)
|
60
|
+
Item.new(id, @uid, @@redis.hgetall("cartman:line_item:#{id}").inject({}){|memo,(k,v)| memo[k.to_sym] = v; memo})
|
61
|
+
end
|
59
62
|
end
|
60
63
|
end
|
@@ -1,13 +1,15 @@
|
|
1
|
+
require 'redis'
|
2
|
+
|
1
3
|
module Cartman
|
2
4
|
class Configuration
|
3
5
|
@@configuration = {
|
4
6
|
cart_expires_in: 604800, # one week
|
5
|
-
return_items_as: :openstruct, # vs a :hash
|
6
7
|
cost_field: :cost, # for cart totaling
|
8
|
+
redis: Redis.new, # Redis connection
|
7
9
|
}
|
8
10
|
|
9
11
|
def initialize(&block)
|
10
|
-
instance_eval &block
|
12
|
+
instance_eval &block if block_given?
|
11
13
|
end
|
12
14
|
|
13
15
|
def method_missing(method, *args, &block)
|
data/lib/cartman/item.rb
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
module Cartman
|
2
|
+
class Item
|
3
|
+
def initialize(item_id, cart_id, data)
|
4
|
+
@id = item_id
|
5
|
+
@cart_id = cart_id
|
6
|
+
@data = data
|
7
|
+
end
|
8
|
+
|
9
|
+
def _id
|
10
|
+
@id
|
11
|
+
end
|
12
|
+
|
13
|
+
def cart
|
14
|
+
@cart ||= Cart.new(@cart_id)
|
15
|
+
end
|
16
|
+
|
17
|
+
def remove
|
18
|
+
cart.remove_item(self)
|
19
|
+
end
|
20
|
+
|
21
|
+
def _key
|
22
|
+
"cartman:line_item:#{@id}"
|
23
|
+
end
|
24
|
+
|
25
|
+
def method_missing(method, *args, &block)
|
26
|
+
if method.to_s =~ /=\z/
|
27
|
+
Cartman::Configuration.redis.hset _key, method[0..-2], args[0].to_s
|
28
|
+
@data.store(method[0..-2].to_sym, args[0].to_s)
|
29
|
+
else
|
30
|
+
@data.fetch(method)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
data/lib/cartman/version.rb
CHANGED
data/spec/cart_spec.rb
CHANGED
@@ -4,12 +4,6 @@ describe Cartman do
|
|
4
4
|
describe Cartman::Cart do
|
5
5
|
let(:cart) { Cartman::Cart.new(1) }
|
6
6
|
|
7
|
-
before(:all) do
|
8
|
-
Cartman.config do
|
9
|
-
redis Redis.new
|
10
|
-
end
|
11
|
-
end
|
12
|
-
|
13
7
|
before(:each) do
|
14
8
|
Cartman.config.redis.flushdb
|
15
9
|
end
|
@@ -22,7 +16,7 @@ describe Cartman do
|
|
22
16
|
|
23
17
|
describe "#add_item" do
|
24
18
|
before(:each) do
|
25
|
-
cart.add_item(id: 17,
|
19
|
+
cart.add_item(id: 17, type: "Bottle", name: "Bordeux", unit_cost: 92.12, cost: 184.24, quantity: 2)
|
26
20
|
end
|
27
21
|
|
28
22
|
it "creates a line item key" do
|
@@ -37,29 +31,31 @@ describe Cartman do
|
|
37
31
|
cart.ttl.should eq(Cartman.config.cart_expires_in)
|
38
32
|
Cartman.config.redis.ttl("cartman:line_item:1").should eq(Cartman.config.cart_expires_in)
|
39
33
|
end
|
34
|
+
|
35
|
+
it "should return an Item" do
|
36
|
+
item = cart.add_item(id: 34, type: "Bottle", name: "Cabernet", unit_cost: 92.12, cost: 184.24, quantity: 2)
|
37
|
+
item.class.should eq(Cartman::Item)
|
38
|
+
end
|
40
39
|
end
|
41
40
|
|
42
|
-
describe "#
|
43
|
-
|
44
|
-
cart.add_item(id: 17,
|
45
|
-
|
41
|
+
describe "#remove_item" do
|
42
|
+
it "should remove the id from the set, and delete the line_item key" do
|
43
|
+
item = cart.add_item(id: 17, type: "Bottle", name: "Bordeux", unit_cost: 92.12, cost: 184.24, quantity: 2)
|
44
|
+
item_id = item._id
|
45
|
+
cart.remove_item(item)
|
46
|
+
Cartman.config.redis.sismember(cart.send(:key), item_id).should be_false
|
47
|
+
Cartman.config.redis.exists("cartman:line_item:#{item_id}").should be_false
|
46
48
|
end
|
49
|
+
end
|
47
50
|
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
cart.items.class.should eq(Array)
|
53
|
-
cart.items.first.class.should eq(Hash)
|
54
|
-
cart.items.size.should eq(2)
|
55
|
-
cart.items.first[:id].should eq("17")
|
51
|
+
describe "#items" do
|
52
|
+
before(:each) do
|
53
|
+
cart.add_item(id: 17, type: "Bottle", name: "Bordeux", unit_cost: 92.12, cost: 184.24, quantity: 2)
|
54
|
+
cart.add_item(id: 34, type: "Bottle", name: "Cabernet", unit_cost: 92.12, cost: 184.24, quantity: 2)
|
56
55
|
end
|
57
56
|
|
58
|
-
it "should return an array of
|
59
|
-
|
60
|
-
return_items_as :openstruct
|
61
|
-
end
|
62
|
-
cart.items.first.class.should eq(OpenStruct)
|
57
|
+
it "should return an array of Items" do
|
58
|
+
cart.items.first.class.should eq(Cartman::Item)
|
63
59
|
cart.items.first.id.should eq("17")
|
64
60
|
cart.items.first.name.should eq("Bordeux")
|
65
61
|
end
|
@@ -67,8 +63,8 @@ describe Cartman do
|
|
67
63
|
|
68
64
|
describe "#total" do
|
69
65
|
it "should total the default costs field" do
|
70
|
-
cart.add_item(id: 17,
|
71
|
-
cart.add_item(id: 34,
|
66
|
+
cart.add_item(id: 17, type: "Bottle", name: "Bordeux", unit_cost: 92.12, cost: 184.24, quantity: 2)
|
67
|
+
cart.add_item(id: 34, type: "Bottle", name: "Cabernet", unit_cost: 92.12, cost: 184.24, quantity: 2)
|
72
68
|
cart.total.should eq(368.48)
|
73
69
|
end
|
74
70
|
|
@@ -76,8 +72,8 @@ describe Cartman do
|
|
76
72
|
Cartman.config do
|
77
73
|
cost_field :cost_in_cents
|
78
74
|
end
|
79
|
-
cart.add_item(id: 17,
|
80
|
-
cart.add_item(id: 34,
|
75
|
+
cart.add_item(id: 17, type: "Bottle", name: "Bordeux", unit_cost: 92.12, cost_in_cents: 18424, quantity: 2)
|
76
|
+
cart.add_item(id: 34, type: "Bottle", name: "Cabernet", unit_cost: 92.12, cost_in_cents: 18424, quantity: 2)
|
81
77
|
cart.total.should eq(36848)
|
82
78
|
end
|
83
79
|
end
|
data/spec/item_spec.rb
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Cartman do
|
4
|
+
describe Cartman::Item do
|
5
|
+
let(:cart) { Cartman::Cart.new(1) }
|
6
|
+
let(:item) { cart.add_item(id: 17, type: "Bottle", name: "Bordeux", unit_cost: 92.12, cost: 184.24, quantity: 2) }
|
7
|
+
|
8
|
+
describe "data getters and setters" do
|
9
|
+
it "should let me get data stored for the item" do
|
10
|
+
item.id.should eq("17")
|
11
|
+
item.type.should eq("Bottle")
|
12
|
+
item.cost.should eq("184.24")
|
13
|
+
end
|
14
|
+
|
15
|
+
it "should let me modify data stored for the item" do
|
16
|
+
item.quantity.should eq("2")
|
17
|
+
item.quantity = 3
|
18
|
+
item.quantity.should eq("3")
|
19
|
+
end
|
20
|
+
|
21
|
+
it "should immediately save data back to redis" do
|
22
|
+
item.quantity.should eq("2")
|
23
|
+
item.quantity = 3
|
24
|
+
new_item = cart.send(:get_item, item._id)
|
25
|
+
new_item.quantity.should eq("3")
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
describe "#remove" do
|
30
|
+
it "should remove the item from the cart" do
|
31
|
+
item_id = item._id
|
32
|
+
item.remove
|
33
|
+
Cartman.config.redis.sismember(cart.send(:key), item_id).should be_false
|
34
|
+
Cartman.config.redis.exists("cartman:line_item:#{item_id}").should be_false
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
39
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: cartman
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-10-
|
12
|
+
date: 2012-10-23 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: redis
|
@@ -51,6 +51,7 @@ extensions: []
|
|
51
51
|
extra_rdoc_files: []
|
52
52
|
files:
|
53
53
|
- .gitignore
|
54
|
+
- .travis.yml
|
54
55
|
- Gemfile
|
55
56
|
- LICENSE.txt
|
56
57
|
- README.md
|
@@ -59,8 +60,10 @@ files:
|
|
59
60
|
- lib/cartman.rb
|
60
61
|
- lib/cartman/cart.rb
|
61
62
|
- lib/cartman/configuration.rb
|
63
|
+
- lib/cartman/item.rb
|
62
64
|
- lib/cartman/version.rb
|
63
65
|
- spec/cart_spec.rb
|
66
|
+
- spec/item_spec.rb
|
64
67
|
- spec/spec_helper.rb
|
65
68
|
homepage: http://github.com/willcosgrove/cartman
|
66
69
|
licenses: []
|
@@ -76,7 +79,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
76
79
|
version: '0'
|
77
80
|
segments:
|
78
81
|
- 0
|
79
|
-
hash:
|
82
|
+
hash: 3094534765024072547
|
80
83
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
81
84
|
none: false
|
82
85
|
requirements:
|
@@ -85,7 +88,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
85
88
|
version: '0'
|
86
89
|
segments:
|
87
90
|
- 0
|
88
|
-
hash:
|
91
|
+
hash: 3094534765024072547
|
89
92
|
requirements: []
|
90
93
|
rubyforge_project:
|
91
94
|
rubygems_version: 1.8.23
|
@@ -94,4 +97,5 @@ specification_version: 3
|
|
94
97
|
summary: Doing shopping carts like a boss since 2012
|
95
98
|
test_files:
|
96
99
|
- spec/cart_spec.rb
|
100
|
+
- spec/item_spec.rb
|
97
101
|
- spec/spec_helper.rb
|