创建一个项目: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目录下的各自相应的辅助程序中提供的方法。