r1 - 01 Dec 2007 - 09:54:31 - ThanapolWisuttikulYou are here: SETEC Wiki >  Knowledge Web  > WebTechnologyCategory > RubyOnRails > ECommerceWebsiteLab04 > EcommerceWebsiteLab04_1

E-commerce Website Lab04

การสร้างตะกร้าใส่สินค้า (Cart Creation)

A. แผนผังการสร้าง

การทำงานของ E-commerce web application นี้ จะต้องมีการ add สินค้าลงตะกร้า (Shopping cart) ดังนั้นลูกค้าที่ซื้อทุกคนจะต้องมีสินค้าที่ได้เลือกไว้ในตะกร้า เตรียมที่จะจ่ายเงิน (ในส่วนของการ Checkout) ดังนั้น application ของเราต้องเก็บ track ของสินค้าทุกอย่างที่ลูกค้าได้เลือกลงตะกร้า โดยใช้ sessions


modelCart.png

1. Run Instant Rails
2. เพิ่มตารางในฐานข้อมูล  
  2.1 สร้างตาราง session
  2.2 สร้างตาราง line_item.rb
  2.3 สร้าง models LineItem 
  2.4 แก้ไข models ชื่อ line_item.rb
3. นำสินค้าใส่ตะกร้า
  3.1 แก้ไข store_controller.rb , สร้างเมธอด add_to_cart() display_cart() และ  find_cart()
  3.2 สร้าง models ชื่อ cart.rb
  3.3 แก้ไข models ชื่อ line_item.rb 
  3.4 แก้ไข controllers ชื่อ application.rb (controller)
4. แสดงสินค้าในตะกร้า
  4.1  สร้าง views ชื่อ display_cart.rhtml
5. ปรับปรุงหน้าจอ แสดงสินค้าในตะกร้า
6. ดัก Error 
  6.1 แก้ไข store_controller.rb ,แก้ไขเมธอด add_to_cart() 
  6.2 แก้ไข layouts ชื่อ store.rhtml
  6.3 แก้ไข store_controller.rb
7. ลบสินค้าออกจากตะกร้า
  7.1 แก้ไข store_controller.rb, สร้างเมธอด emtpy_cart()
  7.2 แก้ไข models ชื่อ cart.rb


1.จัดการเรื่อง Session

1.1 สร้างตาราง session ในฐานข้อมูล


> cd ecommere
ecommerce> rake db:sessions:create

CREATE TABLE `sessions` (
  `id` int(11) NOT NULL auto_increment,
  `session_id` varchar(255) collate utf8_unicode_ci default NULL,
  `data` text collate utf8_unicode_ci,
  `updated_at` datetime default NULL,
  PRIMARY KEY  (`id`)
)CHARACTER SET 'utf8' COLLATE 'utf8_general_ci';

1.2 แก้ไขไฟล์ config

การปรับแก้ไขนี้ จะสั่งในเก็บ session ที่ฐานข้อมูล โดยเข้าไปแก้ไขที่ environment.rb ดังนี้

(/config/environments/environment.rb)

# Use the database for sessions instead of the file system
# (create the session table with 'rake db:sessions:create')
config.action_controller.session_store = :active_record_store

หลังจากนั้นให้ restart application ใหม่อีกครั้ง หลังจากนั้นจะมีการเก็บ session ลงในฐานข้อมูล

1.3 Cart และ Session

private
  def find_cart
        @cart = (session[:cart] ||= Cart.new)            
        # if there's no cart in the session add a new one
  end

เขียนฟังก์ชันที่ /app/controllers/store_controller.rb

note : ||= เป็นการระบุเงื่อนไขว่าถ้ามี session[:cart] แล้วก็ให้รีเทริ์นค่าให้ @cart เลย แต่ถ้า ยังไม่มีให้สร้างตัวแปรนี้ขึ้นมา

2. สร้างตะกร้าสินค้า

2.1 ตะกร้าสินค้า (สร้าง model)

สร้างไฟล์ cart.rb (app/models/cart.rb)

class Cart 
  attr_reader :items
  def initialize
    @items = []
  end
  
  def add_product(product)
   @items << product
  end

end

2.2 เพิ่มปุ่ม สำหรับซื้อสินค้า

เพิ่มบรรทัดข้างล่างนี้ เพื่อให้มีปุ่มเพิ่มสินค้าที่ สินค้าแต่ละอัน ที่ไฟล์ index.rhtml (app/views/store/index.rhtml)


<%= button_to "Add to Cart" , :action => :add_to_cart, :id => product %>


addButton.png

2.3 สร้างฟังก์ชั่นการเลือกสินค้าใส่ตะกร้า (ใน controller)

แก้ไขไฟล์ store_controller.rb (/app/views/store/store_controller.rb) เพิ่มเมธอด add_to_cart

def add_to_cart
   @cart = find_cart
   product = Product.find(params[:id])
   @cart.add_product(product)
end

ถ้าเรา click ที่ปุ่ม add to cart ดูจะพบว่าเกิด Error เนื่องจากเรายังไม่ได้สร้าง template การแสดงผลที่ view


temMissing.png

2.4 สร้างหน้า template การแสดงผล (ใน view)

สร้างไฟล์ใหม่ชื่อ add_to_cart.rhtml ที่ /ecommerce/app/views/add_to_cart.rhtml

<h1>Your Pragmatic Cart</h1>
<ul>
<% for item in @cart.items %>
<li><%= h(item.title) %></li>
<% end %>
</ul>


templateAddtoCart.png

3. สร้างตะกร้าสินค้า (Advance)

จากการแสดงผลด้านบน ยังให้ข้อมูลไม่เพียงพอ ดังนั้นเราต้องเก็บข้อมูลการเลือกสินค้า ซึ่งก็คือ จำนวน นอกจากนี้ก็ควรนำ title และ price ของสินค้าออกมาแสดงผลด้วย

ดังนั้นเราจะสร้างเมธอดเพื่อมาเก็บข้อมูลดังกล่าว ซึ่งการทำงานจะต้องติดต่อกับฐานข้อมูล จึงสร้างที่ models

3.1 สร้าง model เพื่อเก็บข้อมูลสินค้าที่ถูกเลือก

สร้างไฟล์ใหม่ชื่อ cart_item.rb ที่ /ecommerce/app/models/cart_item.rb

class CartItem
  
  attr_reader :product, :quantity
  
  def initialize(product)
    @product = product
    @quantity = 1
  end
  
  def increment_quantity
    @quantity += 1
  end
  
  def title
    @product.title
  end
  
  def price
    @product.price * @quantity
  end
end

3.2 แก้ไข Model (cart.rb)ที่เมธอด add_product(product)

แก้ไขไฟล์ cart.rb (/app/models/cart.rb) แก้ไขเมธอด add_product(product)

 def add_product(product)  
    current_item = @items.find {|item| item.product == product}
    if current_item
      current_item.increment_quantity
    else
      @items << CartItem.new(product)
    end
 end

3.3 แก้ไข Views add_to_cart

แก้ไขไฟล์่ชื่อ add_to_cart.rhtml ที่ /ecommerce/app/views/add_to_cart.rhtml

เพื่อแสดงข้อมูลที่ต้องการ


<h1>Your Pragmatic Cart</h1>
<ul>
<% for cart_item in @cart.items %>
<li><%= cart_item.quantity %> &times; <%= h(cart_item.title) %></li>
<% end %>
</ul>

พอไปที่ web browser จะพบ Error ดังภาพข้างล่าง

เนื่องจากตอนแรกที่เรา เพิ่มสินค้านั้นยังไม่มีการเก็บข้อมูลที่เราต้องการให้แสดงผล


NoMethod2.png

ดังนั้น เราต้องเคลียร์ข้อมูลเดิมออกก่อนดังนี้ โดยไปพิมพ์คำสั่งนี้ที่ "Ruby Console Window"

ecommerce>  rake db:sessions:clear

Restart Web Application


dbSessionClear.png


11111.png

4. Handling Errors

4.1 แสดงผล Error (Flash)

ที่ผ่านมาจะเห็นว่า URL ของ web browser มีการส่งค่าพารามิเตอร์(id) ของสินค้าไปให้แต่ละ action ทำให้ผู้ใช้อาจพิมพ์ ทาง URL ได้ แต่หากไม่มี id ของสินค้านั้นๆ ก็จะทำให้โปนแกรม error ได้ ดังภาพ

  • เช่นถ้าพิมพ์ http://127.0.0.1:3000/store/add_to_cart/pen
  • เรียกไปที่ action : add_to_cart , controller : store
  • ส่ง id = pen (อะไรก็ได้ที่ไม่มีจริง)


handingError2.png

  • จะเห็นว่ามี Error เกิดขึ้น ซึ่งนั่นก็หมายถึงว่าโปรแกรมผิดพลาด ผู้ใช้อาจไม่รู้ว่าต้องทำอย่างไร ดังนั้นจึงต้องมีการดัก Error ดังกล่าว ซึ่ง ในที่นี้จะใช้ Flash
  • Flash จะเป็นที่เก็บข้อความที่เกิดขึ้นระหว่างการทำงาน
  • และจะถูกลบโดยอัตโนมัติ เมื่อมีการทำงานในกระบวนการถัดไป

  • จาก error ด้านบนเราสามารถป้องกันการเข้าถึง action : add_to_cart() ทางการพิมพ์ที่ browser ได้
  • โดยแก้ไขไฟล์ store_controller.rb ที่ action : add_to_cart() ใน app/controller/store_controller.rb ดังนี้

def add_to_cart
   begin
      product = Product.find(params[:id])
   rescue ActiveRecord::RecordNotFound
      logger.error("Attempt to access invalid product #{params[:id]}" )
      flash[:notice] = "Invalid product"
      redirect_to :action => :index
   else
      @cart = find_cart
      @cart.add_product(product)
  end
end


addToCartRescue.png

  • ซึ่งถ้าพิมพ์ URL : http://127.0.0.1:3000/store/add_to_cart/pen
  • จะ link ไปหน้าการแสดงรายการสินค้า (index)
  • แต่ flash[:notice] ไม่มีการแสดง error ออกมา เนื่องจากยังไม่ได้สร้าง display
  • เราต้องเขียน display ใน layout โดยมีเงื่อนไขว่า ถ้ามีข้อความใน flash[:notice] ก็ให้แสดงออกมา

แก้ไขในไฟล์ store.rhtml ใน path : app/views/layouts/store.rhtml และ เพิ่มข้อความนี้ลงไปใน main

<% if @flash[:notice] -%>
     <div id="notice"><%= @flash[:notice] %></div>
<% end -%>


addFlash.png


addPen2.png

4.2 ปรับรูปแบบของการแสดง Error (Flash)

เราสามารถปรับรูปแบบการแสดง error นี้ได้ที่ style sheet (catalog.css) ได้ที่นี่ /public/stylesheet/

#notice {
  border: 2px solid red;
  padding: 1em;
  margin-bottom: 2em;
  background-color: #FFD7D7;
  font: bold smaller tahoma;
}

5. ยกเลิกการเลือกสินค้าในตะกร้า (Empty cart)

5.1 เพิ่มปุ่ม สำหรับ "ยกเลิกรายการสินค้า"

เราจะเพิ่มปุ่มนี้ ในส่วนของการแสดงผล (aad_to_cart.rhtml) ที่บรรทัดล่างสุด จะเห็นว่ามีการเรียกทำงานไปที่ฟังก์ชั้น empty_cart


<%= button_to "Empty cart" , :action => :empty_cart %>


emptyCartButton.png

5.2 สร้างฟังก์ชันการลบรายการสินค้า

เมื่อกดปุ่ม empty cart แล้วต้องมาทำงานที่ฟังก์ชั้นด้านล่าง เราจะสร้างในไฟล์ store_controller.rb

def empty_cart
   session[:cart] = nil
   flash[:notice] = "Your cart is currently empty"
   redirect_to :action => :index
end


emptyCartButton2.png

5.3 สร้างฟังก์ชัน Redirected

ฟังก์ชัน redirect_to_index เป็นฟังก์ชั่นที่จะทำหน้าที่ เรียกไปยังไฟล์ index (หน้าแรกของระบบ) เนื่องจาก เราต้องมีการเรียกใช้การทำงานนี้บ่อย เพื่อความง่ายเราจะสร้างฟังก์ชั่นนี้ขึ้นมาใหม่ เพิ่มฟังก์ชั่นนี้ที่ store_controller.rb

private
  def redirect_to_index(msg = nil)
    flash[:notice] = msg if msg
    redirect_to :action => :index
  end

แก้ไข ฟังก์ชั่น empty_cart() และ add_to_cart() ที่มีการเรียกใช้ redirect to index ดังนี้

ไฟล์ store_controller.rb ฟังก์ชั่น empty_cart()

redirect_to_index("Your cart is currently empty" )

def empty_cart
   session[:cart] = nil
   flash[:notice] = "Your cart is currently empty"
   #redirect_to :action => :index
   redirect_to_index("Your cart is currently empty" )
end

ไฟล์ี่ store_controller.rb ฟังก์ชั่น add_to_cart()

redirect_to_index("Invalid product" )

def add_to_cart
   begin
      product = Product.find(params[:id])
   rescue ActiveRecord::RecordNotFound
      logger.error("Attempt to access invalid product #{params[:id]}" )
      flash[:notice] = "Invalid product"
      #redirect_to :action => :index
      redirect_to_index("Invalid product" )
   else
      @cart = find_cart
      @cart.add_product(product)
  end
end

6. แสดงราคาสินค้าที่ต้องชำระ

5.1 แสดงราคาสินค้าทั้งหมด

แก้ไขที่ไฟล์ี่ cart.rb โดยเพิ่มฟังก์ชัน total_price() และ_total_items_

  def total_price
      @items.sum { |item| item.price }
  end
  
  def total_items
      @items.sum { |item| item.quantity }
  end

แก้ไขที่ไฟล์ี่ add_to_cart.rhtml

<div class="cart-title" >Your Cart</div>
<table>
    <% for cart_item in @cart.items %>
        <tr>
            <td><%= cart_item.quantity %>&times;</td>
            <td><%= h(cart_item.title) %></td>
            <td class="item-price" ><%= number_to_currency(cart_item.price) %></td>
        </tr>
    <% end %>
    <tr class="total-line" >
        <td colspan="2" >Total</td>
        <td class="total-cell" ><%= number_to_currency(@cart.total_price) %></td>
    </tr>
</table>
<%= button_to "Empty cart" , :action => :empty_cart %>


showTotal.png

7. เำพิ่ม link ไปยังหน้าแคตาล็อก

แก้ไขที่ไฟล์ี่ add_to_cart.rhtml


<%= link_to '[[Back To Catalog]]', :action => 'index' %><br/>


BackToCatalog.png


Edit | Attach | Printable | Raw View | Backlinks: Web, All Webs | History: r1 | More topic actions
 
Powered by SETEC Wiki
Copyright ©2012 by National Electronics and Computer Technology Center, NECTEC.
Ideas, requests, problems regarding SETEC Wiki? Send feedback