Chúng ta sẽ chỉnh sửa giao diện người dùng (View) với ứng dụng depot đã làm trong bài trước.
Tạo dữ liệu với seeds.rb
Trước tiên chúng ta sẽ cần đến một số dữ liệu mẫu để sử dụng. Nếu bạn còn nhớ thì trong bài trước chúng ta biết là Rails sẽ tạo sẵn một form để chúng ta thực hiện thêm bản ghi vào model rất dễ dàng. Tuy nhiên việc ngồi gõ từng dòng dữ liệu như thế rất chán và mệt mỏi, do đó Rails cung cấp cho chúng ta một cách tạo dữ liệu khác.
Ở trong thư mục db
có một file có tên là seeds.rb,
đây là file Rails dành cho chúng ta để ghi đoạn code tạo đối tượng từ model, và Rails sẽ đọc các dòng code đó rồi insert thành các bản ghi trong CSDL luôn. Ví dụ chúng ta mở file này ra rồi chèn vào đoạn code sau:
# This file should contain all the record creation needed to seed the database with its default values. # The data can then be loaded with the rake db:seed (or created alongside the db with db:setup). # # Examples: # # cities = City.create([{ name: 'Chicago' }, { name: 'Copenhagen' }]) # Mayor.create(name: 'Emanuel', city: cities.first) Product.delete_all Product.create(:title => 'Learn Web Development with Rails', :description => %{ Ruby on Rails Tutorial book and screencast series teach you how to develop and deploy real, industrial-strength web applications with Ruby on Rails. }, :image_url => 'rails_book.png', :price => 29.99) Product.create(:title => 'The Ruby Programming Language', :description => %{ The Ruby Programming Language is the authoritative guide to Ruby and provides comprehensive coverage of versions 1.8 and 1.9 of the language. }, :image_url => 'ruby_book.png', :price => 39.99)
Trong đoạn code trên chúng ta tạo 2 đối tượng Product.
Dòng đầu tiên chúng ta gọi phương thức delete_all,
phương thức này sẽ xóa toàn bộ bản ghi có trong CSDL, tiếp theo chúng ta gọi phương thức create
và đưa vào các tham số dữ liệu để tạo mới đối tượng. Có một lưu ý là trong thuộc tính description
chúng ta dùng cú pháp %{...}
, cú pháp này cho phép chúng ta ghi chuỗi trên nhiều dòng, thay vì truyền vào trong dấu nháy kép thì phải nối chuỗi.
Sau đó để thực hiện việc tạo các bản ghi này trong CSDL thì chúng ta mở command prompt lên rồi gõ lệnh rake db:seed
là được.
C:\Project\Rails\depot>rake db:seed
Bạn có thể chạy server rồi trỏ đến URL /products
hoặc dùng trình sqlite3 để kiểm tra nội dung trong CSDL đã được chèn vào hay chưa, tất nhiên là chẳng có gì đặc biệt cả.
Tùy chỉnh View
Trước tiên chúng ta tìm hiểu sơ qua về khái niệm Layout. Layout ở đây có nghĩa là một đoạn code được dựng sẵn để dùng chung cho toàn bộ website, các trang View khác trong website sẽ copy code trong layout vào code của chính nó rồi chèn thêm các đoạn code đặc trưng của nó vào. Vậy đoạn code layout dùng chung đó nằm ở đâu? câu trả lời la file application.html.erb
trong thư mục app/views/layouts,
file này được Rails tạo ra tự động và có nội dung như sau:
<!DOCTYPE html> <html> <head> <title>Depot</title> <%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track' => true %> <%= javascript_include_tag 'application', 'data-turbolinks-track' => true %> <%= csrf_meta_tags %> </head> <body> <%= yield %> </body> </html>
Chúng ta sẽ tìm hiểu về layout sau, ở đây chúng ta chỉ cần để ý các đoạn nằm trong thẻ <%= %>.
Các đoạn code nằm trong cặp thẻ này được gọi chung là template, chúng ta có thể gọi một số hàm, thực hiện một số câu lệnh đơn giản như if, vòng lặp… hoặc tham chiếu đến biến trong cặp thẻ này… và những gì nằm trong cặp thẻ này sẽ được trình biên dịch Rails dịch ra thành code HTML rồi chèn vào đó. Ở đây dòng:
<%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track' => true %>
có nghĩa là tạo các thẻ <link>
trỏ đến toàn bộ file CSS có trong thư mục app/assets/stylesheets,
bạn có thể mở thư mục này ra và thấy trong đó có sẵn một số file CSS do Rails tự tạo ra rồi, một số file có thể có đuôi .scss,
nhưng cũng không quan trọng mấy.
Tương tự, các file Javascript và các file ảnh sẽ được đặt vào trong thư mục app/assets/javascripts
và app/assets/images.
Bây giờ chúng ta tạo một file có tên depot.css
chứa nội dung như sau:
#product_list table tr td { padding: 5px; vertical-align: top; } #product_list .list_image { width: 60px; height: 70px; } #product_list .list_description { width: 60%; } #product_list .list_description dl { margin: 0; } #product_list .list_description dt { color: #244; font-weight: bold; font-size: larger; } #product_list .list_description dd { margin: 0; } #product_list .list_actions { font-size: x-small; text-align: right; padding-left: 1em; } #product_list .list_line_even { background: #e0f8f8; } #product_list .list_line_odd { background: #f8b0f8; } #store .entry { overflow: auto; margin-top: 1em; border-bottom: 1px dotted #77d; } #store .title { font-size: 120%; font-family: sans-serif; } #store .entry img { width: 80px; margin-right: 5px; margin-bottom: 5px; float: left; } #store .entry h3 { margin-top: 0; margin-bottom: 2px; color: #227; } #store .entry p { margin-top: 0.5em; margin-bottom: 0.8em; } #store .entry .price_line { clear: both; margin-bottom: 0.5em; } #store .entry .add_to_cart { position: relative; } #store .entry .price { color: #44a; font-weight: bold; margin-right: 2em; }
Chúng ta định nghĩa vài class CSS đơn giản để hiển thị trang /products
theo giao diện mới một tí. Và tất nhiên file này sẽ được file layout tham chiếu tới như đã nói ở trên.
Tiếp theo chúng ta sửa lại file index.html.erb
trong thư mục app/views/products
như sau:
<div id="product_list"> <h1>Products</h1> <table> <% @products.each do |product| %> <tr class="<%= cycle('list_line_odd', 'list_line_even') %>"> <td> <%= image_tag(product.image_url, :class => 'list_image') %> </td> <td class="list_description"> <dl> <dt><%= product.title %></dt> <dd><%= truncate(strip_tags(product.description), :length => 80) %></dd> </dl> </td> <td class="list_actions"> <%= link_to 'Show', product %><br/> <%= link_to 'Edit', edit_product_path(product) %><br/> <%= link_to 'Destroy', product, data: { confirm: 'Are you sure?' }, :method => :delete %> </td> </tr> <% end %> </table> </div> <br /> <%= link_to 'New product', new_product_path %>
Có một số điểm lưu ý trong đoạn code trên như sau:
- Hàm
cycle()
có tác dụng duyệt qua lần lượt từng phần tử trong danh sách, khi đến hết danh sách thì lại quay về phần tử đầu tiên, trong ví dụ trên thìclass
của thẻtr
đầu tiên sẽ làlist_line_odd
hoặclist_line_even
tùy vào từng lần lặp. - Hàm
truncate()
có tác dụng lấy một lượng kí tự nhất định, ở đây chúng ta lấy 80 kí tự, ngoài ra chúng ta còn dùng hàmstrip_tags()
để loại bỏ các thẻ HTML trong chuỗi cho trước. - Các dòng
link_to <tên phương thức>
chẳng hạn như
link_to 'Destroy'
có nghĩa là gọi đến phương thứcdestroy
trong file controller, tức là fileapp/controllers/products_controller.rb,
ngoài ra theo sau chúng ta còn có thể truyền vào các tham số, ví dụ nhưdata: { confirm: 'Are you sure?'}
tức là truyền vào đối tượngdata
có thuộc tínhconfirm
có giá trị là chuỗi"Are you sure?"
(dưới dạng JSON). Dòng này sẽ được Rails dịch thành thuộc tínhdata-confirm
trong thẻ<a>
, nếu bạn rành HTML5 thì bạn sẽ biết là thuộc tính này sẽ tạo một hộp thoại để xác nhận.
Bây giờ bạn có thể chạy server và trỏ đến localhost:3000/products
để xem giao diện mới.