Rails学习笔记(5)第6、7、8章摘要
执行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方法,例:



ActiveRecord的方法属性:
。content_columns 得到所有字段。content_columns.name字段名
。日期在今天之前,按日期倒序排列。self表示它是一个类方法(静态方法)。
find(:all, :conditions => " date_available <= now() " , :order => " date_available desc " )
end
以下为链接,效果相当于以前的“ http://..../show.jsp?id=11”
<%= link_to ' Edit ' , :action => ' edit ' , :id => product %>< br />
<%= link_to ' Destroy ' , { :action => ' destroy ' , :id => product }, :confirm => " Are you sure? " %>
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,则控制器下所有网页都会使用此模板
< 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

< a href = " http://www

< a href = " http://www

< a href = " http://www

</ 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。




ruby script/generate model LineItem,创建一个LineItem的数据模型,附带还会创建相应的测试程序。
store_controller.rb:
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把序列化的类取出时,否则是无法知道对象类型的,除非声明一下。
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目录下的各自相应的辅助程序中提供的方法。