Question

What's a good way to update multiple records with hstore columns using activerecord? Right now I'm looping through, updating and saving like this:

time = Time.now.to_s
scoped_tasks.each do |task|
  task.data[:last_checked] = time
  task.save!
end

Is there any way to do this with an update_all query? One solution I've seen looks like this:

MyModel.update_all(:properties => ActiveRecord::Coders::Hstore.dump({'a' => 1}))

But the problem with that is it overwrites the entire column, so other values are lost. I've also seen this:

MyModel.update_all("data = data || hstore('a', 'blah')")

But for some reason I get back 0 for the value. It also looks like it will only work if the hstore is empty.

Was it helpful?

Solution

I struggled with the same question myself, here is how I was able to solve it:

MyModel.update_all([%(data = data || hstore(?,?)), 'a', 'new_value']))

The core fix for this was wrapping the update_all action in a [] and %(). I am still struggling to figure out how the %() defines the SET in the Postgre SQL so if anyone has an explanation that would be uber-helpful.

In my case I was actually removing a key too (really I wanted to update the key name but keep the value). So if anyone has that issue the code looks like:

MyModel.update_all([%(data = delete("data",?)), 'a'])

I was hoping to do both actions in the same call but that was creating a really odd command in the SQL where the second action was added as part of the WHERE clause not the SET. Still a bit of black magic for me but hopefully this helps...

OTHER TIPS

If you use

MyModel.update_all(:properties => ActiveRecord::Coders::Hstore.dump({'a' => 1}))

then it will cleared out other values and if you try to use

MyModel.update_all("data = data || hstore('a', 'blah')") it will only work if there is any value in hstore column, so try to use combination of both

if (hstore_column_name).present? MyModel.update_all("data = data || hstore('a', 'blah')") else MyModel.update_all(:properties => ActiveRecord::Coders::Hstore.dump({'a' => 1}))

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top