Commit cf65a71d by Tan Phat Nguyen

Add feature cart creation

parent 3075e83f
# Place all the behaviors and hooks related to the matching controller here.
# All this logic will automatically be available in application.js.
# You can use CoffeeScript in this file: http://coffeescript.org/
...@@ -88,4 +88,18 @@ h2 { ...@@ -88,4 +88,18 @@ h2 {
.button_to .btn-default { .button_to .btn-default {
background-color: #FFC741; background-color: #FFC741;
}
.r-text {
text-align: right;
}
.nav-icon {
background-image: url(http://g-ecx.images-amazon.com/images/G/01/gno/sprites/global-sprite-32-v3._V325667795_.png);
//background-position: -10px 1024px;
background-position: -10px -266px;
}
.nav-icon:hover {
background-position: -10px 1024px;
} }
\ No newline at end of file
// Place all the styles related to the orders controller here.
// They will automatically be included in application.css.
// You can use Sass (SCSS) here: http://sass-lang.com/
...@@ -16,14 +16,7 @@ class ApplicationController < ActionController::Base ...@@ -16,14 +16,7 @@ class ApplicationController < ActionController::Base
private private
def record_not_found def record_not_found
flash[:danger] = 'Record Not found.'
redirect_to root_path redirect_to root_path
end end
def current_cart
Cart.find(session[:cart_id])
rescue ActiveRecord::RecordNotFound
cart = Cart.create
session[:cart_id] = cart.id
cart
end
end end
...@@ -6,6 +6,7 @@ class CartsController < ApplicationController ...@@ -6,6 +6,7 @@ class CartsController < ApplicationController
end end
def show def show
@carts = current_cart
end end
def new def new
...@@ -43,10 +44,8 @@ class CartsController < ApplicationController ...@@ -43,10 +44,8 @@ class CartsController < ApplicationController
def destroy def destroy
@cart.destroy @cart.destroy
respond_to do |format| flash[:success] = 'Cart is empty.'
format.html { redirect_to carts_url, notice: 'Cart was successfully destroyed.' } redirect_to root_path
format.json { head :no_content }
end
end end
private private
......
...@@ -20,7 +20,10 @@ class LineItemsController < ApplicationController ...@@ -20,7 +20,10 @@ class LineItemsController < ApplicationController
product = Product.find(params[:product_id]) product = Product.find(params[:product_id])
@line_item = @cart.add_product(product.id) @line_item = @cart.add_product(product.id)
redirect_to @line_item.cart if @line_item.save if @line_item.save
flash[:success] = 'You have just one item in cart.'
redirect_to @line_item.cart
end
end end
def update def update
......
class OrdersController < ApplicationController
before_action :set_order, only: [:show, :edit, :update, :destroy]
def index
@orders = Order.newest.page(params[:page])
end
def show
end
def new
if current_cart.line_items.empty?
redirect_to root_path
  • @phatnt You should merge two lines by: redirect_to root_path if current_cart.line_items.empty?

    Edited
Please register or sign in to reply
return
end
@order = Order.new
end
def edit
end
def create
@order = Order.new(order_params)
@order.add_line_items_from_cart(current_cart)
if @order.save
Cart.destroy(session[:cart_id])
session[:cart_id] = nil
flash[:success] = 'Successfully. Thank you for your order.'
redirect_to root_path
else
render :new
end
end
def update
if @order.update(order_params)
flash[:success] = 'Order was successfully updated.'
redirect_to @order
else
render :edit
end
end
def destroy
@order.destroy
flash[:success] = 'Order was successfully destroyed.'
redirect_to orders_path
end
private
def set_order
@order = Order.find(params[:id])
end
def order_params
params.require(:order).permit(:name, :address, :email, :pay_type)
end
end
...@@ -7,4 +7,12 @@ module ApplicationHelper ...@@ -7,4 +7,12 @@ module ApplicationHelper
"#{page_title} | #{base_title}" "#{page_title} | #{base_title}"
end end
end end
def current_cart
Cart.find(session[:cart_id])
rescue ActiveRecord::RecordNotFound
cart = Cart.create
session[:cart_id] = cart.id
cart
end
end end
module OrdersHelper
end
...@@ -11,4 +11,8 @@ class Cart < ActiveRecord::Base ...@@ -11,4 +11,8 @@ class Cart < ActiveRecord::Base
end end
current_item current_item
end end
def total_price
line_items.to_a.sum { |item| item.total_price }
end
end end
class LineItem < ActiveRecord::Base class LineItem < ActiveRecord::Base
belongs_to :product belongs_to :product
belongs_to :cart belongs_to :cart
belongs_to :order
def total_price
quantity * product.price
end
end end
class Order < ActiveRecord::Base
scope :newest, -> { order(created_at: :desc) }
PAYMENT_TYPES = [ 'Check', 'Credit card', 'Purchase order' ]
has_many :line_items, dependent: :destroy
validates :name, :address, :email, :pay_type, presence: true
validates :pay_type, inclusion: PAYMENT_TYPES
paginates_per 10
def add_line_items_from_cart(cart)
cart.line_items.each do |item|
Please register or sign in to reply
  • cart is parameter in situation order not relationship with cart flow: cart has_many line_items order has_many line_items and set cart_id = nil in line_item and set order_id in equal line_item

Please register or sign in to reply
item.cart_id = nil
line_items << item
end
end
def total_price
line_items.to_a.sum { |item| item.total_price }
end
end
json.array!(@carts) do |cart|
json.extract! cart, :id
json.url cart_url(cart, format: :json)
end
<%= provide(:title, 'Current Cart') %> <%= provide(:title, 'Current Cart') %>
<h1 class='page-header'>Venshop Cart Infomation</h1> <h1 class='page-header'>Your Cart Infomation</h1>
<ul> <table class="table">
<% @cart.line_items.each do |item| %> <%= render @cart.line_items %>
<li><%= item.quantity %> &times; <%= item.product.name %></li> <tr class="success">
<% end %> <td colspan='3' class='r-text'>Total</td>
</ul> <td>$<%= @cart.total_price %></td>
</tr>
</table>
<div class='row'>
<div class='col-md-5'></div>
<div class='col-md-1'>
<%= button_to 'Checkout', new_order_url, method: :get, class: 'btn btn-default' %>
</div>
<div class='col-md-1'>
<%= button_to 'Empty Cart', @cart, method: :delete, data: { confirm: 'Are you sure?' }, class: 'btn btn-default' %>
</div>
</div>
json.extract! @cart, :id, :created_at, :updated_at
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
<li><%= link_to 'Home', root_path %></li> <li><%= link_to 'Home', root_path %></li>
<li><%= link_to 'Log in', '#' %></li> <li><%= link_to 'Log in', '#' %></li>
<li><%= link_to 'Register', '#' %></li> <li><%= link_to 'Register', '#' %></li>
<li style='width: 36px'><%= link_to '', cart_path(current_cart), class: 'nav-icon' %></li>
</ul> </ul>
<form class='navbar-form navbar-right'> <form class='navbar-form navbar-right'>
<input type='text' class='form-control' placeholder='Search...'> <input type='text' class='form-control' placeholder='Search...'>
......
...@@ -20,6 +20,10 @@ ...@@ -20,6 +20,10 @@
</ul> </ul>
</div> </div>
<div class='col-sm-9 col-sm-offset-3 col-md-10 col-md-offset-2 main'> <div class='col-sm-9 col-sm-offset-3 col-md-10 col-md-offset-2 main'>
<% flash.each do |message_type, message| %>
  • @phatnt You should move those errors to a partial called _errors.html.erb in application folder. Then you can render to here by: render 'errors'

Please register or sign in to reply
<!-- <div class="alert alert-<%= message_type %>"><%= message %></div> -->
Please register or sign in to reply
<%= content_tag(:div, message, class: "alert alert-#{message_type}") %>
<% end %>
<%= yield %> <%= yield %>
</div> </div>
</div> </div>
......
<tr>
<td><%= line_item.product.name %></td>
<td><%= line_item.product.category.name %></td>
<td class='r-text'><%= line_item.quantity %> &times; <%= line_item.product.price %> = </td>
<td>$<%= line_item.total_price %></td>
</tr>
\ No newline at end of file
<%= form_for(@order) do |f| %>
<%= render 'shared/error_messages', object: f.object %>
<div class="form-group">
<%= f.label :name %><br>
<%= f.text_field :name, class: 'form-control', placeholder: 'ex: Nguyen Tan Phat' %>
</div>
<div class="form-group">
<%= f.label :address %><br>
<%= f.text_area :address, class: 'form-control', placeholder: 'ex: 4 Nguyen Thi Minh Khai' %>
</div>
<div class="form-group">
<%= f.label :email %><br>
<%= f.text_field :email, class: 'form-control', placeholder: 'ex: example@example.com' %>
</div>
<div class="form-group">
<%= f.label :pay_type %><br>
<%= f.select :pay_type, Order::PAYMENT_TYPES, prompt: 'Select a payment method' %>
</div>
<%= f.submit 'Place Order', class: "btn btn-primary" %>
<% end %>
<tr>
<td><%= order.name %></td>
<td><%= order.address %></td>
<td><%= order.email %></td>
<td><%= order.pay_type %></td>
<td><%= link_to 'Show', order %></td>
<td><%= link_to 'Edit', edit_order_path(order) %></td>
<td><%= link_to 'Destroy', order, method: :delete, data: { confirm: 'Are you sure?' } %></td>
</tr>
<% provide(:title, "Edit Product") %>
<h1 class='page-header'>Edit Product</h1>
<%= render 'form' %>
<%= link_to 'Show', @order %> |
<%= link_to 'Back', orders_path %>
<% provide(:title, 'Order Lists') %>
<h1 class='page-header'>Your Orders History</h1>
<div class='table-responsive'>
<table class='table table-striped'>
<tr>
<th>Name</th>
<th>Address</th>
<th>Email</th>
<th>Pay type</th>
<th colspan='3'></th>
</tr>
<%= render @orders %>
</table>
<%= paginate @orders %>
</div>
\ No newline at end of file
json.array!(@orders) do |order|
Please register or sign in to reply
json.extract! order, :id, :name, :address, :email, :pay_type
json.url order_url(order, format: :json)
end
<% provide(:title, 'Order Checkout') %>
<h1 class='page-header'>Please Enter Your Details</h1>
<%= render 'form' %>
\ No newline at end of file
<% provide(:title, @order.name) %>
<h1 class='page-header'>Show Order</h1>
<p>Name: <b><%= @order.name%></b></p>
<p>Address: <b><%= @order.address%></b></p>
<p>Email: <b><%= @order.email%></b></p>
<p>Pay type: <b><%= @order.pay_type%></b></p>
<%= link_to 'Back', orders_path, class: 'btn btn-primary' %>
<%= link_to 'Edit', edit_order_path(@order), class: 'btn btn-primary' %>
<h2 class='sub-header'>Items Detail</h2>
<table class="table">
<%= render @order.line_items %>
<tr class="success">
<td colspan='3' class='r-text'>Total</td>
<td>$<%= @order.total_price %></td>
</tr>
</table>
\ No newline at end of file
json.extract! @order, :id, :name, :address, :email, :pay_type, :created_at, :updated_at
...@@ -17,6 +17,6 @@ ...@@ -17,6 +17,6 @@
<p><%= @product.description %></p> <p><%= @product.description %></p>
</div> </div>
<div class='row'> <div class='row'>
<%= button_to 'Buy', line_items_path(product_id: @product), { class: 'btn btn-default' } %> <%= button_to 'Buy', line_items_path(product_id: @product), class: 'btn btn-default' %>
</div> </div>
<% end %> <% end %>
\ No newline at end of file
Rails.application.routes.draw do Rails.application.routes.draw do
resources :line_items resources :orders
resources :carts resources :line_items, only: [ :create ]
resources :carts, only: [ :show, :destroy ]
namespace :admin do namespace :admin do
resources :products resources :products
...@@ -13,7 +15,7 @@ Rails.application.routes.draw do ...@@ -13,7 +15,7 @@ Rails.application.routes.draw do
get '/category/:id', to: 'categories#show', as: 'category' get '/category/:id', to: 'categories#show', as: 'category'
resources :products, only: [:show] resources :products, only: [ :show ]
get 'home' => 'home#index' get 'home' => 'home#index'
root 'home#index' root 'home#index'
......
class CreateOrders < ActiveRecord::Migration
def change
create_table :orders do |t|
t.string :name
t.text :address
t.string :email
t.string :pay_type
t.timestamps null: false
end
end
end
class AddOrderIdToLineItem < ActiveRecord::Migration
def change
add_column :line_items, :order_id, :integer
end
end
...@@ -11,7 +11,7 @@ ...@@ -11,7 +11,7 @@
# #
# It's strongly recommended that you check this file into your version control system. # It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema.define(version: 20141112101735) do ActiveRecord::Schema.define(version: 20141113023836) do
create_table "carts", force: true do |t| create_table "carts", force: true do |t|
t.datetime "created_at", null: false t.datetime "created_at", null: false
...@@ -30,6 +30,16 @@ ActiveRecord::Schema.define(version: 20141112101735) do ...@@ -30,6 +30,16 @@ ActiveRecord::Schema.define(version: 20141112101735) do
t.datetime "created_at", null: false t.datetime "created_at", null: false
t.datetime "updated_at", null: false t.datetime "updated_at", null: false
t.integer "quantity", limit: 4, default: 1 t.integer "quantity", limit: 4, default: 1
t.integer "order_id", limit: 4
end
create_table "orders", force: true do |t|
t.string "name", limit: 255
t.text "address", limit: 65535
t.string "email", limit: 255
t.string "pay_type", limit: 255
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end end
create_table "products", force: true do |t| create_table "products", force: true do |t|
......
require 'test_helper'
class OrdersControllerTest < ActionController::TestCase
setup do
@order = orders(:one)
end
test "should get index" do
get :index
assert_response :success
assert_not_nil assigns(:orders)
end
test "should get new" do
get :new
assert_response :success
end
test "should create order" do
assert_difference('Order.count') do
post :create, order: { address: @order.address, email: @order.email, name: @order.name, pay_type: @order.pay_type }
end
assert_redirected_to order_path(assigns(:order))
end
test "should show order" do
get :show, id: @order
assert_response :success
end
test "should get edit" do
get :edit, id: @order
assert_response :success
end
test "should update order" do
patch :update, id: @order, order: { address: @order.address, email: @order.email, name: @order.name, pay_type: @order.pay_type }
assert_redirected_to order_path(assigns(:order))
end
test "should destroy order" do
assert_difference('Order.count', -1) do
delete :destroy, id: @order
end
assert_redirected_to orders_path
end
end
# Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html
one:
name: MyString
address: MyText
email: MyString
pay_type: MyString
two:
name: MyString
address: MyText
email: MyString
pay_type: MyString
require 'test_helper'
class OrderTest < ActiveSupport::TestCase
# test "the truth" do
# assert true
# end
end
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment