Ruby for Rails 最佳实践Ⅲ

第三章 了解 Ruby 前提下的 Rails 开发

一、YAML 和实际为编程的配置

YAML (按 UNIX 平台的传统,最初代表 Yet Another Markup Language,现在却代表 YAML Ain’t Markup Language)可以说是一个标记语言,也可以说是一个串行化格式,取决于你看问题的角度。下面是一个简单的例子:一个嵌套的数组结构转变成一个 YAML 表示,然后再由它恢复成一个数组:

require 'yaml'

array = [1, 2, 3, [4, "five", :six]]

puts "Original array:"

puts array.inspect

yarray = array.to_yaml

puts "YAML representation of array: "

puts yarray

thawed = YAML.load(yarray)

puts "Array re-loaded from YAML string: "

p thawed

(此例中,inspect 方法为对象产生一个详细的字符串表示;还有 p 方法,等价于 puts)。

运行这段脚本的输出如下:

Original array:

[1, 2, 3, [4, "five", :six]]

YAML representation of array:

---

- 1

- 2

- 3

- - 4

  - five

  - :six

Array re-loaded from YAML string:

[1, 2, 3, [4, "five", :six]]

 

Rails 在几种上下文中使用 YAML,在 database.yml 中会看到如下的块:

development:

  adapter: mysql

  database: r4rmusic1_development

  username: r4r

  password: railzrulez

  socket: /tmp/mysql.sock

 

将这些行放到一个文件(如sample.yml)中,然后运行下面命令:

F:\ruby_project>ruby -ryaml -e 'p YAML.load(File.read("sample.rb"))'

{"development" => {"socket"=>"/tmp/mysql.sock",

                   "username"=>"r4r",

                   "adapter"=>"mysql",

                   "password"=>"railzrulez",

                   "database"=>"r4rmusic1_development"

                   }

}

 

二、给控制器增加功能

通过点击合适的列标题,可以让列表以不同的方式排序(按标题,按作者,按状态):

def all

  @order = params[:order] || "number"

  sort_proc = case @order

    when "author"  then lambda {|r| [r.user.name.downcase, r.number] }

    when "status",

         "title"   then lambda {|r| [r.send(@order).downcase, r.number]}

    when "number"  then lambda {|r| -r.number }

  end

  @rcrs = Rcr.find(:all).sort_by &sort_proc

end

 

变量@order(一个实例变量)设置为CGI变量order的值;如果该CGI变量的值没有设置,则它的默认值是字符串"number"。然后,变量sort_proc(排序过程)被设置为三个可能的lambda表达式(匿名函数)中的一个。选择哪一个lambda表达式取决于@order的值,这个选择是通过一个case语句来执行的。

 

一旦选定了正确的lambda表达式,所有现存的RCR将根据该lambda表达式的逻辑排序,这个排序需使用ActiveRecord的find方法来获取所有的RCR,以及根据sort_proc中保存的lambda表达式来使用Ruby的sort_by方法过滤这个列表。

 

如果了解Ruby,则该方法很容易编写。但是一定要了解Ruby!确切地说,需要了解下面这些内容:

case语句;

lambda关键字,用它生成一个匿名函数;

send方法(请注意status和title是怎样一起处理的);

sort_by方法,需要给它传递一个lambda表达式。

 

三、部署 Rails 的辅助文件

Rails 对每一个控制器都会自动产生一个辅助文件,可以编写任意多的 Ruby 方法。位于 app\helpers 下。

 

下面是一个从RCRchive列表排序代码中提取的例子。在RCR的每一个视图中的每一个列标题,都超链接到rcr/all动作。这些链接只在一个方面有区别:order参数的值(“author”、“title”、“number”或“Status”)。这意味着这四个链接使用几乎完全相同的代码。为减少重复,可用一个辅助方法自动产生合适的链接。你所需要做的仅仅是传递给它一个order参数。

 

该辅助方法定义在文件rcr_helper.rb中,如下所示:

def link_to_order(order)

  link_to(order.capitalize,

          :controller => "rcr",

          :action     => "all",

          :params     => { "order" => order })

end

 

在视图(app/views/rcr/all.rhtml)中,下面四行产生表的列标题:

<th class="rcr"><%= link_to_order("number") %></th>

<th class="rcr"><%= link_to_order("title") %></th>

<th class="rcr"><%= link_to_order("status") %></th>

<th class="rcr"><%= link_to_order("author") %></th>

 

四、给模型增加功能

1. 实现预定义的回调方法

如果在一个ActiveRecord模型文件中编写一个名为before_create的方法,该方法会在该模型的实例的数据库记录产生之前被执行。

如果description字段有默认的字符串值,那应该更好。如果在数据库记录首次产生的时候,该edition不存在描述信息,让我们给它一个默认值"standard"。

def before_create

  self.description = "standard" unless description

end

 

2. 自由形式的编程的模型改进

假设在一个视图模板中,变量@customer包含一个客户对象,你可以像下面这样显示这个人的名字:

<p>Hello, <%= @customer.title + " " + @customer.first_name + " " +

              @customer.middle_initial + ". " +

              @customer.last_name" %></p>

 

下面让 customer 对象自己产生该名字的友好板本:

class Customer < ActiveRecord::Base

  def nice_name

    title + " " + first_name + " " +

      (if middle_initial then middle_initial + ". " else "" end) +

      last_name

  end

end

 

下面可以在视图中直接调用 @customer 中该实例的方法:

<p>Good morning, <%= @customer.nice_name %>.</p>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值