創建一個項目:rails depot
執行SQL腳本:mysql depot_development < db/create.sql
創建三個庫,分別用于開發、測試、生產:depot_development、depot_test、depot_production。
每個表都應該帶一個和業務無關的ID字段。
在rails配置數據庫的連接:config\database.yml。密碼之前冒號之后要間隔一個空格。
ruby script/generate scaffold Product Admin,針對Product表產生一整套的網頁程序(增刪改),Admin是控制器名
ruby script/generate controller Store index 創建一個名為Store的控制器,并含有一個index() Action方法。
啟動WEB服務:ruby script/server。(
http://localhost:3000/admin )
模型類:
。validates_presence_of :title, :desc, :image_url 必須不為空
。validates_numericality_of :price 必須是數字
。validates_uniqueness_of :title 必須唯一
。validates_format_of :image_url,
:with => %r{^http:.+\.(gif|jpg|png)$}i,
:message => "must be a URL for a GIF, JPG, or PNG image" 文件名必須是圖片文件的擴展名
。模型保存到數據庫之前會調用validate方法,例:
def validate
errors.add(:price, "should be positive") unless price.nil? || price > 0.0
end
ActiveRecord的方法屬性:
。content_columns 得到所有字段。content_columns.name字段名
。日期在今天之前,按日期倒序排列。self表示它是一個類方法(靜態方法)。
def self.salable_items
find(:all, :conditions => "date_available <= now()", :order => "date_available desc")
end
以下為鏈接,效果相當于以前的“
http://..../show.jsp?id=11”
<%= link_to 'Show', :action => 'show', :id => product %><br/>
<%= link_to 'Edit', :action => 'edit', :id => product %><br/>
<%= link_to 'Destroy', { :action => 'destroy', :id => product }, :confirm => "Are you sure?" %>
<%= if @product_pages.current.previous
link_to("Previous page", { :page => @product_pages.current.previous })
end
%>
<%= if @product_pages.current.next
link_to("Next page", { :page => @product_pages.current.next })
end
%>
truncate(product.desciption, 80) 顯示產品描述字段的摘要(80個字符)
product.date_available.strftime("%y-%m-%d") 日期字段的格式化顯示
sprintf("%0.2f", product.price) 數值的格式化顯示, number_to_currency方法也有類似功能
public/stylesheets 目錄保存了網頁所用的CSS式樣表。用ruby script/generate scaffold ....生成框架代碼的網頁自動使用scaffold.css
布局模板
。app/views/layouts目錄中創建一個與控制器同名的模板文件store.rhtml,則控制器下所有網頁都會使用此模板
<html>
<head>
<title>Pragprog Books Online Store</title>
<%= stylesheet_link_tag "scaffold", "depot", :media => "all" %>
</head>
<body>
<div id="banner">
<img src="/images/logo.png"/>
<%= @page_title || "Pragmatic Bookshelf" %>
</div>
<div id="columns">
<div id="side">
<a href="http://www
.">Home</a><br />
<a href="http://www
./faq">Questions</a><br />
<a href="http://www
./news">News</a><br />
<a href="http://www
./contact">Contact</a><br />
</div>
<div id="main">
<% if @flash[:notice] -%>
<div id="notice"><%= @flash[:notice] %></div>
<% end -%>
<%= @content_for_layout %>
</div>
</div>
</body>
</html>
。<%= stylesheet_link_tag "scaffold", "depot", :media => "all" %>生成指向scaffold.css、depot.css兩個式樣表的<link>標簽
。@page_title 各個頁面標題變量
。@flash[:notice] 提示性的信息(key=notice),這是一個公共變量。
。<%= @content_for_layout %> 位置嵌入顯示控制器內名網頁。由于其他網頁變成了模板的一部份,所以其<html>等標簽應該去掉。
store_controller.rb ,當從session里取出某購物車不存在,則新建一個,并存入session。最后把此購物車賦給變量cart。
def find_cart
@cart = (session[:cart] ||= Cart.new)
end
ruby script/generate model LineItem,創建一個LineItem的數據模型,附帶還會創建相應的測試程序。
store_controller.rb:
def add_to_cart
product = Product.find(params[:id])
@cart.add_product(product)
redirect_to(:action => 'display_cart')
rescue
logger.error("Attempt to access invalid product #{params[:id]}")
redirect_to_index('Invalid product')
end
。params是URL的參數數組
。redirect_to轉向語句
。rescue 異常,相當于Java的Exception
。redirect_to_index是application.rb中的一個方法,這個文件里的方法是各控制器公開的。
。logger是rails內置的變量。
class Cart
attr_reader :items
attr_reader :total_price
def initialize
empty!
end
def add_product(product)
item = @items.find {|i| i.product_id == product.id}
if item
item.quantity += 1
else
item = LineItem.for_product(product)
class Cart
# An array of LineItem objects
attr_reader :items
# The total price of everything added to this cart
attr_reader :total_price
# Create a new shopping cart. Delegates this work to #empty!
def initialize
empty!
end
# Add a product to our list of items. If an item already
# exists for that product, increase the quantity
# for that item rather than adding a new item.
def add_product(product)
item = @items.find {|i| i.product_id == product.id}
if item
item.quantity += 1
else
item = LineItem.for_product(product)
@items << item
end
@total_price += product.price
end
# Empty the cart by resetting the list of items
# and zeroing the current total price.
def empty!
@items = []
@total_price = 0.0
end
end
end
@total_price += product.price
end
def empty!
@items = []
@total_price = 0.0
end
end
。由于Cart沒有對應的數據表,它只是一個普通的數據類,因此要定義相應的屬性。
。@items << item 把對象item加入到@items數組
。@items=[] 空數組
如果出現SessionRestoreError錯誤,則檢查application.rb是否做了如下的模型聲明。因為對于動態語句,session把序列化的類取出時,否則是無法知道對象類型的,除非聲明一下。
class ApplicationController < ActionController::Base
model :cart
model :line_item
end
<% ... -%> -%>相當于一個換行符
@items.find(|i| i.product_id == product.id) |i|的作用應該相當于@items數組中的一個元素(書上沒有提到,要查一下ruby語法)。
if @items.empty? 判斷數組是否為空數組
flash[:notice] flash可以在同一個Session的下一個請求中使用,隨后這些內容就會被自動刪除(下一個的下一個就被清空了??)。
實例變量是代替不了flash的,因為IE無狀態的特性,在下一個請求中,上一個請求的實例變量已失效。
當異常沒有被任何程序捕捉,最后總會轉到ApplicationController的rescue_action_in_public()方法
各視圖可以使用appp/helpers目錄下的各自相應的輔助程序中提供的方法。