我有一个具有以下表格格式的模型:
string "name"
integer "line_id"
json "filters"
其中,filters
字段包含具有嵌套键的 json 对象。我想在不覆盖其余 json 的情况下修改特定密钥。
目前,存储在filters
中的 json 对象看起来像
{
"ext": {"name": "filter", "id": 3},
"int": {"name": "numb", "id": 1}
}
我正在尝试在不修改 json 对象的其余部分的情况下将int.name
的值更新为"remove"
。
如果我执行以下操作,它只会覆盖整个 json 对象,而不是修改该特定键:
Model.where("filters->>'int'->>'name' IS NOT NULL").update(
filters: {
int: {
name: "remove"
}
}
)
如何简单地使用路径int.name
更新该键,同时保持其余属性不变?
你使用的是哪个版本的rails? 如果您使用的是 Rails 5,您应该能够
m = Model.where("filters->>'int'->>'name' IS NOT NULL").first
m.filters['name'] = 'remove'
m.save
这将保留现有的哈希键。
我认为对于 rails 4,您需要在现场使用 json 序列化程序,但我相信一旦您拥有序列化程序,就应该以相同的方式工作。
像这样的事情怎么样
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)
我从未使用过json
列,所以我不确定预期值是 JSON 还是将在插入前转换为 JSON 的Hash
,但更新语句将类似于
Model.update([1],[{
"ext"=> {"name"=> "filter", "id"=> 3},
"int"=> {"name"=> "remove", "id"=> 1}
}])
这使用ActiveRecord::Relation#update
其中第一个Array
是要更新的 ID,第二个Array
是要与这些 id 关联的新值。