我有一段代码,其中有:
requests.each do |request|
request.each do |rqst|
select_keys = ["author", "author_name"]
selected_unit_req = rqst.select { |m| select_keys.include?(m) }
user = Etl::Models::User.where(username: selected_unit_req["author"]["username"] )
user.merge!({ author_name: selected_unit_req["author"]["name"] })
end
end
我无法测试合并!方法,运行现有的单元测试时得到NoMethodError:undefined method '[]' for nil:NilClass
。有什么建议吗?
答案 0 :(得分:0)
让我们假设在您给的示例rqst
中返回的是空哈希值{}
。
设置selected_unit_req
时,它将设置为空哈希值:
selected_unit_req = rqst.select { |m| select_keys.include?(m) }
=> {}
当您随后调用selected_unit_req["author"]
时,将检查哈希中是否有名为author
的键,并返回nil
:
selected_unit_req["author"]
=> nil
因此,运行完整调用selected_unit_req["author"]["username"]
等效于以下内容:
nil["username"]
NoMethodError: undefined method `[]' for nil:NilClass
这就是引发错误的原因;您希望selected_unit_req["author"]
返回带有键username
的哈希,但它返回的是nil
。
确保selected_unit_req
具有您首先需要的哈希键和值。
更新
在下面的评论中,您询问如何验证它是否具有所需的密钥。答案取决于几件事,例如您希望在没有行为时看到的行为以及您使用的Ruby版本。
如果没有键,并且您使用的是现代版本的Ruby(> = 2.3.0),我将假设可以跳过rqst
。
这是对Hash类使用dig
方法的一种方法:
request.each do |rqst|
next unless rqst.dig('author', 'username') && rqst.dig('author', 'name')
user = Etl::Models::User.where(username: rqst['author']['username'] )
user.merge!({ author_name: rqst['author']['name'] })
end
如果next
没有键rqst
的子键为author
且另一个子键为{{ 1}}。之所以有效,是因为如果哈希中没有这些键,username
将返回name
。
让我们假装dig
。该行的解释方式是:
nil
由于rqst == {}
在Ruby中是falsy,因此最终会调用next unless nil && nil
跳过当前的nil
值,然后继续进行迭代中的下一个值。 / p>
我也删除了next
,因为它不必要地重复了;由于您已经确切知道要从rqst
中获得什么键/值,因此无需仅使用这些值创建新的哈希;相反,您可以提取这些值并在需要的地方直接使用它们。