Commit 3075e83f by Tan Phat Nguyen

Add cart of product

parent c57a728d
# 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/
# 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/
// Place all the styles related to the carts controller here.
// They will automatically be included in application.css.
// You can use Sass (SCSS) here: http://sass-lang.com/
...@@ -84,4 +84,8 @@ h2 { ...@@ -84,4 +84,8 @@ h2 {
.col-sm-3 { .col-sm-3 {
width: 20%; width: 20%;
}
.button_to .btn-default {
background-color: #FFC741;
} }
\ No newline at end of file
// Place all the styles related to the line_items controller here.
// They will automatically be included in application.css.
// You can use Sass (SCSS) here: http://sass-lang.com/
...@@ -5,9 +5,25 @@ class ApplicationController < ActionController::Base ...@@ -5,9 +5,25 @@ class ApplicationController < ActionController::Base
rescue_from ActiveRecord::RecordNotFound, :with => :record_not_found rescue_from ActiveRecord::RecordNotFound, :with => :record_not_found
def current_cart
Cart.find(session[:cart_id])
rescue ActiveRecord::RecordNotFound
cart = Cart.create
session[:cart_id] = cart.id
cart
end
private private
def record_not_found def record_not_found
redirect_to root_path redirect_to root_path
end
def current_cart
Cart.find(session[:cart_id])
rescue ActiveRecord::RecordNotFound
cart = Cart.create
session[:cart_id] = cart.id
cart
end end
end end
class CartsController < ApplicationController
before_action :set_cart, only: [:show, :edit, :update, :destroy]
def index
@carts = Cart.all
end
def show
end
def new
@cart = Cart.new
end
def edit
end
def create
@cart = Cart.new(cart_params)
respond_to do |format|
if @cart.save
format.html { redirect_to @cart, notice: 'Cart was successfully created.' }
format.json { render :show, status: :created, location: @cart }
else
format.html { render :new }
format.json { render json: @cart.errors, status: :unprocessable_entity }
end
end
end
def update
respond_to do |format|
if @cart.update(cart_params)
format.html { redirect_to @cart, notice: 'Cart was successfully updated.' }
format.json { render :show, status: :ok, location: @cart }
else
format.html { render :edit }
format.json { render json: @cart.errors, status: :unprocessable_entity }
end
end
end
def destroy
@cart.destroy
respond_to do |format|
format.html { redirect_to carts_url, notice: 'Cart was successfully destroyed.' }
format.json { head :no_content }
end
end
private
def set_cart
@cart = Cart.find(params[:id])
end
def cart_params
params[:cart]
end
end
class LineItemsController < ApplicationController
before_action :set_line_item, only: [:show, :edit, :update, :destroy]
def index
@line_items = LineItem.all
end
def show
end
def new
@line_item = LineItem.new
end
def edit
end
def create
@cart = current_cart
product = Product.find(params[:product_id])
@line_item = @cart.add_product(product.id)
redirect_to @line_item.cart if @line_item.save
end
def update
respond_to do |format|
if @line_item.update(line_item_params)
format.html { redirect_to @line_item, notice: 'Line item was successfully updated.' }
format.json { render :show, status: :ok, location: @line_item }
else
format.html { render :edit }
format.json { render json: @line_item.errors, status: :unprocessable_entity }
end
end
end
def destroy
@line_item.destroy
respond_to do |format|
format.html { redirect_to line_items_url, notice: 'Line item was successfully destroyed.' }
format.json { head :no_content }
end
end
private
def set_line_item
@line_item = LineItem.find(params[:id])
end
def line_item_params
params.require(:line_item).permit(:product_id, :cart_id)
end
end
module CartsHelper
end
module LineItemsHelper
end
class Cart < ActiveRecord::Base
has_many :line_items, :dependent => :destroy
def add_product(product_id)
current_item = line_items.where(product_id: product_id).first
if current_item
current_item.quantity += 1
else
current_item = LineItem.new(product_id: product_id)
line_items << current_item
end
current_item
end
end
class LineItem < ActiveRecord::Base
belongs_to :product
belongs_to :cart
end
class Product < ActiveRecord::Base class Product < ActiveRecord::Base
scope :newest, -> { order(created_at: :desc).limit(5) }
belongs_to :category belongs_to :category
has_many :line_items
validates :name, presence: true, length: { maximum: 200 } validates :name, presence: true, length: { maximum: 200 }
validates :price, presence: true, numericality: true, validates :price, presence: true, numericality: true,
...@@ -8,12 +11,21 @@ class Product < ActiveRecord::Base ...@@ -8,12 +11,21 @@ class Product < ActiveRecord::Base
validates :description, presence: true validates :description, presence: true
validate :photo_size validate :photo_size
scope :newest, -> { order(created_at: :desc).limit(5) } before_destroy :ensure_not_referenced_by_any_line_item
mount_uploader :photo, ImageUploader mount_uploader :photo, ImageUploader
paginates_per 10 paginates_per 10
def ensure_not_referenced_by_any_line_item
if line_items.count.zero?
return true
else
errors[:base] << 'Line Items present'
return false
end
end
private private
def photo_size def photo_size
......
<%= form_for(@cart) do |f| %>
<% if @cart.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(@cart.errors.count, "error") %> prohibited this cart from being saved:</h2>
<ul>
<% @cart.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
<h1>Editing Cart</h1>
<%= render 'form' %>
<%= link_to 'Show', @cart %> |
<%= link_to 'Back', carts_path %>
<p id="notice"><%= notice %></p>
<h1>Listing Carts</h1>
<table>
<thead>
<tr>
<th colspan="3"></th>
</tr>
</thead>
<tbody>
<% @carts.each do |cart| %>
<tr>
<td><%= link_to 'Show', cart %></td>
<td><%= link_to 'Edit', edit_cart_path(cart) %></td>
<td><%= link_to 'Destroy', cart, method: :delete, data: { confirm: 'Are you sure?' } %></td>
</tr>
<% end %>
</tbody>
</table>
<br>
<%= link_to 'New Cart', new_cart_path %>
json.array!(@carts) do |cart|
json.extract! cart, :id
json.url cart_url(cart, format: :json)
end
<h1>New Cart</h1>
<%= render 'form' %>
<%= link_to 'Back', carts_path %>
<%= provide(:title, 'Current Cart') %>
<h1 class='page-header'>Venshop Cart Infomation</h1>
<ul>
<% @cart.line_items.each do |item| %>
<li><%= item.quantity %> &times; <%= item.product.name %></li>
<% end %>
</ul>
json.extract! @cart, :id, :created_at, :updated_at
<%= form_for(@line_item) do |f| %>
<% if @line_item.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(@line_item.errors.count, "error") %> prohibited this line_item from being saved:</h2>
<ul>
<% @line_item.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :product_id %><br>
<%= f.number_field :product_id %>
</div>
<div class="field">
<%= f.label :cart_id %><br>
<%= f.number_field :cart_id %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
<h1>Editing Line Item</h1>
<%= render 'form' %>
<%= link_to 'Show', @line_item %> |
<%= link_to 'Back', line_items_path %>
<p id="notice"><%= notice %></p>
<h1>Listing Line Items</h1>
<table>
<thead>
<tr>
<th>Product</th>
<th>Cart</th>
<th colspan="3"></th>
</tr>
</thead>
<tbody>
<% @line_items.each do |line_item| %>
<tr>
<td><%= line_item.product_id %></td>
<td><%= line_item.cart_id %></td>
<td><%= link_to 'Show', line_item %></td>
<td><%= link_to 'Edit', edit_line_item_path(line_item) %></td>
<td><%= link_to 'Destroy', line_item, method: :delete, data: { confirm: 'Are you sure?' } %></td>
</tr>
<% end %>
</tbody>
</table>
<br>
<%= link_to 'New Line item', new_line_item_path %>
json.array!(@line_items) do |line_item|
json.extract! line_item, :id, :product_id, :cart_id
json.url line_item_url(line_item, format: :json)
end
<h1>New Line Item</h1>
<%= render 'form' %>
<%= link_to 'Back', line_items_path %>
<p id="notice"><%= notice %></p>
<p>
<strong>Product:</strong>
<%= @line_item.product_id %>
</p>
<p>
<strong>Cart:</strong>
<%= @line_item.cart_id %>
</p>
<%= link_to 'Edit', edit_line_item_path(@line_item) %> |
<%= link_to 'Back', line_items_path %>
json.extract! @line_item, :id, :product_id, :cart_id, :created_at, :updated_at
...@@ -4,4 +4,5 @@ ...@@ -4,4 +4,5 @@
</div> </div>
<h4><%= link_to product.name, product_path(product) %></h4> <h4><%= link_to product.name, product_path(product) %></h4>
<span class='price-col'>$<%= product.price %></span> <span class='price-col'>$<%= product.price %></span>
<%= button_to 'Add to Cart', line_items_path(product_id: product), { class: 'btn btn-default' } %>
</div> </div>
\ No newline at end of file
...@@ -17,6 +17,6 @@ ...@@ -17,6 +17,6 @@
<p><%= @product.description %></p> <p><%= @product.description %></p>
</div> </div>
<div class='row'> <div class='row'>
<%= link_to 'Buy', '#', class: 'btn btn-primary' %> <%= 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 :carts
namespace :admin do namespace :admin do
resources :products resources :products
end end
......
class CreateCarts < ActiveRecord::Migration
def change
create_table :carts do |t|
t.timestamps null: false
end
end
end
class CreateLineItems < ActiveRecord::Migration
def change
create_table :line_items do |t|
t.integer :product_id
t.integer :cart_id
t.timestamps null: false
end
end
end
class AddQuantityToLineItem < ActiveRecord::Migration
def change
add_column :line_items, :quantity, :integer, :default => 1
end
end
class CombineItemsInCart < ActiveRecord::Migration
def change
Cart.all.each do |cart|
sums = cart.line_items.group(:product_id).sum(:quantity)
sums.each do |product_id, quantity|
if quantity > 1
cart.line_items.where(product_id: product_id).delete_all
cart.line_items.create(product_id: product_id, quantity: quantity)
end
end
end
end
end
...@@ -11,7 +11,12 @@ ...@@ -11,7 +11,12 @@
# #
# 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: 20141111033549) do ActiveRecord::Schema.define(version: 20141112101735) do
create_table "carts", force: true do |t|
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "categories", force: true do |t| create_table "categories", force: true do |t|
t.string "name", limit: 255 t.string "name", limit: 255
...@@ -19,6 +24,14 @@ ActiveRecord::Schema.define(version: 20141111033549) do ...@@ -19,6 +24,14 @@ ActiveRecord::Schema.define(version: 20141111033549) do
t.datetime "updated_at" t.datetime "updated_at"
end end
create_table "line_items", force: true do |t|
t.integer "product_id", limit: 4
t.integer "cart_id", limit: 4
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.integer "quantity", limit: 4, default: 1
end
create_table "products", force: true do |t| create_table "products", force: true do |t|
t.string "name", limit: 255 t.string "name", limit: 255
t.decimal "price", precision: 10, scale: 2 t.decimal "price", precision: 10, scale: 2
......
require 'test_helper'
class CartsControllerTest < ActionController::TestCase
setup do
@cart = carts(:one)
end
test "should get index" do
get :index
assert_response :success
assert_not_nil assigns(:carts)
end
test "should get new" do
get :new
assert_response :success
end
test "should create cart" do
assert_difference('Cart.count') do
post :create, cart: { }
end
assert_redirected_to cart_path(assigns(:cart))
end
test "should show cart" do
get :show, id: @cart
assert_response :success
end
test "should get edit" do
get :edit, id: @cart
assert_response :success
end
test "should update cart" do
patch :update, id: @cart, cart: { }
assert_redirected_to cart_path(assigns(:cart))
end
test "should destroy cart" do
assert_difference('Cart.count', -1) do
delete :destroy, id: @cart
end
assert_redirected_to carts_path
end
end
require 'test_helper'
class LineItemsControllerTest < ActionController::TestCase
setup do
@line_item = line_items(:one)
end
test "should get index" do
get :index
assert_response :success
assert_not_nil assigns(:line_items)
end
test "should get new" do
get :new
assert_response :success
end
test "should create line_item" do
assert_difference('LineItem.count') do
post :create, line_item: { cart_id: @line_item.cart_id, product_id: @line_item.product_id }
end
assert_redirected_to line_item_path(assigns(:line_item))
end
test "should show line_item" do
get :show, id: @line_item
assert_response :success
end
test "should get edit" do
get :edit, id: @line_item
assert_response :success
end
test "should update line_item" do
patch :update, id: @line_item, line_item: { cart_id: @line_item.cart_id, product_id: @line_item.product_id }
assert_redirected_to line_item_path(assigns(:line_item))
end
test "should destroy line_item" do
assert_difference('LineItem.count', -1) do
delete :destroy, id: @line_item
end
assert_redirected_to line_items_path
end
end
# Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html
# This model initially had no columns defined. If you add columns to the
# model remove the '{}' from the fixture names and add the columns immediately
# below each fixture, per the syntax in the comments below
#
one: {}
# column: value
#
two: {}
# column: value
# Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html
one:
product_id: 1
cart_id: 1
two:
product_id: 1
cart_id: 1
require 'test_helper'
class CartTest < ActiveSupport::TestCase
# test "the truth" do
# assert true
# end
end
require 'test_helper'
class LineItemTest < 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