activerecord-postgres-hstore
activerecord-postgres-hstore copied to clipboard
update_all doesn't work?
MyModel.update_all(:properties => {'a' => 1})
tries to issue an UPDATE statement with properties set to the serialized YAML hash (and fails). Is this a bug or intended behaviour?
Similarly the following fails: MyModel.update_all(['properties = ?', {'a' => 1}])
Update: following works -- MyModel.update_all(:properties => ActiveRecord::Coders::Hstore.dump({'a' => 1}))
Not sure if this a peculiarity of ActiveRecord and not the hstore gem.
Problem with this solution is that it seems to overwrite the entire column, so other values are lost. I tried this solution but it didn't work either.
If you aren't against writing sql literals, you could make it a little more understandable.
Overwrite all values in the hstore:
MyModel.update_all("properties = hstore('a', '1')")
Merge in new attributes:
MyModel.update_all("properties = properties || hstore('a', '1')")
Plus you can more easily control whether you want to set the hstore column or merge in new data.
Does the second one not behave like it would in ruby? Because looking at it, it looks like if properties already exists then it won't assign 'a'
to '1'
. Not sure the exact syntax, but I guess I would expect something more like:
MyModel.update_all("properties = properties || hstore(); properties['a'] = '1'")
It's actually just PostgreSQL syntax. The ||
operator concatenates two hstore's and PostgreSQL's hstore()
function creates a new hstore with key 'a' and value '1' (('a' => '1')
is the same thing, but using the deprecated =>
operator).
The query is setting properties
to the concatenation of the existing value of properties
with 'a' => '1'
.
The examples section in the docs includes this case.
Ah, okay, so it's more like a Hash#merge
in ruby, or the |
operator on arrays. Thanks for the reference.