这个要看场景,很多时候报错优于沉默。
比如作者引用的find_by_id
。在大多数场景下,特别是 controller 中,应该用find
来期待报错而不是find_by_id
,然后rescue ActiveRecord::RecordNotFound
。
有时候沉默会比较好,比如处理复杂的 hash 的时候。
谢谢,要这样写:Post.where("id = ?",1).first.try(:title)
#11 楼 @Kabie 我写了一个 trytry,象这样:a.trytry('b.c.d.e') haskell 不熟悉,看着语法不是太喜欢,我会选择在 ruby 里做补丁,然后等 matz 把好东西都拿过来。
module Object
include ModuleBase
def trytry(sym_list, value=nil)
return self if value.present? and sym_list.last != '='
receiver = self
sym_list.to_s.split('.').each do |field|
if field.last == '='
receiver.try(field, value)
receiver.save!
else
receiver = if field =~ /\(/
params = field.gsub(/[ \):]/, '').gsub('(', ',').split(',')
receiver.try(params[0], *params[1..-1])
else
receiver.try(field)
end
end
end
receiver
end
end
@5swords present?
和try
都是 Rails 里面的,你却拿来给 Ruby 打补丁,这都是哪跟哪啊。
另外 try 最好也不要滥用。像这种Post.where("id = ?",1).first.try(:title)
在实际中根本用不着。
为什么?如果你是显示 Post 页面,id = 1 的 post 根本就不存在,你也就去不了那个页面,就不存在 try 这 try 那的问题来。
如果你是显示一个 collection, 比如 Post.last(5)。id = 1 的 post 根本就不在这个 collection 当中,更没有必要 try。
@Kabie 主要原因是这个 rescue 把以前所有可能发生的报错全部拯救了,这样调试时根本看不到正常的 backtrace,可能的坏蛋都被这个包庇者藏起来了。
但是有具体 class 的拯救还是好的,比如rescue ActiveRecord::RecordNotFound
总之 resue 应该用于具体的,有意义的拯救。像这种解决显示 title 的问题,即使有具体的拯救也没有必要使用。好比郭靖也不会见人就使降龙十八掌。
更多的你可以看看这个: http://stackoverflow.com/questions/10048173/why-is-it-bad-style-to-rescue-exception-e-in-ruby
Don’t rescue Exception. EVER. or I will stab you.
就这个具体场景而言,我认为find_by_id
和try(:title)
都是不好的做法。好的做法是先拿到 post instance, 然后再展开各种 attributes。如果找不到,rescue as above。
haskell 和 ruby 都是函数式,只不过 haskell 有内置 fmap,just,nothing 等,而 ruby 没有,ruby 实现类似的也很简单:
fmap = ->(f, x) do
x.nil? ? nil : f.(x)
end
getPostTitle = ->(post) { post.title }
findPost = ->(id) {Post.where(:id => id).first}
fmap.(getPostTitle, findPost.(1)) # return post 1 title
fmap.(getPostTitle, findPost.(0)) # return nil
只不过对于这种需求,ruby 一般不用函数式编程,而是用 #2 楼 @jasl 提到的 rails 扩展的 try 这种声明式编程