activerecord-postgres-hstore icon indicating copy to clipboard operation
activerecord-postgres-hstore copied to clipboard

update_all doesn't work?

Open saurabhnanda opened this issue 11 years ago • 5 comments

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.

saurabhnanda avatar Apr 18 '13 13:04 saurabhnanda

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.

mockdeep avatar Oct 08 '13 22:10 mockdeep

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.

greggroth avatar Jul 16 '14 00:07 greggroth

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'")

mockdeep avatar Jul 16 '14 02:07 mockdeep

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.

greggroth avatar Jul 16 '14 03:07 greggroth

Ah, okay, so it's more like a Hash#merge in ruby, or the | operator on arrays. Thanks for the reference.

mockdeep avatar Jul 16 '14 03:07 mockdeep