DEV Community

Heshie Brody
Heshie Brody

Posted on • Updated on

Update jsonb Columns Using The Rails Active Record Native Methods

While building a Rails API backend for a recent project I came across a challenge when updating jsonb columns.

You see as a pure Rail'ist (Is that a thing...?) I try to stay away from writing SQL strings in my app when I could use Active Record native methods, but since I had defined some columns as Jsonb it seemed like I would need to use SQL since all the tutorials were making use of jsonb_set SQL method as follows:

sql = 'UPDATE users SET preferences = jsonb_set(
options, \'{email_opt_in}\', \'false\', FALSE) WHERE id = 1;'

c.execute(sql)
Enter fullscreen mode Exit fullscreen mode

But as a Rail'ist I was looking for something more like user.update(params).

So...
This is what I came up with:

  1. First get the current column value which Active Record returns as a Ruby hash:
    user = session_user
    currentKeys = user.api_keys

  2. Convert post params to a hash and extract the nested values which were nested under keys:
    hashedParams = user_params.to_h[:keys]

  3. Use the Ruby hash merge method to merge my post params and current user column data:
    newKeys = currentKeys.merge(hashedParams)

  4. I could now use the Rails object update method as usual:
    user.update(api_keys: newKeys)

Here is the complete code:

    user = session_user
    currentKeys = user.api_keys
    hashedParams = user_params.to_h[:keys]
    newKeys = currentKeys.merge(hashedParams)

    if user.update(api_keys: newKeys)
        Bla, bla, bla...
Enter fullscreen mode Exit fullscreen mode

Ok, now here's the thing: I need validation if the above is acceptable as a Rail'ist(you heard it here first) so please If I'm missing anything(method, convention, irk etc.) comment below :)

Thanks For Reading!

Top comments (2)

Collapse
 
danishsatkut profile image
Danish Aziz Satkut

Your code can result in a race condition when two request execute the above code at the same time. Hence, the tutorials use the jsonb_set, which performs the modification directly at DB level.

Collapse
 
heshiebee profile image
Heshie Brody

Good point. Wrote this when I was just starting out, should definitely revise this :)