shop_bunny 0.7
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/application_controller.rb +3 -0
- data/app/controllers/carts_controller.rb +50 -0
- data/app/models/cart.rb +121 -0
- data/app/models/cart_item.rb +23 -0
- data/app/models/coupon.rb +24 -0
- data/app/models/coupon_use.rb +7 -0
- data/app/models/item.rb +6 -0
- data/app/views/carts/show.html.erb +83 -0
- data/db/development.sqlite3 +0 -0
- data/db/migrate/20100902115627_create_carts.rb +14 -0
- data/db/migrate/20100902115757_create_cart_items.rb +15 -0
- data/db/migrate/20100915073016_create_items.rb +14 -0
- data/db/migrate/20100915091059_create_coupons.rb +21 -0
- data/db/migrate/20100915093821_create_coupon_uses.rb +14 -0
- data/db/migrate/20100915162029_remove_owner_id_from_carts.rb +9 -0
- data/db/migrate/20100916194407_set_default_column_value_for_cart_items_quantity.rb +9 -0
- data/db/schema.rb +57 -0
- data/db/seeds.rb +19 -0
- data/db/test.sqlite3 +0 -0
- data/lib/generators/shop_bunny/install_generator.rb +13 -0
- data/lib/shop_bunny/engine.rb +15 -0
- data/lib/shop_bunny/shipping_cost_calculator.rb +6 -0
- data/lib/shop_bunny.rb +20 -0
- metadata +91 -0
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
class CartsController < ApplicationController
|
|
2
|
+
respond_to :html, :json
|
|
3
|
+
before_filter :find_cart
|
|
4
|
+
before_filter :find_item, :only => [:add_item, :remove_item]
|
|
5
|
+
|
|
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 update
|
|
29
|
+
@cart.update_attributes(params[:cart])
|
|
30
|
+
respond_with @cart do |format|
|
|
31
|
+
format.html {
|
|
32
|
+
if @cart.errors.any?
|
|
33
|
+
render 'show'
|
|
34
|
+
else
|
|
35
|
+
# We have to redirect by hand here, because
|
|
36
|
+
# url_for(@cart) returns "/cart.x" when cart is a singular resource
|
|
37
|
+
# (see routes.rb). This is a known limitation of Rails.
|
|
38
|
+
# See https://rails.lighthouseapp.com/projects/8994/tickets/4168
|
|
39
|
+
redirect_to :action => :show
|
|
40
|
+
end
|
|
41
|
+
}
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
private
|
|
46
|
+
|
|
47
|
+
def find_item
|
|
48
|
+
@item = @cart.item_model.find(params[:item_id])
|
|
49
|
+
end
|
|
50
|
+
end
|
data/app/models/cart.rb
ADDED
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
class Cart < ActiveRecord::Base
|
|
2
|
+
attr_accessor :coupon_code
|
|
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
|
|
121
|
+
end
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
class CartItem < ActiveRecord::Base
|
|
2
|
+
belongs_to :cart
|
|
3
|
+
belongs_to :item, :class_name => ShopBunny.item_model_class_name
|
|
4
|
+
|
|
5
|
+
validates_presence_of :cart_id
|
|
6
|
+
validates_presence_of :item_id
|
|
7
|
+
validates_numericality_of :quantity
|
|
8
|
+
|
|
9
|
+
before_validation :set_default_quantity
|
|
10
|
+
after_update :destroy_if_empty
|
|
11
|
+
# TODO attr_accessible :quantity
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
private
|
|
15
|
+
|
|
16
|
+
def set_default_quantity
|
|
17
|
+
self.quantity ||= 0
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def destroy_if_empty
|
|
21
|
+
self.destroy if quantity.to_i <= 0
|
|
22
|
+
end
|
|
23
|
+
end
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
class Coupon < ActiveRecord::Base
|
|
2
|
+
has_many :coupon_uses, :dependent => :destroy
|
|
3
|
+
has_many :carts, :through => :coupon_uses
|
|
4
|
+
|
|
5
|
+
validates_presence_of :code
|
|
6
|
+
validates_uniqueness_of :code
|
|
7
|
+
validates_presence_of :title
|
|
8
|
+
attr_accessible
|
|
9
|
+
|
|
10
|
+
# TODO Add self destruction when coupon has expired?
|
|
11
|
+
|
|
12
|
+
def expired?
|
|
13
|
+
not_yet_valid? || has_expired?
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
# FIXME rename?
|
|
17
|
+
def not_yet_valid?
|
|
18
|
+
Time.now < self.valid_from if self.valid_from
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def has_expired?
|
|
22
|
+
Time.now > self.valid_until if self.valid_until
|
|
23
|
+
end
|
|
24
|
+
end
|
data/app/models/item.rb
ADDED
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
<div class="shop">
|
|
2
|
+
<h1>Shop</h1>
|
|
3
|
+
<table>
|
|
4
|
+
<table>
|
|
5
|
+
<tr>
|
|
6
|
+
<th>Item id</th>
|
|
7
|
+
<th>Item price</th>
|
|
8
|
+
<th>Action</th>
|
|
9
|
+
</tr>
|
|
10
|
+
<% @cart.item_model.limit(10).each do |item| %>
|
|
11
|
+
<tr>
|
|
12
|
+
<th><%= item.id %></th>
|
|
13
|
+
<th><%= item.price %></th>
|
|
14
|
+
<th><%= link_to("Add to cart", add_item_to_cart_path(:item_id => item.id)) %></th>
|
|
15
|
+
</tr>
|
|
16
|
+
<% end %>
|
|
17
|
+
</table>
|
|
18
|
+
</table>
|
|
19
|
+
</div>
|
|
20
|
+
|
|
21
|
+
<div class="shopping-cart">
|
|
22
|
+
<div class="items">
|
|
23
|
+
<%= form_for @cart, :url => cart_path do |f| %>
|
|
24
|
+
<h1>Shopping Cart</h1>
|
|
25
|
+
<table>
|
|
26
|
+
<tr>
|
|
27
|
+
<th>Item id</th>
|
|
28
|
+
<th>Item price</th>
|
|
29
|
+
<th>Item quantity</th>
|
|
30
|
+
<th>Remove</th>
|
|
31
|
+
</tr>
|
|
32
|
+
|
|
33
|
+
<%= f.fields_for :cart_items do |cart_item| %>
|
|
34
|
+
<tr>
|
|
35
|
+
<td><%= cart_item.object.item.id %></td>
|
|
36
|
+
<td><%= cart_item.object.item.price %></td>
|
|
37
|
+
<td><%= cart_item.text_field :quantity %></td>
|
|
38
|
+
<td><%= link_to 'Remove', remove_item_from_cart_path(:item_id => cart_item.object.item.id) %></td>
|
|
39
|
+
</tr>
|
|
40
|
+
<% end %>
|
|
41
|
+
</table>
|
|
42
|
+
|
|
43
|
+
<table class="cashpoint">
|
|
44
|
+
<tr>
|
|
45
|
+
<td>Sum: <%= @cart.item_sum %></td>
|
|
46
|
+
</tr>
|
|
47
|
+
<tr>
|
|
48
|
+
<td>Shippin costs: <%= @cart.shipping_costs %></td>
|
|
49
|
+
</tr>
|
|
50
|
+
<tr>
|
|
51
|
+
<td>Total: <%= @cart.total %></td>
|
|
52
|
+
</tr>
|
|
53
|
+
</table>
|
|
54
|
+
|
|
55
|
+
<%= f.submit %>
|
|
56
|
+
<% end %>
|
|
57
|
+
</div>
|
|
58
|
+
|
|
59
|
+
<div class="coupons">
|
|
60
|
+
<%= form_for @cart, :url => cart_path do |f| %>
|
|
61
|
+
<h1>Available coupons</h2>
|
|
62
|
+
<ul>
|
|
63
|
+
<% Coupon.limit(10).all.each do |coupon| %>
|
|
64
|
+
<li><%= coupon.code %></ti>
|
|
65
|
+
<% end %>
|
|
66
|
+
</ul>
|
|
67
|
+
|
|
68
|
+
<h2>Your coupons</h2>
|
|
69
|
+
<ul>
|
|
70
|
+
<% @cart.coupons.each do |coupon| %>
|
|
71
|
+
<li><%= coupon.title %></ti>
|
|
72
|
+
<% end %>
|
|
73
|
+
</ul>
|
|
74
|
+
<p>
|
|
75
|
+
<%# TODO Show error messages %>
|
|
76
|
+
<%= @cart.errors if @cart.errors.any? %>
|
|
77
|
+
</p>
|
|
78
|
+
<%= f.label :coupon_code, 'Got a code?' %>
|
|
79
|
+
<%= f.text_field :coupon_code %>
|
|
80
|
+
<%= f.submit :value => "Add code" %>
|
|
81
|
+
<% end %>
|
|
82
|
+
</div>
|
|
83
|
+
</div>
|
|
Binary file
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
class CreateCoupons < ActiveRecord::Migration
|
|
2
|
+
def self.up
|
|
3
|
+
create_table :coupons do |t|
|
|
4
|
+
t.boolean :removes_tax, :default => false
|
|
5
|
+
t.float :discount_percentage, :default => 1.0
|
|
6
|
+
t.float :discount_credit, :default => 0.0
|
|
7
|
+
t.boolean :removes_shipping_cost, :default => false
|
|
8
|
+
t.integer :bonus_article_id
|
|
9
|
+
t.date :valid_from
|
|
10
|
+
t.date :valid_until
|
|
11
|
+
t.text :title
|
|
12
|
+
t.string :code
|
|
13
|
+
|
|
14
|
+
t.timestamps
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def self.down
|
|
19
|
+
drop_table :coupons
|
|
20
|
+
end
|
|
21
|
+
end
|
data/db/schema.rb
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# This file is auto-generated from the current state of the database. Instead
|
|
2
|
+
# of editing this file, please use the migrations feature of Active Record to
|
|
3
|
+
# incrementally modify your database, and then regenerate this schema definition.
|
|
4
|
+
#
|
|
5
|
+
# Note that this schema.rb definition is the authoritative source for your
|
|
6
|
+
# database schema. If you need to create the application database on another
|
|
7
|
+
# system, you should be using db:schema:load, not running all the migrations
|
|
8
|
+
# from scratch. The latter is a flawed and unsustainable approach (the more migrations
|
|
9
|
+
# you'll amass, the slower it'll run and the greater likelihood for issues).
|
|
10
|
+
#
|
|
11
|
+
# It's strongly recommended to check this file into your version control system.
|
|
12
|
+
|
|
13
|
+
ActiveRecord::Schema.define(:version => 20100916194407) do
|
|
14
|
+
|
|
15
|
+
create_table "cart_items", :force => true do |t|
|
|
16
|
+
t.integer "cart_id"
|
|
17
|
+
t.integer "item_id"
|
|
18
|
+
t.integer "quantity", :default => 0
|
|
19
|
+
t.datetime "created_at"
|
|
20
|
+
t.datetime "updated_at"
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
create_table "carts", :force => true do |t|
|
|
24
|
+
t.string "type"
|
|
25
|
+
t.datetime "created_at"
|
|
26
|
+
t.datetime "updated_at"
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
create_table "coupon_uses", :force => true do |t|
|
|
30
|
+
t.integer "cart_id"
|
|
31
|
+
t.integer "coupon_id"
|
|
32
|
+
t.datetime "created_at"
|
|
33
|
+
t.datetime "updated_at"
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
create_table "coupons", :force => true do |t|
|
|
37
|
+
t.boolean "removes_tax", :default => false
|
|
38
|
+
t.float "discount_percentage", :default => 1.0
|
|
39
|
+
t.float "discount_credit", :default => 0.0
|
|
40
|
+
t.boolean "removes_shipping_cost", :default => false
|
|
41
|
+
t.integer "bonus_article_id"
|
|
42
|
+
t.date "valid_from"
|
|
43
|
+
t.date "valid_until"
|
|
44
|
+
t.text "title"
|
|
45
|
+
t.string "code"
|
|
46
|
+
t.datetime "created_at"
|
|
47
|
+
t.datetime "updated_at"
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
create_table "items", :force => true do |t|
|
|
51
|
+
t.float "price"
|
|
52
|
+
t.string "title"
|
|
53
|
+
t.datetime "created_at"
|
|
54
|
+
t.datetime "updated_at"
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
end
|
data/db/seeds.rb
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# This file should contain all the record creation needed to seed the database with its default values.
|
|
2
|
+
# The data can then be loaded with the rake db:seed (or created alongside the db with db:setup).
|
|
3
|
+
#
|
|
4
|
+
# Examples:
|
|
5
|
+
#
|
|
6
|
+
# cities = City.create([{ :name => 'Chicago' }, { :name => 'Copenhagen' }])
|
|
7
|
+
# Mayor.create(:name => 'Daley', :city => cities.first)
|
|
8
|
+
|
|
9
|
+
# Dummy data for development
|
|
10
|
+
if Rails.env.development?
|
|
11
|
+
3.times { |i| Item.create! :price => i }
|
|
12
|
+
3.times { |i|
|
|
13
|
+
c = Coupon.new
|
|
14
|
+
c.code = "code#{i}"
|
|
15
|
+
c.title = "10% discount coupon #{i}"
|
|
16
|
+
c.discount_percentage = 0.9
|
|
17
|
+
c.save!
|
|
18
|
+
}
|
|
19
|
+
end
|
data/db/test.sqlite3
ADDED
|
Binary file
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
module ShopBunny
|
|
2
|
+
class InstallGenerator < Rails::Generators::Base
|
|
3
|
+
source_root File.expand_path("../../../../", __FILE__)
|
|
4
|
+
|
|
5
|
+
def copy_files
|
|
6
|
+
puts Dir['.']
|
|
7
|
+
directory 'db/migrate'
|
|
8
|
+
copy_file 'config/initializers/shop_bunny.rb'
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
# TODO Write a generator test
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
require 'rails'
|
|
2
|
+
|
|
3
|
+
module ShopBunny
|
|
4
|
+
class Engine < Rails::Engine
|
|
5
|
+
|
|
6
|
+
# Config defaults
|
|
7
|
+
config.mount_at = '/'
|
|
8
|
+
|
|
9
|
+
# Check the gem config
|
|
10
|
+
initializer "check config" do |app|
|
|
11
|
+
# make sure mount_at ends with trailing slash
|
|
12
|
+
config.mount_at += '/' unless config.mount_at.last == '/'
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
data/lib/shop_bunny.rb
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
module ShopBunny
|
|
3
|
+
require 'shop_bunny/engine' if defined?(Rails) && Rails::VERSION::MAJOR == 3
|
|
4
|
+
require 'shop_bunny/shipping_cost_calculator'
|
|
5
|
+
|
|
6
|
+
mattr_accessor :item_model_class_name
|
|
7
|
+
@@item_model_class_name = 'Item'
|
|
8
|
+
|
|
9
|
+
mattr_accessor :shipping_cost_calculator
|
|
10
|
+
@@shipping_cost_calculator = ShopBunny::ShippingCostCalculator
|
|
11
|
+
|
|
12
|
+
mattr_accessor :controller_enhancement
|
|
13
|
+
@@controller_enhancement = nil
|
|
14
|
+
|
|
15
|
+
# This is the default way to setup ShopBunny and is used in the
|
|
16
|
+
# initializer which gets generated by `rails generate shop_bunny:install`
|
|
17
|
+
def self.setup
|
|
18
|
+
yield self
|
|
19
|
+
end
|
|
20
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: shop_bunny
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
hash: 5
|
|
5
|
+
prerelease: false
|
|
6
|
+
segments:
|
|
7
|
+
- 0
|
|
8
|
+
- 7
|
|
9
|
+
version: "0.7"
|
|
10
|
+
platform: ruby
|
|
11
|
+
authors:
|
|
12
|
+
- kopfmaschine.com
|
|
13
|
+
autorequire:
|
|
14
|
+
bindir: bin
|
|
15
|
+
cert_chain: []
|
|
16
|
+
|
|
17
|
+
date: 2010-09-20 00:00:00 +02:00
|
|
18
|
+
default_executable:
|
|
19
|
+
dependencies: []
|
|
20
|
+
|
|
21
|
+
description: A simple shop gem that integrates a cart and coupons functionality
|
|
22
|
+
email:
|
|
23
|
+
- jan@kopfmaschine.com
|
|
24
|
+
executables: []
|
|
25
|
+
|
|
26
|
+
extensions: []
|
|
27
|
+
|
|
28
|
+
extra_rdoc_files: []
|
|
29
|
+
|
|
30
|
+
files:
|
|
31
|
+
- lib/generators/shop_bunny/install_generator.rb
|
|
32
|
+
- lib/shop_bunny.rb
|
|
33
|
+
- lib/shop_bunny/shipping_cost_calculator.rb
|
|
34
|
+
- lib/shop_bunny/engine.rb
|
|
35
|
+
- app/views/carts/show.html.erb
|
|
36
|
+
- app/models/cart.rb
|
|
37
|
+
- app/models/coupon_use.rb
|
|
38
|
+
- app/models/cart_item.rb
|
|
39
|
+
- app/models/coupon.rb
|
|
40
|
+
- app/models/item.rb
|
|
41
|
+
- app/controllers/application_controller.rb
|
|
42
|
+
- app/controllers/carts_controller.rb
|
|
43
|
+
- db/test.sqlite3
|
|
44
|
+
- db/schema.rb
|
|
45
|
+
- db/migrate/20100915162029_remove_owner_id_from_carts.rb
|
|
46
|
+
- db/migrate/20100915091059_create_coupons.rb
|
|
47
|
+
- db/migrate/20100915073016_create_items.rb
|
|
48
|
+
- db/migrate/20100902115627_create_carts.rb
|
|
49
|
+
- db/migrate/20100915093821_create_coupon_uses.rb
|
|
50
|
+
- db/migrate/20100916194407_set_default_column_value_for_cart_items_quantity.rb
|
|
51
|
+
- db/migrate/20100902115757_create_cart_items.rb
|
|
52
|
+
- db/development.sqlite3
|
|
53
|
+
- db/seeds.rb
|
|
54
|
+
has_rdoc: true
|
|
55
|
+
homepage: http://kopfmaschine.com
|
|
56
|
+
licenses: []
|
|
57
|
+
|
|
58
|
+
post_install_message:
|
|
59
|
+
rdoc_options: []
|
|
60
|
+
|
|
61
|
+
require_paths:
|
|
62
|
+
- lib
|
|
63
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
64
|
+
none: false
|
|
65
|
+
requirements:
|
|
66
|
+
- - ">="
|
|
67
|
+
- !ruby/object:Gem::Version
|
|
68
|
+
hash: 3
|
|
69
|
+
segments:
|
|
70
|
+
- 0
|
|
71
|
+
version: "0"
|
|
72
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
73
|
+
none: false
|
|
74
|
+
requirements:
|
|
75
|
+
- - ">="
|
|
76
|
+
- !ruby/object:Gem::Version
|
|
77
|
+
hash: 23
|
|
78
|
+
segments:
|
|
79
|
+
- 1
|
|
80
|
+
- 3
|
|
81
|
+
- 6
|
|
82
|
+
version: 1.3.6
|
|
83
|
+
requirements: []
|
|
84
|
+
|
|
85
|
+
rubyforge_project:
|
|
86
|
+
rubygems_version: 1.3.7
|
|
87
|
+
signing_key:
|
|
88
|
+
specification_version: 3
|
|
89
|
+
summary: A shop template for your needs
|
|
90
|
+
test_files: []
|
|
91
|
+
|