我试图更新对象的属性,但我尝试更新的对象通常不再存在。
例如:我正在处理CSV文件以获取属性:
array.each do |a|
player = Player.find_by_grepo_id(a[:grepo_id])
player.update_attributes(a)
end
如果找不到播放器,则会抛出错误。
我从之前的经历中学到了什么:
ActiveRecord :: Base.find如果找不到记录则总是抛出异常,这是故意的。 我应该只使用find,如果我绝对希望拥有我正在寻找的任何东西。 如果我发布了一个节目动作并且无法找到该文章,我应该挽救该异常并呈现404(未找到) 而不是重定向到索引(技术上)。
如果我想在没有强制异常的情况下通过它的id属性找到某些东西,我应该使用动态查找器 find_by_id(在我的情况下是find_by_grepo_id),如果找不到具有该id的记录,将返回false。
但是在运行包含上述代码的任务时我得到了
NoMethodError: undefined method `update_attributes' for nil:NilClass
那是因为具有该特定ID的玩家不再存在。如果我用update_attributes
方法将.present?
调用包装起来就可以了。
我缺少什么?不应该使用find_by_id方法不抛出错误而只是跳过它吗?
答案 0 :(得分:3)
如果你想在一个电话而不是两个电话中进行,你可以使用这样的update_all
方法:
Player.where(:grepo_id => a[:grepo_id]).update_all(a)
这将产生以下SQL:
UPDATE players SET ... = ..., ... = ... WHERE players.grepo_id = ...
如果grepo_id
不存在,也可以使用:任何内容都不会更新。但请注意,这只是运行SQL; 忽略模型上的任何验证或回调。
答案 1 :(得分:2)
这是因为你正在执行update_attributes,即使它没有通过grepo_id找到记录。如果找不到任何记录,find_by_grepo_id将返回nil。所以你需要添加一个条件来摆脱这个错误。
array.each do |a|
player = Player.find_by_grepo_id(a[:grepo_id])
player.update_attributes(a) if player.present?
end
答案 2 :(得分:0)
Rails有一个try
方法(check the docs),你可以在这里使用它:
array.each do |a|
player = Player.find_by_grepo_id(a[:grepo_id])
player.try do |p|
p.update_attributes(a)
end
end
当没有找到记录时,这应该可以正常工作并更新属性或无声地失败(不会抛出异常)。