如何在哈希中使用类似于.try()的方法来避免在空值时出现"undefined method"错误?

183

在Rails中,如果某个值不存在我们可以采取以下方法来避免出现错误:

@myvar = @comment.try(:body)

我在深入挖掘哈希表时,如何避免出现错误?

@myvar = session[:comments][@comment.id]["temp_value"] 
# [:comments] may or may not exist here
在上述情况下,session[:comments]try[@comment.id] 无法使用。有什么其他的方法可以实现相同的功能?

2
相关问题:https://dev59.com/WG855IYBdhLWcg3wYjSF - Andrew Grimm
5
Ruby 2.3 引入了 Hash#dig 方法,使得这里不再需要使用 try。现在 @baxang 给出的答案最好。 - user513951
Dig不会使try变得不必要,因为它仍然会在除哈希之外的其他对象上失败。例如nil。但是,使用dig与save运算符结合使用可以=> session&.dig(:comments, @comment.id, "temp_value") - Markus Andreas
12个回答

1

当你这样做:

myhash[:one][:two][:three]

你只是在调用一个“[]”方法的一系列链式调用,如果myhash[:one]返回nil,则会出现错误,因为nil没有“[]”方法。因此,一种简单而相当hacky的方法是向Niclass添加一个“[]”方法,它返回nil:我会在Rails应用程序中按如下方式设置它:
添加该方法:
#in lib/ruby_extensions.rb
class NilClass
  def [](*args)
    nil
  end
end

引入文件:

#in config/initializers/app_environment.rb
require 'ruby_extensions'

现在你可以毫不担心地调用嵌套的哈希表了:我在控制台中演示如下:
>> hash = {:foo => "bar"}
=> {:foo=>"bar"}
>> hash[:foo]
=> "bar"
>> hash[:doo]
=> nil
>> hash[:doo][:too]
=> nil

这很有趣 - 谢谢Max!你知道这个方法有什么缺点吗?还有其他人对此有什么看法吗? - sscirrus
17
它会隐藏你在代码其他部分意外遇到的 nil 问题。我认为这种方法很危险。 - Arsen7

-1

尝试使用

@myvar = session[:comments][@comment.id]["temp_value"] if session[:comments]

如果我不知道[:comments]或者[@comment.id]是否存在怎么办? - sscirrus
在这种情况下,我认为最好创建嵌套的IF语句来检查会话中的每个参数。 - bor1s
1
@sscirrus:如果(session[:comments] and session[:comments][@comment.id]),你可以执行session[:comments][@comment.id]["temp_value"] - Andrew Grimm
@AndrewGrimm - 是的,我想到这个方法也可以,但我希望有更简洁的解决方案(因为我会在同一个地方使用几个类似的表达式,这看起来很代码密集)。我喜欢你的实际答案。 :) - sscirrus

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接