ecart 0.0.1
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 +6 -0
- data/.rspec +2 -0
- data/.travis.yml +5 -0
- data/Gemfile +4 -0
- data/README.md +102 -0
- data/Rakefile +17 -0
- data/ecart.gemspec +25 -0
- data/lib/cart.rb +55 -0
- data/lib/cart_item.rb +16 -0
- data/lib/ecart.rb +4 -0
- data/lib/ecart/version.rb +3 -0
- data/lib/generators/ecart/install/install_generator.rb +34 -0
- data/lib/generators/templates/cart_controller.rb +21 -0
- data/lib/generators/templates/cart_helper.rb +35 -0
- data/lib/item.rb +10 -0
- data/spec/cart_spec.rb +127 -0
- data/spec/spec_helper.rb +17 -0
- metadata +86 -0
data/.gitignore
ADDED
data/.rspec
ADDED
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/README.md
ADDED
@@ -0,0 +1,102 @@
|
|
1
|
+
# Ecart for Rails 3.0 - An e-commerce cart
|
2
|
+
Ecart is a simple solution for integrating a cart when you are building
|
3
|
+
an online store from scratch, and want to add this functionality
|
4
|
+
|
5
|
+
Ecart project integrates a cart to a rails app
|
6
|
+
|
7
|
+
[](http://travis-ci.org/kurenn/ecart)
|
8
|
+
|
9
|
+
## Installing Gem
|
10
|
+
|
11
|
+
Include Ecart in Gemfile;
|
12
|
+
|
13
|
+
```ruby
|
14
|
+
gem "ecart"
|
15
|
+
```
|
16
|
+
|
17
|
+
or you can install from latest build;
|
18
|
+
|
19
|
+
```ruby
|
20
|
+
gem 'ecart', :git => 'git@github.com:kurenn/ecart.git'
|
21
|
+
```
|
22
|
+
|
23
|
+
You can run bundle from command line
|
24
|
+
|
25
|
+
bundle install
|
26
|
+
|
27
|
+
## Before installing
|
28
|
+
|
29
|
+
I'm assuming you have a Product model on your rails app, but don't worry
|
30
|
+
if that's not the case you can customize it as you like
|
31
|
+
|
32
|
+
## Installing to App (using Generators)
|
33
|
+
|
34
|
+
You can run following generators to get started with Ecart quickly.
|
35
|
+
|
36
|
+
|
37
|
+
Install
|
38
|
+
|
39
|
+
|
40
|
+
Usage:
|
41
|
+
|
42
|
+
|
43
|
+
rails g ecart:install
|
44
|
+
|
45
|
+
This will generate several files that will handle all the cart logic
|
46
|
+
(which you can customize later)
|
47
|
+
|
48
|
+
## Don't forget to let know rails to load the lib directory
|
49
|
+
|
50
|
+
You can do so in the config/application.rb file
|
51
|
+
|
52
|
+
```ruby
|
53
|
+
config.autoload_paths += Dir["#{config.root}/lib", "#{config.root}/lib/**/"]
|
54
|
+
```
|
55
|
+
|
56
|
+
## Changelog
|
57
|
+
<ul>
|
58
|
+
<li>Current gem v.0.0.1</li>
|
59
|
+
</ul>
|
60
|
+
|
61
|
+
|
62
|
+
## Contributors & Patches & Forks
|
63
|
+
<ul>
|
64
|
+
<li>Abraham Kuri Vargas (@kurenn)</li>
|
65
|
+
</ul>
|
66
|
+
|
67
|
+
|
68
|
+
## Future
|
69
|
+
<ul>
|
70
|
+
<li>Add dinamic association with a model</li>
|
71
|
+
<li>Update the price by fetching from DB</li>
|
72
|
+
<li>Provide views for the cart</li>
|
73
|
+
</ul>
|
74
|
+
|
75
|
+
|
76
|
+
## Credits
|
77
|
+
Abraham Kuri - kurenn@icalialabs.com
|
78
|
+
|
79
|
+
[Add Me On Twitter](http://twitter.com/kurenn "Follow me")
|
80
|
+
|
81
|
+
[Add Me On Linkedin](http://www.linkedin.com/pub/abraham-kuri/26/a21/b41 "Add Me On Linkedin")
|
82
|
+
|
83
|
+
[Add Me On Facebook](https://www.facebook.com/kurenn "Add Me On Facebook")
|
84
|
+
|
85
|
+
|
86
|
+
## Score me
|
87
|
+
<img src="https://addons.opera.com/media/extensions/55/14355/1.0.1-rev1/icons/icon_64x64.png"></img>
|
88
|
+
|
89
|
+
You can +K my influence in Ruby on Rails on @klout
|
90
|
+
|
91
|
+
http://klout.com/#/kurenn
|
92
|
+
|
93
|
+
|
94
|
+
## License
|
95
|
+
Copyright (c) 2011 Abraham Kuri Vargas
|
96
|
+
|
97
|
+
This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
|
98
|
+
|
99
|
+
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
100
|
+
|
101
|
+
You should have received a copy of the GNU General Public License along with this program. If not, see http://www.gnu.org/licenses/gpl.html.
|
102
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
#!/usr/bin/env rake
|
2
|
+
require "bundler"
|
3
|
+
|
4
|
+
Bundler::GemHelper.install_tasks
|
5
|
+
|
6
|
+
desc "Bundle the gem"
|
7
|
+
|
8
|
+
task :bundle do
|
9
|
+
sh('bundle install')
|
10
|
+
sh 'gem build *.gemspec'
|
11
|
+
sh 'gem install *.gem'
|
12
|
+
sh 'rm *.gem'
|
13
|
+
end
|
14
|
+
|
15
|
+
task(:default).clear
|
16
|
+
task :default => :bundle
|
17
|
+
|
data/ecart.gemspec
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "ecart/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "ecart"
|
7
|
+
s.version = Ecart::VERSION
|
8
|
+
s.authors = ["Abraham Kuri"]
|
9
|
+
s.email = ["kurenn@icalialabs.com"]
|
10
|
+
s.homepage = "https://github.com/kurenn/ecart"
|
11
|
+
s.summary = %q{E-commerce cart with rails}
|
12
|
+
s.description = %q{Setup a fully functional e-commerce cart}
|
13
|
+
|
14
|
+
s.rubyforge_project = "ecart"
|
15
|
+
|
16
|
+
s.files = `git ls-files`.split("\n")
|
17
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
18
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
19
|
+
s.require_paths = ["lib"]
|
20
|
+
|
21
|
+
# specify any dependencies here; for example:
|
22
|
+
s.add_development_dependency 'rails', '>= 3.1'
|
23
|
+
s.add_development_dependency "rspec"
|
24
|
+
# s.add_runtime_dependency "rest-client"
|
25
|
+
end
|
data/lib/cart.rb
ADDED
@@ -0,0 +1,55 @@
|
|
1
|
+
class Cart
|
2
|
+
attr_reader :cart_items
|
3
|
+
|
4
|
+
def initialize
|
5
|
+
@cart_items = []
|
6
|
+
end
|
7
|
+
|
8
|
+
def add_item(item)
|
9
|
+
cart_item = find_item(item)
|
10
|
+
if !cart_item.nil?
|
11
|
+
cart_item.increment_quantity
|
12
|
+
else
|
13
|
+
@cart_items << CartItem.new(item)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def items
|
18
|
+
@cart_items.map(&:item)
|
19
|
+
end
|
20
|
+
|
21
|
+
def find_item(item)
|
22
|
+
@cart_items.find {|cart_item| cart_item.item.id == item.id }
|
23
|
+
end
|
24
|
+
|
25
|
+
def total
|
26
|
+
total = 0.0
|
27
|
+
@cart_items.each do |cart_item|
|
28
|
+
total += (cart_item.item.price * cart_item.quantity)
|
29
|
+
end
|
30
|
+
total
|
31
|
+
end
|
32
|
+
|
33
|
+
def total_items
|
34
|
+
@cart_items.map(&:quantity).inject{|sum, q| sum + q}.to_i
|
35
|
+
end
|
36
|
+
|
37
|
+
def remove_item(item)
|
38
|
+
cart_item = find_item(item)
|
39
|
+
if cart_item.quantity > 1
|
40
|
+
cart_item.decrease_quantity
|
41
|
+
else
|
42
|
+
@cart_items.delete_if {|ci| ci == cart_item}
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def remove_item!(item)
|
47
|
+
cart_item = find_item(item)
|
48
|
+
@cart_items.delete_if { |ci| ci == cart_item }
|
49
|
+
end
|
50
|
+
|
51
|
+
def empty?
|
52
|
+
self.total_items.zero?
|
53
|
+
end
|
54
|
+
|
55
|
+
end
|
data/lib/cart_item.rb
ADDED
data/lib/ecart.rb
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'rails/generators'
|
2
|
+
|
3
|
+
module Ecart
|
4
|
+
module Generators
|
5
|
+
class InstallGenerator < ::Rails::Generators::Base
|
6
|
+
source_root File.expand_path("../../../../../lib", __FILE__)
|
7
|
+
|
8
|
+
desc 'This generator install the class cart and cartitem to the lib directory of a rails app'
|
9
|
+
|
10
|
+
def add_ecart
|
11
|
+
copy_file 'cart.rb', 'lib/cart.rb'
|
12
|
+
copy_file 'cart_item.rb', 'lib/cart_item.rb'
|
13
|
+
copy_file 'generators/templates/cart_helper.rb', 'app/helpers/cart_helper.rb'
|
14
|
+
copy_file 'generators/templates/cart_controller.rb', 'app/controllers/cart_controller.rb'
|
15
|
+
end
|
16
|
+
|
17
|
+
def add_ecart_routes
|
18
|
+
app = ::Rails.application
|
19
|
+
@app_name = app.class.to_s.split("::").first
|
20
|
+
insert_into_file 'config/routes.rb', routes, :after => "#{@app_name}::Application.routes.draw do"
|
21
|
+
insert_into_file 'app/controllers/application_controller.rb', "\n\tinclude CartHelper", :after => 'protect_from_forgery'
|
22
|
+
end
|
23
|
+
|
24
|
+
def routes
|
25
|
+
<<CONTENT
|
26
|
+
|
27
|
+
match 'add_to_cart/:id' => 'cart#add_to_cart', :as => :add_to_cart
|
28
|
+
match 'remove_from_cart/:id' => 'cart#remove_from_cart', :as => :remove_from_cart
|
29
|
+
match 'empty_cart' => 'cart#empty', :as => :empty_cart
|
30
|
+
CONTENT
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
class CartController < ApplicationController
|
2
|
+
|
3
|
+
def add_to_cart
|
4
|
+
product = Product.find(params[:id])
|
5
|
+
@cart = find_cart
|
6
|
+
@cart.add_item(product)
|
7
|
+
redirect_to :back
|
8
|
+
end
|
9
|
+
|
10
|
+
def remove_from_cart
|
11
|
+
product = Product.find(params[:id])
|
12
|
+
@cart = find_cart
|
13
|
+
@cart.remove_item(product)
|
14
|
+
redirect_to :back
|
15
|
+
end
|
16
|
+
|
17
|
+
def empty
|
18
|
+
empty_cart
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module CartHelper
|
2
|
+
|
3
|
+
#Find the cart
|
4
|
+
def find_cart
|
5
|
+
session[:cart] ||= Cart.new
|
6
|
+
end
|
7
|
+
|
8
|
+
#Cleans up the cart
|
9
|
+
def empty_cart
|
10
|
+
session[:cart] = nil
|
11
|
+
flash[:notice] = "Your cart is empty"
|
12
|
+
redirect_to :back
|
13
|
+
end
|
14
|
+
|
15
|
+
#Link to empty the cart
|
16
|
+
def link_to_empty_cart
|
17
|
+
link_to "Empty the car", empty_cart_path
|
18
|
+
end
|
19
|
+
|
20
|
+
#Link to add to cart
|
21
|
+
def link_to_add_to_cart(product)
|
22
|
+
link_to "Add to cart", add_to_cart_path(product.id)
|
23
|
+
end
|
24
|
+
|
25
|
+
#Link to remove from cart
|
26
|
+
def link_to_remove_from_cart(product)
|
27
|
+
link_to "Remove from cart", remove_from_cart_path(product.id) if find_cart.find_item(product)
|
28
|
+
end
|
29
|
+
|
30
|
+
#Returns the cart
|
31
|
+
def cart
|
32
|
+
find_cart
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
data/lib/item.rb
ADDED
data/spec/cart_spec.rb
ADDED
@@ -0,0 +1,127 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'cart'
|
3
|
+
require 'item'
|
4
|
+
require 'cart_item'
|
5
|
+
|
6
|
+
|
7
|
+
describe Cart do
|
8
|
+
let(:cart) { Cart.new }
|
9
|
+
|
10
|
+
it 'should initialize with an empty array of items' do
|
11
|
+
cart.items.should == []
|
12
|
+
end
|
13
|
+
|
14
|
+
describe '#add_item' do
|
15
|
+
it 'should add the id of the item to the cart' do
|
16
|
+
item = Item.new({:id => 1})
|
17
|
+
cart.add_item(item)
|
18
|
+
cart.items.should include(item)
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'should increment the quantity of the item if it exists' do
|
22
|
+
item = Item.new({:id => 1})
|
23
|
+
other_item = Item.new({:id => 1})
|
24
|
+
cart.add_item(item)
|
25
|
+
cart.add_item(other_item)
|
26
|
+
cart.cart_items.first.quantity.should == 2
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
describe '#find_item' do
|
31
|
+
it 'should return nil if no object found' do
|
32
|
+
item = Item.new({:id => 1})
|
33
|
+
cart.find_item(item).should be_nil
|
34
|
+
end
|
35
|
+
|
36
|
+
it 'should return the cart item when item is found' do
|
37
|
+
item = Item.new({:id => 1})
|
38
|
+
cart.add_item(item)
|
39
|
+
cart.find_item(item).should_not be_nil
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
describe '#total' do
|
44
|
+
it 'should return 0.0 when no cart items' do
|
45
|
+
cart.total.should == 0.0
|
46
|
+
end
|
47
|
+
|
48
|
+
it 'should return the total of the cart' do
|
49
|
+
cart.add_item(Item.new({:id => 1, :price => 12.5, :name => "Ball"}))
|
50
|
+
cart.add_item(Item.new({:id => 2, :price => 10, :name => "Soccer ball"}))
|
51
|
+
cart.add_item(Item.new({:id => 2}))
|
52
|
+
cart.total.should == 32.5
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
describe '#remove_item' do
|
57
|
+
it 'removes the item from the cart' do
|
58
|
+
item = Item.new({:id => 1})
|
59
|
+
cart.add_item(item)
|
60
|
+
cart.remove_item(item)
|
61
|
+
cart.items.should_not include(item)
|
62
|
+
end
|
63
|
+
|
64
|
+
it 'should decrease the quantity of the cart_item' do
|
65
|
+
item = Item.new({:id => 2, :price => 10, :name => "Soccer ball"})
|
66
|
+
cart.add_item(item)
|
67
|
+
cart.add_item(item)
|
68
|
+
cart.remove_item(item)
|
69
|
+
cart.items.should include(item)
|
70
|
+
cart.find_item(item).quantity.should == 1
|
71
|
+
end
|
72
|
+
|
73
|
+
it 'should delete the item when there is just one' do
|
74
|
+
item = Item.new({:id => 2, :price => 10, :name => "Soccer ball"})
|
75
|
+
cart.add_item(item)
|
76
|
+
cart.remove_item(item)
|
77
|
+
cart.items.should_not include(item)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
describe '#remove_item!' do
|
82
|
+
|
83
|
+
it 'should remove the item no matter what' do
|
84
|
+
item = Item.new({:id => 1})
|
85
|
+
cart.add_item(item)
|
86
|
+
cart.add_item(item)
|
87
|
+
cart.remove_item!(item)
|
88
|
+
cart.items.should_not include(item)
|
89
|
+
end
|
90
|
+
|
91
|
+
it 'should remove only if the cart item is in the cart' do
|
92
|
+
item = Item.new({:id => 1})
|
93
|
+
cart.remove_item!(item).should be_empty
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
describe '#total_items' do
|
98
|
+
|
99
|
+
it 'should return the total number of items in the cart' do
|
100
|
+
item = Item.new({:id => 1})
|
101
|
+
other_item = Item.new({:id => 2})
|
102
|
+
cart.add_item(item)
|
103
|
+
cart.add_item(other_item)
|
104
|
+
cart.add_item(item)
|
105
|
+
cart.total_items.should == 3
|
106
|
+
end
|
107
|
+
|
108
|
+
it 'should return 0 if no items in the cart' do
|
109
|
+
cart.total_items.should == 0
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
describe '#empty?' do
|
114
|
+
|
115
|
+
it 'should return true if cart is empty' do
|
116
|
+
cart.should be_empty
|
117
|
+
end
|
118
|
+
|
119
|
+
it 'should return false if the cart is not empty' do
|
120
|
+
item = Item.new({:id => 1})
|
121
|
+
cart.add_item(item)
|
122
|
+
cart.should_not be_empty
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
end
|
127
|
+
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
# This file was generated by the `rspec --init` command. Conventionally, all
|
2
|
+
# specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
|
3
|
+
# Require this file using `require "spec_helper"` to ensure that it is only
|
4
|
+
# loaded once.
|
5
|
+
#
|
6
|
+
# See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
|
7
|
+
RSpec.configure do |config|
|
8
|
+
config.treat_symbols_as_metadata_keys_with_true_values = true
|
9
|
+
config.run_all_when_everything_filtered = true
|
10
|
+
config.filter_run :focus
|
11
|
+
|
12
|
+
# Run specs in random order to surface order dependencies. If you find an
|
13
|
+
# order dependency and want to debug it, you can fix the order by providing
|
14
|
+
# the seed, which is printed after each run.
|
15
|
+
# --seed 1234
|
16
|
+
config.order = 'random'
|
17
|
+
end
|
metadata
ADDED
@@ -0,0 +1,86 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: ecart
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Abraham Kuri
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-07-09 00:00:00.000000000Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: rails
|
16
|
+
requirement: &70212394340520 !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '3.1'
|
22
|
+
type: :development
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: *70212394340520
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: rspec
|
27
|
+
requirement: &70212394339800 !ruby/object:Gem::Requirement
|
28
|
+
none: false
|
29
|
+
requirements:
|
30
|
+
- - ! '>='
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '0'
|
33
|
+
type: :development
|
34
|
+
prerelease: false
|
35
|
+
version_requirements: *70212394339800
|
36
|
+
description: Setup a fully functional e-commerce cart
|
37
|
+
email:
|
38
|
+
- kurenn@icalialabs.com
|
39
|
+
executables: []
|
40
|
+
extensions: []
|
41
|
+
extra_rdoc_files: []
|
42
|
+
files:
|
43
|
+
- .gitignore
|
44
|
+
- .rspec
|
45
|
+
- .travis.yml
|
46
|
+
- Gemfile
|
47
|
+
- README.md
|
48
|
+
- Rakefile
|
49
|
+
- ecart.gemspec
|
50
|
+
- lib/cart.rb
|
51
|
+
- lib/cart_item.rb
|
52
|
+
- lib/ecart.rb
|
53
|
+
- lib/ecart/version.rb
|
54
|
+
- lib/generators/ecart/install/install_generator.rb
|
55
|
+
- lib/generators/templates/cart_controller.rb
|
56
|
+
- lib/generators/templates/cart_helper.rb
|
57
|
+
- lib/item.rb
|
58
|
+
- spec/cart_spec.rb
|
59
|
+
- spec/spec_helper.rb
|
60
|
+
homepage: https://github.com/kurenn/ecart
|
61
|
+
licenses: []
|
62
|
+
post_install_message:
|
63
|
+
rdoc_options: []
|
64
|
+
require_paths:
|
65
|
+
- lib
|
66
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
67
|
+
none: false
|
68
|
+
requirements:
|
69
|
+
- - ! '>='
|
70
|
+
- !ruby/object:Gem::Version
|
71
|
+
version: '0'
|
72
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
74
|
+
requirements:
|
75
|
+
- - ! '>='
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: '0'
|
78
|
+
requirements: []
|
79
|
+
rubyforge_project: ecart
|
80
|
+
rubygems_version: 1.8.12
|
81
|
+
signing_key:
|
82
|
+
specification_version: 3
|
83
|
+
summary: E-commerce cart with rails
|
84
|
+
test_files:
|
85
|
+
- spec/cart_spec.rb
|
86
|
+
- spec/spec_helper.rb
|