cartman 0.2.0 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
data/.travis.yml ADDED
@@ -0,0 +1,5 @@
1
+ language: ruby
2
+ rvm:
3
+ - "1.9.2"
4
+ - "1.9.3"
5
+ script: bundle exec rspec spec
data/README.md CHANGED
@@ -1,4 +1,5 @@
1
1
  # Cartman
2
+ [![Build Status](https://secure.travis-ci.org/willcosgrove/cartman.png)](http://travis-ci.org/willcosgrove/cartman)
2
3
 
3
4
  ![](http://blog.brightcove.com/sites/all/uploads/eric_theodore_cartman_southpark.jpg)
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 items(return_as=Cartman::Configuration.return_items_as)
24
- items = line_item_keys.collect { |item_key|
25
- @@redis.hgetall(item_key).inject({}){|memo,(k,v)| memo[k.to_sym] = v; memo} # symbolize keys
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(:openstruct).collect { |item|
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)
@@ -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
@@ -1,3 +1,3 @@
1
1
  module Cartman
2
- VERSION = "0.2.0"
2
+ VERSION = "0.3.0"
3
3
  end
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, class: "Bottle", name: "Bordeux", unit_cost: 92.12, cost: 184.24, quantity: 2)
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 "#items" do
43
- before(:each) do
44
- cart.add_item(id: 17, class: "Bottle", name: "Bordeux", unit_cost: 92.12, cost: 184.24, quantity: 2)
45
- cart.add_item(id: 34, class: "Bottle", name: "Cabernet", unit_cost: 92.12, cost: 184.24, quantity: 2)
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
- it "should return an array of hashes if config hashes is set" do
49
- Cartman.config do
50
- return_items_as :hash
51
- end
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 openstructs if no return type is set" do
59
- Cartman.config do
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, class: "Bottle", name: "Bordeux", unit_cost: 92.12, cost: 184.24, quantity: 2)
71
- cart.add_item(id: 34, class: "Bottle", name: "Cabernet", unit_cost: 92.12, cost: 184.24, quantity: 2)
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, class: "Bottle", name: "Bordeux", unit_cost: 92.12, cost_in_cents: 18424, quantity: 2)
80
- cart.add_item(id: 34, class: "Bottle", name: "Cabernet", unit_cost: 92.12, cost_in_cents: 18424, quantity: 2)
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.2.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-21 00:00:00.000000000 Z
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: 1736743105413686891
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: 1736743105413686891
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