使用hstore Rails update_all

时间:2013-10-08 22:37:35

标签: ruby ruby-on-rails-3 activerecord rails-postgresql hstore

使用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为空时才会起作用。

2 个答案:

答案 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}))