子在川上曰

  逝者如斯夫不舍昼夜
随笔 - 71, 文章 - 0, 评论 - 915, 引用 - 0
数据加载中……

Rails学习笔记(5)第6、7、8章摘要

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

 

posted on 2007-04-10 09:47 陈刚 阅读(1666) 评论(1)  编辑  收藏 所属分类: Rails&Ruby

评论

# re: Rails学习笔记(5)第6、7、8章摘要  回复  更多评论   

ruby script/generate scaffold Product Admin
貌似 在rails 2.0中,不支持这种方法了吧 貌似不能指定建立控制器.

现在的建 scaffold的方法
ruby script/generate scaffold Product title:string .....

不知道我理解的对否,望指正
2008-01-18 15:08 | 就这调调

只有注册用户登录后才能发表评论。


网站导航: