power_shop 0.1.0 → 0.1.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.
- checksums.yaml +4 -4
- data/.gitignore +5 -0
- data/.rspec +2 -0
- data/Gemfile +3 -0
- data/LICENSE +20 -0
- data/README.md +13 -0
- data/Rakefile +18 -0
- data/app/controllers/catalog_controller.rb +2 -0
- data/app/controllers/power_shop/application_controller.rb +13 -0
- data/app/controllers/power_shop/cart_controller.rb +53 -0
- data/app/controllers/power_shop/catalog_controller.rb +32 -0
- data/app/controllers/power_shop/orders_controller.rb +33 -0
- data/app/forms/power_shop/order_form.rb +99 -0
- data/app/mailers/order_notifications.rb +2 -0
- data/app/mailers/power_shop/order_notifications.rb +29 -0
- data/app/models/category.rb +4 -0
- data/app/models/order.rb +2 -0
- data/app/models/order_item.rb +2 -0
- data/app/models/power_shop/category.rb +18 -0
- data/app/models/power_shop/order.rb +8 -0
- data/app/models/power_shop/order_item.rb +9 -0
- data/app/models/power_shop/product.rb +45 -0
- data/app/models/power_shop/shop_image.rb +8 -0
- data/app/models/power_shop/shopping_cart.rb +8 -0
- data/app/models/power_shop/shopping_cart_item.rb +6 -0
- data/app/models/product.rb +4 -0
- data/app/models/shop_image.rb +3 -0
- data/app/models/shopping_cart.rb +2 -0
- data/app/models/shopping_cart_item.rb +2 -0
- data/app/uploaders/power_shop/shop_image_uploader.rb +30 -0
- data/app/uploaders/shop_image_uploader.rb +2 -0
- data/app/views/power_shop/cart/show.html.erb +0 -0
- data/app/views/power_shop/catalog/category.html.erb +0 -0
- data/app/views/power_shop/catalog/index.html.erb +2 -0
- data/app/views/power_shop/catalog/product.html.erb +0 -0
- data/app/views/power_shop/orders/success.html.erb +0 -0
- data/config/locales/ru.yml +12 -0
- data/config/routes.rb +18 -0
- data/db/migrate/20140723131458_create_categories.rb +20 -0
- data/db/migrate/20140728071046_create_products.rb +20 -0
- data/db/migrate/20140729041407_create_cart.rb +8 -0
- data/db/migrate/20140731171009_create_shop_image.rb +13 -0
- data/db/migrate/20140804101936_create_friendly_id_slugs.rb +15 -0
- data/db/migrate/20140828061402_create_orders.rb +13 -0
- data/db/migrate/20140828061556_create_order_items.rb +14 -0
- data/lib/generators/power_shop/install/install_generator.rb +20 -0
- data/lib/generators/power_shop/install/templates/active_admin/category.rb.erb +43 -0
- data/lib/generators/power_shop/install/templates/active_admin/order.rb +50 -0
- data/lib/generators/power_shop/install/templates/active_admin/product.rb.erb +64 -0
- data/lib/power_shop/engine.rb +27 -0
- data/lib/power_shop/middleware/shopping_cart.rb +26 -0
- data/lib/power_shop/version.rb +3 -0
- data/lib/power_shop.rb +4 -0
- data/lib/spec.rake +15 -0
- data/lib/tasks/spec.rake +15 -0
- data/power_shop.gemspec +45 -0
- data/script/rails +7 -0
- data/spec/dummy/app/assets/images/.keep +0 -0
- data/spec/dummy/app/controllers/concerns/.keep +0 -0
- data/spec/dummy/app/mailers/.keep +0 -0
- data/spec/dummy/app/models/.keep +0 -0
- data/spec/dummy/app/models/concerns/.keep +0 -0
- data/spec/dummy/lib/assets/.keep +0 -0
- data/spec/dummy/log/.keep +0 -0
- metadata +78 -10
- data/spec/dummy/log/test.log +0 -85730
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 927a4565c38e1512685b3dfd996f02c190835387
|
|
4
|
+
data.tar.gz: ae853db448b6bfeac215261b925b0877450326cd
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 38a297f31b3b99cb7d377479793dfb86d595b5f307629cb43a622d525137ffefef102a919591a9ef8e9756bdcfb91b7f1574c70ac3369d99d72fc1a098ac8fe9
|
|
7
|
+
data.tar.gz: 1234305aa80b6489041eb86eed6b1b0c32a6725f3d803fee66edf7364e89c3dbe666590104a7341fe6f6af62df92dbc9fd732b90b43ae455828a60d3c8847d8e
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/Gemfile
ADDED
data/LICENSE
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
Copyright (c) 2014 Semyon Pupkov
|
|
2
|
+
|
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
|
4
|
+
a copy of this software and associated documentation files (the
|
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
|
9
|
+
the following conditions:
|
|
10
|
+
|
|
11
|
+
The above copyright notice and this permission notice shall be
|
|
12
|
+
included in all copies or substantial portions of the Software.
|
|
13
|
+
|
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
power_shop
|
|
2
|
+
==========
|
|
3
|
+
|
|
4
|
+
Simple and flexible Ruby On Rails Ecomerce engine
|
|
5
|
+
|
|
6
|
+

|
|
7
|
+
[](https://codeclimate.com/github/artofhuman/power_shop)
|
|
8
|
+
[](http://badge.fury.io/rb/power_shop)
|
|
9
|
+
|
|
10
|
+
Requirements
|
|
11
|
+
|
|
12
|
+
1. CKeditor https://github.com/galetahub/ckeditor (Add gem ckeditor to you Gemfile)
|
|
13
|
+
2. Rmagick (sudo apt-get install libmagickwand-dev)
|
data/Rakefile
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
begin
|
|
2
|
+
require 'bundler/setup'
|
|
3
|
+
rescue LoadError
|
|
4
|
+
puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
require 'active_support/deprecation'
|
|
8
|
+
ActiveSupport::Deprecation.silenced = true
|
|
9
|
+
|
|
10
|
+
APP_RAKEFILE = File.expand_path("../spec/dummy/Rakefile", __FILE__)
|
|
11
|
+
load 'rails/tasks/engine.rake'
|
|
12
|
+
|
|
13
|
+
load 'lib/tasks/spec.rake'
|
|
14
|
+
|
|
15
|
+
Bundler::GemHelper.install_tasks
|
|
16
|
+
Dir[File.join(File.dirname(__FILE__), 'tasks/**/*.rake')].each {|f| load f }
|
|
17
|
+
|
|
18
|
+
task :default => [:spec]
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
module PowerShop
|
|
2
|
+
class ApplicationController < ::ApplicationController
|
|
3
|
+
|
|
4
|
+
# Public: get cart from middleware
|
|
5
|
+
# TODO: concern for project application controller
|
|
6
|
+
#
|
|
7
|
+
# Returns ShoppingCart
|
|
8
|
+
def cart
|
|
9
|
+
@cart ||= request.env['shopping_cart']
|
|
10
|
+
end
|
|
11
|
+
helper_method :cart
|
|
12
|
+
end
|
|
13
|
+
end
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
module PowerShop
|
|
2
|
+
# Controller represents methods for cart
|
|
3
|
+
class CartController < PowerShop::ApplicationController
|
|
4
|
+
|
|
5
|
+
before_filter :find_product, :only => [:add_product, :delete_product]
|
|
6
|
+
skip_before_filter :verify_authenticity_token
|
|
7
|
+
|
|
8
|
+
# Public: add products to shopping cart
|
|
9
|
+
# if request is simple post redirects back
|
|
10
|
+
# if request is ajax respond with json message
|
|
11
|
+
#
|
|
12
|
+
# Returns text/html or text/json
|
|
13
|
+
def add_product
|
|
14
|
+
cart.add(@product, @product.price, params.fetch(:quantity, 1))
|
|
15
|
+
|
|
16
|
+
if request.xhr?
|
|
17
|
+
render_json_cart
|
|
18
|
+
else
|
|
19
|
+
redirect_to :back
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def delete_product
|
|
24
|
+
# TODO: 99 - its hack for remove all items :)
|
|
25
|
+
cart.remove(@product, 99)
|
|
26
|
+
redirect_to :back
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
# Pubclic: show cart page
|
|
30
|
+
# TODO: preload associations
|
|
31
|
+
#
|
|
32
|
+
# Returns text/html
|
|
33
|
+
def show
|
|
34
|
+
@cart = cart
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
protected
|
|
38
|
+
|
|
39
|
+
def find_product
|
|
40
|
+
@product = ::Product.find(params[:product_id])
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
# Internal: render json response with cart params
|
|
44
|
+
#
|
|
45
|
+
# Returns text/json
|
|
46
|
+
def render_json_cart
|
|
47
|
+
render :json => {
|
|
48
|
+
total_items: cart.total_unique_items,
|
|
49
|
+
subtotal: cart.subtotal
|
|
50
|
+
}.to_json
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
module PowerShop
|
|
2
|
+
class CatalogController < PowerShop::ApplicationController
|
|
3
|
+
# Public: show all products with pagination
|
|
4
|
+
#
|
|
5
|
+
# Returns: text/html
|
|
6
|
+
def index
|
|
7
|
+
@products = scoped_products.page(params[:page])
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
# Public: show products inside current category
|
|
11
|
+
#
|
|
12
|
+
# Returns: text/html
|
|
13
|
+
def category
|
|
14
|
+
@category = ::Category.friendly.find(params[:id])
|
|
15
|
+
@products = scoped_products.where(category: @category).page(params[:page])
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
# Public: show detail page for product
|
|
19
|
+
#
|
|
20
|
+
# Returns text/html
|
|
21
|
+
def product
|
|
22
|
+
@category = ::Category.friendly.find(params[:category_id])
|
|
23
|
+
@product = scoped_products.friendly.find(params[:id])
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
protected
|
|
27
|
+
|
|
28
|
+
def scoped_products
|
|
29
|
+
::Product.active.includes(:images, :category)
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
module PowerShop
|
|
2
|
+
class OrdersController < PowerShop::ApplicationController
|
|
3
|
+
|
|
4
|
+
# GET: create new order action
|
|
5
|
+
# if order success created, redirect to success page
|
|
6
|
+
#
|
|
7
|
+
# Returns text/html
|
|
8
|
+
def create
|
|
9
|
+
@cart = cart
|
|
10
|
+
@order_form = ::OrderForm.new(@cart, permited_params[:order_form])
|
|
11
|
+
|
|
12
|
+
if @order_form.valid?
|
|
13
|
+
if @order_form.perform
|
|
14
|
+
flash[:order_id] = @order_form.order.id
|
|
15
|
+
return redirect_to power_shop.success_order_url
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
render :template => 'power_shop/cart/show'
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
# GET: show simple page for success message
|
|
23
|
+
#
|
|
24
|
+
# Returns text/html
|
|
25
|
+
def success
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
protected
|
|
29
|
+
def permited_params
|
|
30
|
+
params.permit(order_form: [:user_name, :user_phone, :user_email])
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
# coding: utf-8
|
|
2
|
+
|
|
3
|
+
module PowerShop
|
|
4
|
+
# class represent form for create new order
|
|
5
|
+
# TODO: this class want specs
|
|
6
|
+
class OrderForm
|
|
7
|
+
include ActiveModel::Model
|
|
8
|
+
|
|
9
|
+
attr_accessor :user_name, :user_email, :user_phone, :delivery_address
|
|
10
|
+
attr_reader :cart, :order
|
|
11
|
+
|
|
12
|
+
validates :user_name, :user_phone, presence: true
|
|
13
|
+
validates_email_format_of :user_email, allow_nil: true, allow_blank: true
|
|
14
|
+
|
|
15
|
+
delegate :total, :to => :cart
|
|
16
|
+
|
|
17
|
+
# Public: initialize new order form
|
|
18
|
+
#
|
|
19
|
+
# cart - Shopping cart
|
|
20
|
+
def initialize(cart, attributes={})
|
|
21
|
+
@order = ::Order.new
|
|
22
|
+
@cart = cart
|
|
23
|
+
|
|
24
|
+
apply_attributes(attributes) if attributes.present?
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
# Public: process create new order, clear cart, and sent notifications
|
|
28
|
+
#
|
|
29
|
+
# Example:
|
|
30
|
+
# if @order_form.valid?
|
|
31
|
+
# @order_form.perform
|
|
32
|
+
#
|
|
33
|
+
# Returns boolean
|
|
34
|
+
def perform
|
|
35
|
+
return false unless valid?
|
|
36
|
+
|
|
37
|
+
if result = make_order
|
|
38
|
+
cart.clear
|
|
39
|
+
send_emails
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
result
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
protected
|
|
46
|
+
|
|
47
|
+
def create_order_items
|
|
48
|
+
cart.shopping_cart_items.each do |cart_item|
|
|
49
|
+
order.order_items.create(
|
|
50
|
+
{
|
|
51
|
+
product_id: cart_item.item.id,
|
|
52
|
+
product_title: cart_item.item.name,
|
|
53
|
+
price: cart_item.price,
|
|
54
|
+
quantity: cart_item.quantity
|
|
55
|
+
}
|
|
56
|
+
)
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def create_order
|
|
61
|
+
not_expected_attributes = ['id', 'created_at', 'updated_at']
|
|
62
|
+
order_attributes = @order.attribute_names.reject do |attr|
|
|
63
|
+
not_expected_attributes.include?(attr)
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
order_attributes.each do |attr|
|
|
67
|
+
order.send("#{attr}=", self.send(attr))
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
order.save!
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
# Internal: it makes order in database
|
|
74
|
+
#
|
|
75
|
+
# Retuurns boolean
|
|
76
|
+
def make_order
|
|
77
|
+
ActiveRecord::Base.transaction do
|
|
78
|
+
create_order
|
|
79
|
+
create_order_items
|
|
80
|
+
end
|
|
81
|
+
rescue
|
|
82
|
+
false
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
def send_emails
|
|
86
|
+
::OrderNotifications.for_admin(order).deliver
|
|
87
|
+
::OrderNotifications.for_user(order, user_email).deliver if user_email.present?
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
# Internal: sets form values
|
|
91
|
+
#
|
|
92
|
+
# Returns nothing
|
|
93
|
+
def apply_attributes(attributes)
|
|
94
|
+
attributes.each_pair do |attr, value|
|
|
95
|
+
send("#{attr}=", value)
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
end
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
module PowerShop
|
|
2
|
+
class OrderNotifications < ActionMailer::Base
|
|
3
|
+
default from: "from@example.com"
|
|
4
|
+
|
|
5
|
+
def for_admin(order)
|
|
6
|
+
@order = order
|
|
7
|
+
mail(
|
|
8
|
+
to: admin_emails,
|
|
9
|
+
subject: 'На сайте оформлен заказ',
|
|
10
|
+
content_type: "text/html"
|
|
11
|
+
)
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def for_user(order, user_email)
|
|
15
|
+
@order = order
|
|
16
|
+
mail(
|
|
17
|
+
to: user_email,
|
|
18
|
+
subject: 'Спасибо за заказ',
|
|
19
|
+
content_type: "text/html"
|
|
20
|
+
)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
protected
|
|
24
|
+
|
|
25
|
+
def admin_emails
|
|
26
|
+
'admin@example.com'
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
data/app/models/order.rb
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
module PowerShop
|
|
2
|
+
class Category < ActiveRecord::Base
|
|
3
|
+
self.abstract_class = true
|
|
4
|
+
self.table_name = 'categories'
|
|
5
|
+
|
|
6
|
+
acts_as_nested_set
|
|
7
|
+
|
|
8
|
+
has_many :products, :dependent => :destroy,
|
|
9
|
+
class_name: '::Product'
|
|
10
|
+
|
|
11
|
+
has_one :image, :class_name => '::ShopImage', :as => :subject,
|
|
12
|
+
:dependent => :destroy
|
|
13
|
+
|
|
14
|
+
accepts_nested_attributes_for :image, :allow_destroy => true
|
|
15
|
+
|
|
16
|
+
validates :name, presence: true
|
|
17
|
+
end
|
|
18
|
+
end
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
module PowerShop
|
|
2
|
+
class Product < ActiveRecord::Base
|
|
3
|
+
self.abstract_class = true
|
|
4
|
+
self.table_name = 'products'
|
|
5
|
+
|
|
6
|
+
belongs_to :category, class_name: '::Category'
|
|
7
|
+
|
|
8
|
+
# == Calbacks for calculate active products in category
|
|
9
|
+
after_create :increment_category_count, if: ->(product) { product.active? }
|
|
10
|
+
after_destroy :decrement_category_count, if: ->(product) { product.active? }
|
|
11
|
+
after_update :touch_category_count
|
|
12
|
+
|
|
13
|
+
has_many :images, :class_name => '::ShopImage', :as => :subject,
|
|
14
|
+
:dependent => :destroy
|
|
15
|
+
|
|
16
|
+
accepts_nested_attributes_for :images, :allow_destroy => true
|
|
17
|
+
validates_presence_of :name, :price, :category_id
|
|
18
|
+
|
|
19
|
+
# Public: get only active products
|
|
20
|
+
#
|
|
21
|
+
# Returns ActiveRecord::Relation
|
|
22
|
+
def self.active
|
|
23
|
+
where(active: true)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
# Public: get first image from images
|
|
27
|
+
#
|
|
28
|
+
# Returns ShopImage
|
|
29
|
+
def main_image
|
|
30
|
+
images.first
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def increment_category_count
|
|
34
|
+
::Category.increment_counter :products_count, category_id
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def decrement_category_count
|
|
38
|
+
::Category.decrement_counter :products_count, category_id
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def touch_category_count
|
|
42
|
+
active? ? increment_category_count : decrement_category_count
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
|
|
3
|
+
module PowerShop
|
|
4
|
+
class ShopImageUploader < CarrierWave::Uploader::Base
|
|
5
|
+
|
|
6
|
+
include CarrierWave::RMagick
|
|
7
|
+
|
|
8
|
+
# Choose what kind of storage to use for this uploader:
|
|
9
|
+
storage :file
|
|
10
|
+
# storage :fog
|
|
11
|
+
|
|
12
|
+
# Override the directory where uploaded files will be stored.
|
|
13
|
+
# This is a sensible default for uploaders that are meant to be mounted:
|
|
14
|
+
def store_dir
|
|
15
|
+
"uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
version :admin_thumb do
|
|
19
|
+
process :resize_to_limit => [100, 100]
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
version :thumb do
|
|
23
|
+
process :resize_to_limit => [100, 100]
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def extension_white_list
|
|
27
|
+
%w(jpg jpeg png)
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
data/config/routes.rb
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# coding: utf-8
|
|
2
|
+
PowerShop::Engine.routes.draw do
|
|
3
|
+
scope 'catalog' do
|
|
4
|
+
get '/:id', to: 'catalog#category', as: 'category'
|
|
5
|
+
get '/:category_id/:id', to: 'catalog#product', as: 'product'
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
get 'catalog', to: 'catalog#index'
|
|
9
|
+
|
|
10
|
+
resource :cart, :only => [:show, :destroy], controller: 'cart' do
|
|
11
|
+
post 'add_product/:product_id' => 'cart#add_product', :as => 'add_product'
|
|
12
|
+
delete 'delete_product/:product_id' => 'cart#delete_product', :as => 'delete_product'
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
resource :order, :only => :create do
|
|
16
|
+
get 'success' => 'orders#success'
|
|
17
|
+
end
|
|
18
|
+
end
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
class CreateCategories < ActiveRecord::Migration
|
|
2
|
+
def change
|
|
3
|
+
create_table :categories do |t|
|
|
4
|
+
t.string :name, null: false
|
|
5
|
+
t.string :slug
|
|
6
|
+
t.integer :parent_id
|
|
7
|
+
t.integer :lft
|
|
8
|
+
t.integer :rgt
|
|
9
|
+
t.integer :depth
|
|
10
|
+
t.text :description
|
|
11
|
+
|
|
12
|
+
t.timestamps
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
add_index :categories, :slug, unique: true
|
|
16
|
+
add_index :categories, :rgt
|
|
17
|
+
add_index :categories, :lft
|
|
18
|
+
add_index :categories, :parent_id
|
|
19
|
+
end
|
|
20
|
+
end
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
class CreateProducts < ActiveRecord::Migration
|
|
2
|
+
def change
|
|
3
|
+
create_table :products do |t|
|
|
4
|
+
t.belongs_to :category, null: false
|
|
5
|
+
t.boolean :active, default: true
|
|
6
|
+
t.string :name, null: false
|
|
7
|
+
t.string :slug
|
|
8
|
+
t.text :description
|
|
9
|
+
t.float :price, null: false
|
|
10
|
+
t.integer :sort, default: 500
|
|
11
|
+
|
|
12
|
+
t.timestamps
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
add_index :products, :slug, unique: true
|
|
16
|
+
add_index :products, :category_id
|
|
17
|
+
|
|
18
|
+
add_column :categories, :products_count, :integer, :default => 0
|
|
19
|
+
end
|
|
20
|
+
end
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
class CreateShopImage < ActiveRecord::Migration
|
|
2
|
+
def change
|
|
3
|
+
create_table :shop_images do |t|
|
|
4
|
+
t.integer :subject_id, null: false
|
|
5
|
+
t.string :subject_type, null: false
|
|
6
|
+
t.string :image
|
|
7
|
+
|
|
8
|
+
t.timestamps
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
add_index :shop_images, :subject_id
|
|
12
|
+
end
|
|
13
|
+
end
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
class CreateFriendlyIdSlugs < ActiveRecord::Migration
|
|
2
|
+
def change
|
|
3
|
+
create_table :friendly_id_slugs do |t|
|
|
4
|
+
t.string :slug, :null => false
|
|
5
|
+
t.integer :sluggable_id, :null => false
|
|
6
|
+
t.string :sluggable_type, :limit => 50
|
|
7
|
+
t.string :scope
|
|
8
|
+
t.datetime :created_at
|
|
9
|
+
end
|
|
10
|
+
add_index :friendly_id_slugs, :sluggable_id
|
|
11
|
+
add_index :friendly_id_slugs, [:slug, :sluggable_type]
|
|
12
|
+
add_index :friendly_id_slugs, [:slug, :sluggable_type, :scope], :unique => true
|
|
13
|
+
add_index :friendly_id_slugs, :sluggable_type
|
|
14
|
+
end
|
|
15
|
+
end
|