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

时间:2018-05-24 17:53:57

标签: ruby-on-rails json ruby postgresql

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

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

filters字段包含带嵌套键的json对象。我想修改一个特定的密钥而不覆盖其余的json。

目前,存储在filters中的json对象看起来像

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

我正在尝试将int.name的值更新为"remove"而不修改json对象的其余部分。

如果我执行以下操作,它只会覆盖整个json对象而不是修改该特定键:

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

如何只使用路径int.name更新一个密钥,同时保持其余属性相同?

2 个答案:

答案 0 :(得分:2)

您使用的是哪个版本的导轨?如果你使用的是rails 5,你应该可以

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

这将保留现有的哈希键。

我认为使用rails 4,你需要在场上使用json序列化器,但是一旦你拥有序列化器,它应该以相同的方式工作,我相信。

答案 1 :(得分:0)

这样的事情

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还是Hash,它会在插入之前转换为JSON,但更新语句类似于

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

这使用ActiveRecord::Relation#update,其中第一个Array是要更新的ID,第二个Array是与这些ID关联的新值。