E-commerce Website Lab04
การสร้างตะกร้าใส่สินค้า (Cart Creation)
A. แผนผังการสร้าง
การทำงานของ E-commerce web application นี้ จะต้องมีการ add สินค้าลงตะกร้า (Shopping cart) ดังนั้นลูกค้าที่ซื้อทุกคนจะต้องมีสินค้าที่ได้เลือกไว้ในตะกร้า เตรียมที่จะจ่ายเงิน (ในส่วนของการ Checkout)
ดังนั้น application ของเราต้องเก็บ track ของสินค้าทุกอย่างที่ลูกค้าได้เลือกลงตะกร้า โดยใช้ sessions
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

:
||= เป็นการระบุเงื่อนไขว่าถ้ามี 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 %>
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
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>
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 %> × <%= h(cart_item.title) %></li>
<% end %>
</ul>
พอไปที่ web browser จะพบ Error ดังภาพข้างล่าง
เนื่องจากตอนแรกที่เรา เพิ่มสินค้านั้นยังไม่มีการเก็บข้อมูลที่เราต้องการให้แสดงผล
ดังนั้น เราต้องเคลียร์ข้อมูลเดิมออกก่อนดังนี้ โดยไปพิมพ์คำสั่งนี้ที่ "Ruby Console Window"
ecommerce> rake db:sessions:clear
Restart Web Application
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 (อะไรก็ได้ที่ไม่มีจริง)
- จะเห็นว่ามี 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
- ซึ่งถ้าพิมพ์ 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 -%>
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 %>
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
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 %>×</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 %>
7. เำพิ่ม link ไปยังหน้าแคตาล็อก
แก้ไขที่ไฟล์ี่
add_to_cart.rhtml
<%= link_to '[[Back To Catalog]]', :action => 'index' %><br/>