Selasa, 20 Desember 2016

Simple Shopping Cart




Kita Akan membuat satu fitur yang umum terdapat pada online shop yaitu shopping cart. user bisa menambahkan item yang dipilih ke keranjang pembelian

Berikut list gem file yang akan kita gunakan, Silahkan klik untuk mengunjungi halaman dokumentasi gem berikut
  1. devise
  2. twitter-bootstrap-rails
  3. slim-rails
  4. ancestry
  5. paperclip
  6. faker
  7. shopping_cart
Disini saya memakai OS ubuntu 14.04 dengan rails versi 4.2.4. Jadi pastikan dulu kalian memakai rails 4

Langkah pertama kita buat project baru
$ rails _4.2.4_ new testapp2 -d postgresql
Buka dan edit MyStore/Gemfile dan tambahkan gem yang kita butuhkan
gem 'devise'
gem "twitter-bootstrap-rails"
gem "slim-rails"
gem 'ancestry'
gem 'paperclip'
gem 'faker'
gem 'acts_as_shopping_cart', '~> 0.4.0'
$ cd MyStore
$ bundle install
Langkah selanjutnya kita akan melakukan generate settings devise, model, table dan column yang kita butuhkan
$ rails generate devise:install
$ rails generate devise user
$ rails g model category name:string description:text ancestry:string
$ rails generate paperclip category image
$ rails g model product name:string code:string weight:decimal price:decimal category:references
$ rails generate paperclip product image
$ rails  g model order number:string user:references status:string total_price_items:decimal total_price_delivery:decimal total_all_price:decimal receiver_name:string receiver_phone_number:string receiver_mobile_number:string receiver_state:string receiver_city:string receiver_address:text receiver_postal_code:string destination_code:string service_delivery:string
$ rails g model shopping_cart user:references order:references delivery_method:string
$ rails g model shopping_cart_items owner_id:integer owner_type:string quantity:integer item_id:integer item_type:string price_currency:string price_cents:decimal
Jangan lupa setting database.yml kalian dengan username dan password ketika instalasi Rails


$ rake db:create
$ rake db:migrate

Selanjutnya kita generate controller dan view yang kita butuhkan
$ rails g controller shopping index
$ rails generate bootstrap:install static
$ rails g bootstrap:layout application
Langkah berikutnya kita akan melakukan edit dan create beberapa file tolong diperhatikan file dan baris code jika kalian ingin melakukan copy dan paste

Mengatur halaman view dan controller yang akan kita gunakan edit file MyStore/config/route.rb
Rails.application.routes.draw do
  devise_for :users
  get 'home/index'
  get 'shopping/index'
  get 'shopping/cart_items'
  post 'shopping/create_order'
  post 'shopping/add_to_cart'
  root :to => "shopping#index"
end
Edit File MyStore/app/controllers/application_controller.rb
keterangan untuk method shopping cart yaitu untuk mengetahui apakah user sudah mempunyai shoppingcart atau belum bila tidak ada ada akan dibuatkan

class ApplicationController < ActionController::Base
  protect_from_forgery with: :exception
  before_filter :shopping_cart

  def shopping_cart
     if current_user.present?
        shopping_cart = ShoppingCart.where('order_id is null').where(user_id: current_user.id).try(:last)
        shopping_cart = shopping_cart.present? ? shopping_cart : ShoppingCart.create(user_id: current_user.id)
        @shopping_cart = shopping_cart
     end
  end
end
Edit File MyStore/app/controllers/shopping_controller.rb
Keterangan fungsi sesuai dengan namanya add_to_cart untuk menambahkan barang yang kita pilih ke keranjang belanja dan create_order untuk membuat pesanan
class ShoppingController < ApplicationController
 before_filter :authenticate_user!, unless: :devise_controller?, except: [:index]
 def index
  category_id = params[:category]
  unless category_id.present?
    @products = Product.all
  else
    @products = Product.where(:category_id => category_id)
  end
 end
 
 def add_to_cart
   quantity = params[:quantity].to_i
   product_id = params[:product]
   @product = Product.find(product_id)
   @shopping_cart.add(@product, @product.price, quantity)
   redirect_to  request.referer || "/"
   flash[:notice] = "#{@product.name} has been added to the Cart."
 end

 def create_order
  total_price_delivery = 0
  total_price_items = @shopping_cart.total_items
  total_all_price = total_price_delivery + total_price_items

  @order = Order.new
  @order.number = "#{current_user.id}-#{Time.now.to_i}"
  @order.user_id = current_user.id
  @order.total_price_items = total_price_items
  @order.total_price_delivery = total_price_delivery
  @order.total_all_price = total_all_price
  @order.save
  @shopping_cart.update(:order_id => @order.id)
  redirect_to root_path
  flash[:notice] = "Your Order has been created"
 end

 def cart_items
  render :template => 'shopping/cart_items'
 end
end

Bila ada dua application file di folder layout hapus yang berakhiran .erb karena kita akan memakai slim biar code html terlihat sedikit dan rapih. Disini kita akan memasang navbar menu dengan bootraps
Edit File MyStore/app/view/layout/application.html.slim
doctype html
html lang="en"
  head
    meta charset="utf-8"
    meta http-equiv="X-UA-Compatible" content="IE=Edge,chrome=1"
    meta name="viewport" content="width=device-width, initial-scale=1.0"
    title= content_for?(:title) ? yield(:title) : "MyStore"
    = csrf_meta_tags
    = stylesheet_link_tag "application", :media => "all"
    = favicon_link_tag 'apple-touch-icon-144x144-precomposed.png', :rel => 'apple-touch-icon-precomposed', :type => 'image/png', :sizes => '144x144'
    = favicon_link_tag 'apple-touch-icon-114x114-precomposed.png', :rel => 'apple-touch-icon-precomposed', :type => 'image/png', :sizes => '114x114'
    = favicon_link_tag 'apple-touch-icon-72x72-precomposed.png', :rel => 'apple-touch-icon-precomposed', :type => 'image/png', :sizes => '72x72'
    = favicon_link_tag 'apple-touch-icon-precomposed.png', :rel => 'apple-touch-icon-precomposed', :type => 'image/png'
    = favicon_link_tag 'favicon.ico', :rel => 'shortcut icon'
    = javascript_include_tag "application"
    /! Le HTML5 shim, for IE6-8 support of HTML elements
    /[if lt IE 9]
      = javascript_include_tag "//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.2/html5shiv.min.js"
  body
    .navbar.navbar-default.navbar-static-top
        .container
          button.navbar-toggle type="button" data-toggle="collapse" data-target=".navbar-responsive-collapse"
            span.icon-bar
            span.icon-bar
            span.icon-bar
          a.navbar-brand href="/"MyStore
          .navbar-collapse.collapse.navbar-responsive-collapse
            ul.nav.navbar-nav.navbar-right
              - if current_user
                li= link_to "Cart Item (#{@shopping_cart.cart_items.count})", '/shopping/cart_items'
                li= link_to current_user.email, '/'
                li= link_to "Logout", destroy_user_session_path, data: { method: :delete }
              - else
                li= link_to 'Login', '/users/sign_in'
    .container
      .row
        .col-lg-9
          = bootstrap_flash
          = yield
        .col-lg-3
          .well.sidebar-nav
            h3 Categories
            ul.nav.nav-list
              li= link_to 'All', "/shopping/index"
              - Category.all.each do |category|
                li= link_to category.name, "/shopping/index?category=#{category.id}"
      footer
        p &copy; Company 2016
Kita akan membuat function helper untuk menampilkan format uang 10000 menjadi Rp 10.000
Edit File Mystore/app/helpers/application_helper.rb
module ApplicationHelper
  def data_currency(data)
    number_to_currency(data, unit: 'Rp. ', :precision => 0)
  end
end

Edit File MyStore/app/view/shopping/index.html.slim
- @products.each do |product|
  .col-md-3.col-sm-6.hero-feature
    .thumbnail
      = image_tag product.image(:medium)
      .caption
        .title-voucher
          h4
            = "#{product.name.last(14).capitalize}.."
          = number_to_currency(product.price, unit: 'IDR ')
        .clearfix
      form.form-search action = "/shopping/add_to_cart" method="post"
        input name="authenticity_token" type="hidden" value=form_authenticity_token
        input name="product" type="hidden" value="#{product.id}"
        .input-group
          span.input-group-btn
            button.btn.btn-search type="submit"  Add to cart
          input.form-control name= "quantity" value="1" type="text"
Buat file File MyStore/app/view/shopping/cart_items.html.slim
- if @shopping_cart.cart_items.present?
  table.table
    thead
      tr
        th style="text-align:left" Product
        th style="width:100px" Kuantitas
        th Harga Satuan
        th Total Harga
    tbody
      - @shopping_cart.cart_items.each do |item|
        tr style="border-bottom:1px solid #ccc"
          td
            = item.product.name
          td
            input.form-control.quantity_change style="text-align: center;" name="kuantitas" placeholder="0" type="text" value = "#{item.quantity}" item = "#{item.id}"/
          td style="text-align:center"
            = data_currency(item.product.price)
          td
            div style="float:right"
              div id=("item_#{item.id}")
                = data_currency(item.subtotal)
- else
  center
    p No Item in Cart

- if @shopping_cart.cart_items.present?
  .footer_pembayaran
    h3 style="float:right;width: 176px;"
      div style="float:right"
        .total_items
          = data_currency(@shopping_cart.total_items)
    br clear="both"
  form.form-search action = "/shopping/create_order" method="post"
    input name="authenticity_token" type="hidden" value=form_authenticity_token
    button.btn-primary.pull-right type="submit"  Buy Now
Langkah selanjutnya  memasang relasi dan setting paperclip di model

Edit File MyStore/app/model/product.rb
class Product < ApplicationRecord
  belongs_to :category
  has_attached_file :image, styles: { medium: "300x300>", thumb: "66x66>" }, default_url: "/images/:style/missing.png"
  validates_attachment_content_type :image, :content_type => ["image/jpg", "image/jpeg", "image/png", "image/gif"]
end
Edit File MyStore/app/model/category.rb
class Category < ActiveRecord::Base
  has_attached_file :image, styles: { medium: "300x300>", thumb: "66x66>" }, default_url: "/images/:style/missing.png"
  validates_attachment_content_type :image, :content_type => ["image/jpg", "image/jpeg", "image/png", "image/gif"]
  has_ancestry
end
Edit File MyStore/app/model/shopping_cart.rb
class ShoppingCart < ActiveRecord::Base
  acts_as_shopping_cart
  belongs_to :user
  belongs_to :order

   def subtotals
    self.cart_items.map { |i| i.subtotal }
  end

  def total_items
   subtotals.sum
  end
end
Edit File MyStore/app/model/shopping_cart_item.rb
class ShoppingCartItem < ActiveRecord::Base
  acts_as_shopping_cart_item
  belongs_to :product,
             :class_name=>"Product",
             :foreign_key=>"item_id"
end
Langkah selanjutnya membuat dumy data biar data product dan category langsung ada tanpa harus kita create dulu. Maksud dari 10.times dan 12.times yaitu kita akan membuat product sebanyak 10 kali dan category sebanyak 12 kali

Edit 
file File MyStore/db/seed.rb. Kode dibawah untuk membuat dumy data 
# faker data table category
10.times do 
  category = Category.new
  category.name = Faker::Commerce.department
  category.description = Faker::Lorem.paragraph
  category.image = File.open(Dir.glob(File.join(Rails.root, 'sampleimages', '*')).sample)
  category.save
end

# faker data table category
12.times do 
  product = Product.new
  product.name = Faker::Commerce.product_name
  product.code = Faker::Number.hexadecimal(3)
  product.weight = Faker::Number.number(1)
  product.price = Faker::Number.decimal(6)
  product.image = File.open(Dir.glob(File.join(Rails.root, 'sampleimages', '*')).sample)
  product.category_id = Category.pluck(:id).sample
  product.save
end
Untuk membuat dummy image kita buat folder 'sampleimages' di dalam folder MyStore dan copy image yang kamu punya ke dalam folder tersebut

$ rake db:seed
$ rails s
Buka di browser localhost:3000 bila berjalan sempurna maka akan tampil seperti gambar berikut


Gambar halaman list product

Gambar Halaman login
Gambar Halaman cart item

Oke sampai sini selesai bila ada pertanyaan silahkan comment dibawah


Tidak ada komentar:

Posting Komentar