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.