简体   繁体   中英

Rails Model - Update Nested Key/Value in JSON

I have a model with the following table format:

string  "name"
integer "line_id"
json    "filters"

Where the filters field contains a json object with nested keys. I want to modify a specific key without overwriting the rest of the json.

Currently, the json object stored in filters looks like

{
  "ext": {"name": "filter", "id": 3},
  "int": {"name": "numb", "id": 1}
}

I'm trying to update int.name 's value to "remove" without modifying the rest of the json object.

If I do the following, it'll simply overwrite the entire json object instead of modifying that specific key:

Model.where("filters->>'int'->>'name' IS NOT NULL").update(
  filters: {
    int: {
      name: "remove"
    }
  }
)

How can I simply update that one key with the path int.name while keeping the rest of the attributes the same?

which version of rails are you using? if you are using rails 5, you should be able to

m = Model.where("filters->>'int'->>'name' IS NOT NULL").first
m.filters['name'] = 'remove'
m.save

this will leave the existing hash keys in place.

I think with rails 4, you need a json serializer on the field, but should work the same way once you have the serializer, i believe.

How about something like this

models = Model.where("filters->>'int'->>'name' IS NOT NULL")
  .each_with_object({}) do |m,obj|
    # credit to mudasobwa for the tap usage 
    obj[m.id] = {filters: m.filters.tap { |h| h['int']['name'] = 'remove' } }
  end 
Model.update(models.keys,models.values)

I have never used a json column so I am unsure if the anticipated value is meant to be JSON or a Hash that will be converted to JSON before insertion but the update statement will be akin to

Model.update([1],[{
         "ext"=> {"name"=> "filter", "id"=> 3},
         "int"=> {"name"=> "remove", "id"=> 1}
       }])

This uses ActiveRecord::Relation#update where the first Array is the ids to update and the second Array is the new values to associate with those ids.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM