下面代碼find
方法中這種看起來奇怪的語法,一個&符號後面跟着一個名字,叫做to_proc。是Rails對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
。
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
方法的作用是遍歷列表,並讓每一個項目中的對象執行代碼塊中定義的邏輯操作並得到返回值,這樣將返回一個基於原來列表的返回值列表。
>> projects.collect { |p| p.name }
=> ["Write another ASCIIcast", "Go out walking"]
to_proc允許你給一段需要傳遞給代碼塊的邏輯起一個名字,這樣寫在代碼塊中的邏輯就可以定義在其他地方,代碼塊中只需傳入
&邏輯名字
的參數了。就像下面的樣子:
>> projects.collect {&:name}
=> ["Write another ASCIIcast", "Go out walking"]
當你需要鏈式調用的時候,這種格式的作用就更明顯了。下面的代碼是不是可讀性更強了:
>> projects.collect(&:name).collect(&:upcase)
=> ["WRITE ANOTHER ASCIICAST", "GO OUT WALKING"]
當然了,不僅僅侷限於
collect
方法,所有代碼塊都可以使用to_proc。比如說可以爲any
方法定義檢查項目是否正常開展的to_proc,爲all
方法可以定義保存的to_proc等等。
>> 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">]
最開始可能覺得語法看起來怪怪的,但當你遇到需要使用鏈式調用時,它絕對是你的好幫手。
作者授權:Your welcome to post the translated text on your blog as well if the episode is free(not Pro). I just ask that you post a link back to the original episode on railscasts.com.
原文鏈接:http://railscasts.com/episodes/6-shortcut-blocks-with-symbol-to-proc?view=asciicast