shop_bunny 0.7.1 → 0.7.3
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/app/controllers/carts_controller.rb +1 -50
- data/app/models/cart.rb +1 -119
- data/config/initializers/shop_bunny.rb +0 -6
- data/config/routes.rb +2 -1
- data/lib/generators/shop_bunny/install_generator.rb +6 -1
- data/lib/generators/shop_bunny/templates/shopbunny_controller_template.rb +3 -0
- data/lib/generators/shop_bunny/templates/shopbunny_model_template.rb +3 -0
- data/lib/shop_bunny/cart_controller_module.rb +53 -0
- data/lib/shop_bunny/cart_module.rb +130 -0
- data/lib/shop_bunny.rb +2 -0
- metadata +16 -12
|
@@ -1,53 +1,4 @@
|
|
|
1
1
|
class CartsController < ApplicationController
|
|
2
|
-
|
|
3
|
-
before_filter :find_cart
|
|
4
|
-
before_filter :find_item, :only => [:add_item, :remove_item]
|
|
2
|
+
include ShopBunny::CartControllerModule
|
|
5
3
|
|
|
6
|
-
if ShopBunny.controller_enhancement
|
|
7
|
-
include ShopBunny.controller_enhancement
|
|
8
|
-
end
|
|
9
|
-
|
|
10
|
-
def show
|
|
11
|
-
respond_with @cart
|
|
12
|
-
end
|
|
13
|
-
|
|
14
|
-
def add_item
|
|
15
|
-
@cart.add_item(@item) if @item
|
|
16
|
-
respond_with @cart do |format|
|
|
17
|
-
format.html { redirect_to :action => :show }
|
|
18
|
-
end
|
|
19
|
-
end
|
|
20
|
-
|
|
21
|
-
def remove_item
|
|
22
|
-
@cart.remove_item(@item) if @item
|
|
23
|
-
respond_with @cart do |format|
|
|
24
|
-
format.html { redirect_to :action => :show }
|
|
25
|
-
end
|
|
26
|
-
end
|
|
27
|
-
|
|
28
|
-
def checkout
|
|
29
|
-
end
|
|
30
|
-
|
|
31
|
-
def update
|
|
32
|
-
@cart.update_attributes(params[:cart])
|
|
33
|
-
respond_with @cart do |format|
|
|
34
|
-
format.html {
|
|
35
|
-
if @cart.errors.any?
|
|
36
|
-
render 'show'
|
|
37
|
-
else
|
|
38
|
-
# We have to redirect by hand here, because
|
|
39
|
-
# url_for(@cart) returns "/cart.x" when cart is a singular resource
|
|
40
|
-
# (see routes.rb). This is a known limitation of Rails.
|
|
41
|
-
# See https://rails.lighthouseapp.com/projects/8994/tickets/4168
|
|
42
|
-
redirect_to :action => :show
|
|
43
|
-
end
|
|
44
|
-
}
|
|
45
|
-
end
|
|
46
|
-
end
|
|
47
|
-
|
|
48
|
-
private
|
|
49
|
-
|
|
50
|
-
def find_item
|
|
51
|
-
@item = @cart.item_model.find(params[:item_id])
|
|
52
|
-
end
|
|
53
4
|
end
|
data/app/models/cart.rb
CHANGED
|
@@ -1,121 +1,3 @@
|
|
|
1
1
|
class Cart < ActiveRecord::Base
|
|
2
|
-
|
|
3
|
-
has_many :cart_items, :dependent => :destroy
|
|
4
|
-
has_many :coupon_uses, :dependent => :destroy
|
|
5
|
-
has_many :coupons, :through => :coupon_uses
|
|
6
|
-
accepts_nested_attributes_for :cart_items, :allow_destroy => true
|
|
7
|
-
before_save :update_coupons
|
|
8
|
-
attr_accessible :coupon_code, :cart_items_attributes
|
|
9
|
-
validate :coupon_code_must_be_valid
|
|
10
|
-
|
|
11
|
-
def items
|
|
12
|
-
self.cart_items
|
|
13
|
-
end
|
|
14
|
-
|
|
15
|
-
def item_count
|
|
16
|
-
self.cart_items.inject(0) {|sum,e| sum += e.quantity}
|
|
17
|
-
end
|
|
18
|
-
|
|
19
|
-
def shipping_costs
|
|
20
|
-
return 0 if coupons.any?(&:removes_shipping_cost)
|
|
21
|
-
shipping_cost_calculator.costs_for(self)
|
|
22
|
-
end
|
|
23
|
-
|
|
24
|
-
# Calculates the sum of all cart_items, excluding the coupons discount!
|
|
25
|
-
def item_sum
|
|
26
|
-
self.cart_items.inject(0) {|sum,e| sum += e.quantity*e.item.price}
|
|
27
|
-
end
|
|
28
|
-
|
|
29
|
-
# Calculates the total sum and applies the coupons discount!
|
|
30
|
-
def total
|
|
31
|
-
sum = item_sum
|
|
32
|
-
|
|
33
|
-
absolute_discount = coupons.sum(:discount_credit)
|
|
34
|
-
relative_discount = coupons.inject(1) {|s,coupon| s * coupon.discount_percentage }
|
|
35
|
-
|
|
36
|
-
sum -= absolute_discount
|
|
37
|
-
sum *= relative_discount
|
|
38
|
-
|
|
39
|
-
sum += shipping_costs
|
|
40
|
-
|
|
41
|
-
[0, sum].max
|
|
42
|
-
end
|
|
43
|
-
|
|
44
|
-
#increases the quantity of an article. creates a new one if it doesn't exist
|
|
45
|
-
def add_item(item,options = {})
|
|
46
|
-
options[:quantity] ||= 1
|
|
47
|
-
cart_item = self.cart_items.find_or_create_by_item_id(item.id)
|
|
48
|
-
cart_item.quantity += options[:quantity]
|
|
49
|
-
cart_item.save!
|
|
50
|
-
self.reload
|
|
51
|
-
cart_item
|
|
52
|
-
end
|
|
53
|
-
|
|
54
|
-
#removes a quantity of an article specified by :article_id, returns nil if no article has been found
|
|
55
|
-
def remove_item(item,options = {})
|
|
56
|
-
cart_item = self.cart_items.find_by_item_id(item)
|
|
57
|
-
|
|
58
|
-
options[:quantity] ||= cart_item.quantity
|
|
59
|
-
if cart_item
|
|
60
|
-
cart_item.quantity -= options[:quantity]
|
|
61
|
-
cart_item.save!
|
|
62
|
-
self.reload
|
|
63
|
-
end
|
|
64
|
-
cart_item
|
|
65
|
-
end
|
|
66
|
-
|
|
67
|
-
#sets the quantity of an article specified by :article_id, returns nil if no article has been found
|
|
68
|
-
def update_item(item,options)
|
|
69
|
-
cart_item = self.cart_items.find_by_item_id(item)
|
|
70
|
-
if cart_item
|
|
71
|
-
cart_item.quantity = options[:quantity]
|
|
72
|
-
cart_item.save!
|
|
73
|
-
self.reload
|
|
74
|
-
end
|
|
75
|
-
cart_item
|
|
76
|
-
end
|
|
77
|
-
|
|
78
|
-
def shipping_cost_calculator
|
|
79
|
-
ShopBunny.shipping_cost_calculator
|
|
80
|
-
end
|
|
81
|
-
|
|
82
|
-
# Returns the class/model of the items you can buy. (Products)
|
|
83
|
-
def item_model
|
|
84
|
-
ShopBunny.item_model_class_name.constantize
|
|
85
|
-
end
|
|
86
|
-
|
|
87
|
-
# Make
|
|
88
|
-
def as_json(options={})
|
|
89
|
-
{
|
|
90
|
-
:cart => attributes.
|
|
91
|
-
merge(
|
|
92
|
-
:cart_items => cart_items.as_json,
|
|
93
|
-
:item_count => item_count,
|
|
94
|
-
:coupons => coupons.as_json,
|
|
95
|
-
:item_sum => item_sum,
|
|
96
|
-
:shipping_costs => shipping_costs,
|
|
97
|
-
:total => total
|
|
98
|
-
)
|
|
99
|
-
}
|
|
100
|
-
end
|
|
101
|
-
|
|
102
|
-
private
|
|
103
|
-
|
|
104
|
-
def update_coupons
|
|
105
|
-
Array(@coupon_code).each { |code|
|
|
106
|
-
coupon = Coupon.find_by_code(code)
|
|
107
|
-
coupons << coupon if coupon
|
|
108
|
-
}
|
|
109
|
-
end
|
|
110
|
-
|
|
111
|
-
def coupon_code_must_be_valid
|
|
112
|
-
Array(@coupon_code).each { |code|
|
|
113
|
-
coupon = Coupon.find_by_code(code)
|
|
114
|
-
if coupon.nil?
|
|
115
|
-
errors.add(:coupon_code, "is unknown")
|
|
116
|
-
elsif coupon.expired?
|
|
117
|
-
errors.add(:coupon_code, "is expired")
|
|
118
|
-
end
|
|
119
|
-
}
|
|
120
|
-
end
|
|
2
|
+
include ShopBunny::CartModule
|
|
121
3
|
end
|
|
@@ -15,10 +15,4 @@ ShopBunny.setup do |config|
|
|
|
15
15
|
#
|
|
16
16
|
# config.shipping_cost_calculator = MyShippingCostCalculator
|
|
17
17
|
|
|
18
|
-
# ShopBunny.controller_enhancement is a module that is included into the
|
|
19
|
-
# CartsController. You can e.g. control which layout is used for rendering
|
|
20
|
-
# the cart or add filters. E.g. just drop a ShopBunnyEnhancements module in
|
|
21
|
-
# lib/shop_bunny_enhancements.rb and use it like this:
|
|
22
|
-
# require 'shop_bunny_enhancements'
|
|
23
|
-
# config.controller_enhancement = ShopBunnyEnhancements
|
|
24
18
|
end
|
data/config/routes.rb
CHANGED
|
@@ -1,11 +1,16 @@
|
|
|
1
1
|
module ShopBunny
|
|
2
2
|
class InstallGenerator < Rails::Generators::Base
|
|
3
3
|
source_root File.expand_path("../../../../", __FILE__)
|
|
4
|
-
|
|
4
|
+
class_option :controller, :type => :boolean, :default => true, :desc => "copy controller templatefile."
|
|
5
|
+
class_option :model, :type => :boolean, :default => true, :desc => "copy model templatefile."
|
|
6
|
+
|
|
7
|
+
|
|
5
8
|
def copy_files
|
|
6
9
|
puts Dir['.']
|
|
7
10
|
directory 'db/migrate'
|
|
8
11
|
copy_file 'config/initializers/shop_bunny.rb'
|
|
12
|
+
copy_file 'lib/generators/shop_bunny/templates/shopbunny_controller_template.rb', 'app/controllers/carts_controller.rb' if options.controller?
|
|
13
|
+
copy_file 'lib/generators/shop_bunny/templates/shopbunny_model_template.rb', 'app/models/cart.rb' if options.model?
|
|
9
14
|
end
|
|
10
15
|
end
|
|
11
16
|
end
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
module ShopBunny
|
|
2
|
+
module CartControllerModule
|
|
3
|
+
def self.included(clazz)
|
|
4
|
+
clazz.send(:respond_to, :html, :json)
|
|
5
|
+
clazz.send(:before_filter, :find_cart)
|
|
6
|
+
clazz.send(:before_filter, :find_item, :only => [:add_item, :remove_item])
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def show
|
|
10
|
+
respond_with @cart
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def add_item
|
|
14
|
+
@cart.add_item(@item) if @item
|
|
15
|
+
respond_with @cart do |format|
|
|
16
|
+
format.html { redirect_to :action => :show }
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def remove_item
|
|
21
|
+
@cart.remove_item(@item) if @item
|
|
22
|
+
respond_with @cart do |format|
|
|
23
|
+
format.html { redirect_to :action => :show }
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def checkout
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def update
|
|
31
|
+
@cart.update_attributes(params[:cart])
|
|
32
|
+
respond_with @cart do |format|
|
|
33
|
+
format.html {
|
|
34
|
+
if @cart.errors.any?
|
|
35
|
+
render 'show'
|
|
36
|
+
else
|
|
37
|
+
# We have to redirect by hand here, because
|
|
38
|
+
# url_for(@cart) returns "/cart.x" when cart is a singular resource
|
|
39
|
+
# (see routes.rb). This is a known limitation of Rails.
|
|
40
|
+
# See https://rails.lighthouseapp.com/projects/8994/tickets/4168
|
|
41
|
+
redirect_to :action => :show
|
|
42
|
+
end
|
|
43
|
+
}
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
private
|
|
48
|
+
|
|
49
|
+
def find_item
|
|
50
|
+
@item = @cart.item_model.find(params[:item_id])
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
module ShopBunny
|
|
2
|
+
module CartModule
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
def self.included(clazz)
|
|
6
|
+
clazz.send(:attr_accessor, :coupon_code)
|
|
7
|
+
clazz.send(:has_many, :cart_items, :dependent => :destroy)
|
|
8
|
+
clazz.send(:has_many, :coupon_uses, :dependent => :destroy)
|
|
9
|
+
clazz.send(:has_many, :coupons, :through => :coupon_uses)
|
|
10
|
+
clazz.send(:accepts_nested_attributes_for, :cart_items, :allow_destroy => true )
|
|
11
|
+
clazz.send(:before_save, :update_coupons)
|
|
12
|
+
clazz.send(:attr_accessible, :coupon_code, :cart_items_attributes)
|
|
13
|
+
clazz.send(:validate, :coupon_code_must_be_valid)
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def items
|
|
20
|
+
self.cart_items
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def item_count
|
|
24
|
+
self.cart_items.inject(0) {|sum,e| sum += e.quantity}
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def shipping_costs
|
|
28
|
+
return 0 if coupons.any?(&:removes_shipping_cost)
|
|
29
|
+
shipping_cost_calculator.costs_for(self)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
# Calculates the sum of all cart_items, excluding the coupons discount!
|
|
33
|
+
def item_sum
|
|
34
|
+
self.cart_items.inject(0) {|sum,e| sum += e.quantity*e.item.price}
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# Calculates the total sum and applies the coupons discount!
|
|
38
|
+
def total
|
|
39
|
+
sum = item_sum
|
|
40
|
+
|
|
41
|
+
absolute_discount = coupons.sum(:discount_credit)
|
|
42
|
+
relative_discount = coupons.inject(1) {|s,coupon| s * coupon.discount_percentage }
|
|
43
|
+
|
|
44
|
+
sum -= absolute_discount
|
|
45
|
+
sum *= relative_discount
|
|
46
|
+
|
|
47
|
+
sum += shipping_costs
|
|
48
|
+
|
|
49
|
+
[0, sum].max
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
#increases the quantity of an article. creates a new one if it doesn't exist
|
|
53
|
+
def add_item(item,options = {})
|
|
54
|
+
options[:quantity] ||= 1
|
|
55
|
+
cart_item = self.cart_items.find_or_create_by_item_id(item.id)
|
|
56
|
+
cart_item.quantity += options[:quantity]
|
|
57
|
+
cart_item.save!
|
|
58
|
+
self.reload
|
|
59
|
+
cart_item
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
#removes a quantity of an article specified by :article_id, returns nil if no article has been found
|
|
63
|
+
def remove_item(item,options = {})
|
|
64
|
+
cart_item = self.cart_items.find_by_item_id(item)
|
|
65
|
+
|
|
66
|
+
options[:quantity] ||= cart_item.quantity
|
|
67
|
+
if cart_item
|
|
68
|
+
cart_item.quantity -= options[:quantity]
|
|
69
|
+
cart_item.save!
|
|
70
|
+
self.reload
|
|
71
|
+
end
|
|
72
|
+
cart_item
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
#sets the quantity of an article specified by :article_id, returns nil if no article has been found
|
|
76
|
+
def update_item(item,options)
|
|
77
|
+
cart_item = self.cart_items.find_by_item_id(item)
|
|
78
|
+
if cart_item
|
|
79
|
+
cart_item.quantity = options[:quantity]
|
|
80
|
+
cart_item.save!
|
|
81
|
+
self.reload
|
|
82
|
+
end
|
|
83
|
+
cart_item
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
def shipping_cost_calculator
|
|
87
|
+
ShopBunny.shipping_cost_calculator
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
# Returns the class/model of the items you can buy. (Products)
|
|
91
|
+
def item_model
|
|
92
|
+
ShopBunny.item_model_class_name.constantize
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
# Make
|
|
96
|
+
def as_json(options={})
|
|
97
|
+
{
|
|
98
|
+
:cart => attributes.
|
|
99
|
+
merge(
|
|
100
|
+
:cart_items => cart_items.as_json,
|
|
101
|
+
:item_count => item_count,
|
|
102
|
+
:coupons => coupons.as_json,
|
|
103
|
+
:item_sum => item_sum,
|
|
104
|
+
:shipping_costs => shipping_costs,
|
|
105
|
+
:total => total
|
|
106
|
+
)
|
|
107
|
+
}
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
protected
|
|
111
|
+
|
|
112
|
+
def update_coupons
|
|
113
|
+
Array(@coupon_code).each { |code|
|
|
114
|
+
coupon = Coupon.find_by_code(code)
|
|
115
|
+
coupons << coupon if coupon
|
|
116
|
+
}
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
def coupon_code_must_be_valid
|
|
120
|
+
Array(@coupon_code).each { |code|
|
|
121
|
+
coupon = Coupon.find_by_code(code)
|
|
122
|
+
if coupon.nil?
|
|
123
|
+
errors.add(:coupon_code, "is unknown")
|
|
124
|
+
elsif coupon.expired?
|
|
125
|
+
errors.add(:coupon_code, "is expired")
|
|
126
|
+
end
|
|
127
|
+
}
|
|
128
|
+
end
|
|
129
|
+
end
|
|
130
|
+
end
|
data/lib/shop_bunny.rb
CHANGED
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
module ShopBunny
|
|
3
3
|
require 'shop_bunny/engine' if defined?(Rails) && Rails::VERSION::MAJOR == 3
|
|
4
4
|
require 'shop_bunny/shipping_cost_calculator'
|
|
5
|
+
require 'shop_bunny/cart_module'
|
|
6
|
+
require 'shop_bunny/cart_controller_module'
|
|
5
7
|
|
|
6
8
|
mattr_accessor :item_model_class_name
|
|
7
9
|
@@item_model_class_name = 'Item'
|
metadata
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: shop_bunny
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
hash:
|
|
4
|
+
hash: 5
|
|
5
5
|
prerelease: false
|
|
6
6
|
segments:
|
|
7
7
|
- 0
|
|
8
8
|
- 7
|
|
9
|
-
-
|
|
10
|
-
version: 0.7.
|
|
9
|
+
- 3
|
|
10
|
+
version: 0.7.3
|
|
11
11
|
platform: ruby
|
|
12
12
|
authors:
|
|
13
13
|
- kopfmaschine.com
|
|
@@ -15,7 +15,7 @@ autorequire:
|
|
|
15
15
|
bindir: bin
|
|
16
16
|
cert_chain: []
|
|
17
17
|
|
|
18
|
-
date: 2010-09-
|
|
18
|
+
date: 2010-09-24 00:00:00 +02:00
|
|
19
19
|
default_executable:
|
|
20
20
|
dependencies: []
|
|
21
21
|
|
|
@@ -29,28 +29,32 @@ extensions: []
|
|
|
29
29
|
extra_rdoc_files: []
|
|
30
30
|
|
|
31
31
|
files:
|
|
32
|
+
- lib/generators/shop_bunny/templates/shopbunny_model_template.rb
|
|
33
|
+
- lib/generators/shop_bunny/templates/shopbunny_controller_template.rb
|
|
34
|
+
- lib/generators/shop_bunny/install_generator.rb
|
|
32
35
|
- lib/shop_bunny.rb
|
|
33
|
-
- lib/shop_bunny/
|
|
36
|
+
- lib/shop_bunny/cart_controller_module.rb
|
|
37
|
+
- lib/shop_bunny/cart_module.rb
|
|
34
38
|
- lib/shop_bunny/shipping_cost_calculator.rb
|
|
35
|
-
- lib/
|
|
39
|
+
- lib/shop_bunny/engine.rb
|
|
36
40
|
- app/views/carts/show.html.erb
|
|
41
|
+
- app/models/cart.rb
|
|
37
42
|
- app/models/coupon_use.rb
|
|
43
|
+
- app/models/cart_item.rb
|
|
38
44
|
- app/models/coupon.rb
|
|
39
|
-
- app/models/cart.rb
|
|
40
45
|
- app/models/item.rb
|
|
41
|
-
- app/models/cart_item.rb
|
|
42
46
|
- app/controllers/application_controller.rb
|
|
43
47
|
- app/controllers/carts_controller.rb
|
|
44
|
-
- db/migrate/20100915093821_create_coupon_uses.rb
|
|
45
|
-
- db/migrate/20100915091059_create_coupons.rb
|
|
46
48
|
- db/migrate/20100915162029_remove_owner_id_from_carts.rb
|
|
49
|
+
- db/migrate/20100915091059_create_coupons.rb
|
|
50
|
+
- db/migrate/20100915073016_create_items.rb
|
|
47
51
|
- db/migrate/20100902115627_create_carts.rb
|
|
52
|
+
- db/migrate/20100915093821_create_coupon_uses.rb
|
|
48
53
|
- db/migrate/20100916194407_set_default_column_value_for_cart_items_quantity.rb
|
|
49
|
-
- db/migrate/20100915073016_create_items.rb
|
|
50
54
|
- db/migrate/20100902115757_create_cart_items.rb
|
|
55
|
+
- config/initializers/add_cart_finder_to_controllers.rb
|
|
51
56
|
- config/initializers/shop_bunny.rb
|
|
52
57
|
- config/initializers/machinist.rb
|
|
53
|
-
- config/initializers/add_cart_finder_to_controllers.rb
|
|
54
58
|
- config/routes.rb
|
|
55
59
|
has_rdoc: true
|
|
56
60
|
homepage: http://kopfmaschine.com
|