DEV Community

Heshie Brody
Heshie Brody

Posted on • Edited on

2 2

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!

Image of Timescale

🚀 pgai Vectorizer: SQLAlchemy and LiteLLM Make Vector Search Simple

We built pgai Vectorizer to simplify embedding management for AI applications—without needing a separate database or complex infrastructure. Since launch, developers have created over 3,000 vectorizers on Timescale Cloud, with many more self-hosted.

Read full post →

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 :)

Postgres on Neon - Get the Free Plan

No credit card required. The database you love, on a serverless platform designed to help you build faster.

Get Postgres on Neon

AWS GenAI Live!

GenAI LIVE! is a dynamic live-streamed show exploring how AWS and our partners are helping organizations unlock real value with generative AI.

Tune in to the full event

DEV is partnering to bring live events to the community. Join us or dismiss this billboard if you're not interested. ❤️