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

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

 

你可能感兴趣的:(Rails学习笔记(5)第6、7、8章摘要)