#6 Shortcut Blocks with Symbol to_proc
Mar 16, 2007 | 3 minutes | Active Support
It may have a goofy syntax, but the Symbol#to_proc feature Rails adds allows you to do simple blocks very quickly and easily.
下面代码find
方法中这种看起来奇怪的语法,一个&符号后面跟着一个名字,叫做to_proc。是Rails对Ruby的一点功能扩充。
ruby
class Project < ActiveRecord::Base has_many :tasks def self.all_names find(:all).collect(&:name) end end
我们通过Rails Console下的一个例子来解释。Rails script/console
命令启动Rails控制台。首先,获取所有的Project
。
terminal
Laa-Laa:todo eifion$ script/console Loading development environment (Rails 2.2.2) >> projects = Project.find(:all) => [#<Project id: 1, name: "Write another ASCIIcast", created_at: "2008-12-29 09:32:47", updated_at: "2008-12-29 09:32:47">, #<Project id: 2, name: "Go out walking", created_at: "2008-12-29 09:33:04", updated_at: "2008-12-29 09:33:04">]
结果中包含两个项目对象以列表格式返回,如果我们想得到这两个对象的名字应该怎么做呢?第一种方法就是使用collect
方法,在供回调的代码块中填写返回项目名称的逻辑。collect
方法的作用是遍历列表,并让每一个项目中的对象执行代码块中定义的逻辑操作并得到返回值,这样将返回一个基于原来列表的返回值列表。
terminal
>> projects.collect { |p| p.name } => ["Write another ASCIIcast", "Go out walking"]
to_proc允许你给一段需要传递给代码块的逻辑起一个名字,这样写在代码块中的逻辑就可以定义在其他地方,代码块中只需传入&逻辑名字
的参数了。就像下面的样子:
terminal
>> projects.collect {&:name} => ["Write another ASCIIcast", "Go out walking"]
当你需要链式调用的时候,这种格式的作用就更明显了。下面的代码是不是可读性更强了:
terminal
>> projects.collect(&:name).collect(&:upcase) => ["WRITE ANOTHER ASCIICAST", "GO OUT WALKING"]
当然了,不仅仅局限于collect
方法,所有代码块都可以使用to_proc。比如说可以为any
方法定义检查项目是否正常开展的to_proc,为all
方法可以定义保存的to_proc等等。
terminal
>> projects.all?(&:valid?) => true >> projects.any?(&:valid?) => true >> projects.each(&:save!) => [#<Project id: 1, name: "Write another ASCIIcast", created_at: "2008-12-29 09:32:47", updated_at: "2008-12-29 09:32:47">, #<Project id: 2, name: "Go out walking", created_at: "2008-12-29 09:33:04", updated_at: "2008-12-29 09:33:04">]
最开始可能觉得语法看起来怪怪的,但当你遇到需要使用链式调用时,它绝对是你的好帮手。