在 Rails 中,我们平常可以使用很多非常便利的方法,其中有一个我认为有点 cool 的方法 —— Object#try 它有什么作用昵,它可以让我们调用一个对象不用担心这个对象是否为 nil,因此抛出异常。 如何使用它,如下
"HELLO WORLD".try(:downcase)
=> "hello world"
看起来跟 Object#send 差不多,都是传递 symbol,args 和 block,但是差别就是上面所说,nil 使用 send 去调用不属于 nil 的方法,还是会引起异常。
nil.send(:downcase)
NoMethodError: undefined method `downcase' for nil:NilClass
nil.try(:downcase)
=> nil
拿我们项目中的代码来举例
# helper method
def ymdhm_strftime(time)
time.strftime("%Y-%m-%d %H:%M") if time.present?
end
# erb
<p>上映 : <%= ymd_strftime(@film.show_date) %></p>
# 可以直接在页面使用
<p>上映 : <%= @film.show_date.try(strftime, "%Y-%m-%d %H:%M") %></p>
# 可以重构 helper method
def ymdhm_strftime(time)
time.try(strftime, "%Y-%m-%d %H:%M")
end
还有 try 可以链式调用
"HELLO WORLD".try(:downcase).try(:capitalize)
=> "Hello world"
它虽然能给我们带来便利,但是我们不能因此滥用它
# object_try.rb
require 'benchmark/ips'
require 'active_support/core_ext/object/try'
Benchmark.ips do |x|
x.report("try method") { "hello".try(:upcase) }
x.report("call method") { "hello".upcase }
x.compare!
end
ruby object_try.rb
Calculating -------------------------------------
try method 62.882k i/100ms
call method 74.916k i/100ms
-------------------------------------------------
try method 1.861M (± 8.7%) i/s - 9.244M
call method 2.737M (± 8.2%) i/s - 13.635M
Comparison:
call method: 2736550.4 i/s
try method: 1861489.0 i/s - 1.47x slower