Rails Object#try 对潜在的 Rails 中的 nil 调用方法

villins · 2015年08月08日 · 最后由 villins 回复于 2015年08月21日 · 3174 次阅读

对潜在的 Rails 中的 nil 调用方法

在 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

拿我们项目中的代码来举例

before 没有使用 try
# helper method
def ymdhm_strftime(time)
  time.strftime("%Y-%m-%d %H:%M") if time.present?
end
# erb 
<p>上映 : &nbsp; <%= ymd_strftime(@film.show_date) %></p>

after 使用 try

# 可以直接在页面使用
<p>上映 : &nbsp; <%= @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

感谢分享,比外面吵架有营养多了。

不推荐使用 try。出现 nil 的原因还是要明确出来 准确的抛出异常才好

还可以这么写

obj.try { strftime, "%Y-%m-%d %H:%M" }

当需要在 nil 的时候忽略掉参数的某些计算的话,用 block form 比较简便 (其实和 if obj then ... end 也差不多...)

#4 楼 @so_zengtao 用 try,在某些字段运营没有来得及维护,但用一些 object 的方法,用 try 不会导致全局出错

需要 登录 后方可回复, 如果你还没有账号请 注册新账号