Rails 模型 - 更新 JSON 中的嵌套键/值



我有一个具有以下表格格式的模型:

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 关联的新值。

最新更新