使用activerecord使用hstore列更新多个记录的好方法是什么?现在我正在循环,更新和保存,如下所示:
time = Time.now.to_s
scoped_tasks.each do |task|
task.data[:last_checked] = time
task.save!
end
使用update_all
查询是否有办法执行此操作?我见过的一个解决方案是这样的:
MyModel.update_all(:properties => ActiveRecord::Coders::Hstore.dump({'a' => 1}))
但问题是它会覆盖整个列,因此会丢失其他值。我也见过这个:
MyModel.update_all("data = data || hstore('a', 'blah')")
但出于某种原因,我回来了0
的价值。它看起来只有在hstore为空时才会起作用。
答案 0 :(得分:6)
我自己也在努力解决同样的问题,这就是我能够解决的问题:
MyModel.update_all([%(data = data || hstore(?,?)), 'a', 'new_value']))
对此的核心修复是将update_all操作包装在[]和%()中。我仍然在努力弄清楚%()如何定义Postgre SQL中的SET,所以如果有人有一个非常有帮助的解释。
在我的情况下,我实际上也删除了一个键(实际上我想更新键名但保留值)。因此,如果有人有这个问题,代码看起来像:
MyModel.update_all([%(data = delete("data",?)), 'a'])
我希望在同一个调用中执行这两个操作,但是在SQL中创建了一个非常奇怪的命令,其中第二个操作作为WHERE子句的一部分而不是SET添加。对我来说仍然有点黑魔法,但希望这有助于......
答案 1 :(得分:0)
如果您使用
MyModel.update_all(:properties => ActiveRecord::Coders::Hstore.dump({'a' => 1}))
然后它将清除其他值,如果您尝试使用
MyModel.update_all("data = data || hstore('a', 'blah')")
只有在hstore列中有任何值时它才会起作用,
所以尝试使用两者的组合
if (hstore_column_name).present?
MyModel.update_all("data = data || hstore('a', 'blah')")
else
MyModel.update_all(:properties => ActiveRecord::Coders::Hstore.dump({'a' => 1}))