【问题标题】:Ruby - Update jsonb array column setup with jsonb_accessorRuby - 使用 jsonb_accessor 更新 jsonb 数组列设置
【发布时间】:2020-10-18 21:12:01
【问题描述】:

我有一个名为 data 的字段,它是使用 jsonb_accessor ruby​​ gem 设置的,如下所示:

jsonb_accessor :data,
  line_items: [:jsonb, array: true, default: []]

这是在我的Contract 模型上。当 Contract 创建时,它是一个空数组,如下所示:

data: {"line_items"=>[]},

我想向这个空数组添加多个哈希值。例如:

{user: "Joe"}

然后我可能会添加哈希:

{user: "Jack"}

我尝试了很多东西,但都没有成功,包括:

new = [{user: "Joe"}].to_json
Contract.last.update_all(["line_items = line_items || ?::jsonb", new])
##
Contract.last.update(["line_items = line_items || ?::jsonb", new])

然后我尝试了push

Contract.last.line_items.push("line_items" => {user: "Todd"})

然后我尝试了merge

Contract.last.line_items = Contract.last.line_items.merge(new)

没有任何效果。

【问题讨论】:

    标签: ruby-on-rails ruby postgresql jsonb


    【解决方案1】:

    一种选择就是用你想要的数据设置属性,然后用#save(或#save!)持久化它

    contract = Contract.create!
    => #<Contract id: 1, data: {"line_items"=>[]}, line_items: []>
    
    contract.line_items = [{foo: "bar"}]
    contract.save!
    
    contract
    => #<Contract id: 1, data: {"line_items"=>[{"foo"=>"bar"}]}, line_items: [{"foo"=>"bar"}]>
    

    在我的测试中,我能够通过仅传递对象本身(而不是先将其转换为 JSON)来使用 #update 方法:

    Contract.update(1, :line_items => [{foo: "bar"}])
    => #<Contract id: 1, data: {"line_items"=>[{"foo"=>"bar"}]}, line_items: [{"foo"=>"bar"}]>
    

    编辑: 看起来您正在尝试使用单个查询附加到数组,这似乎是可能的

    Contract.where(id: 1).update_all("data=jsonb_set(data,'{line_items}', data->'line_items' || '{\"foo\": \"bar\"}')")
    

    虽然我确信有更好的方法来实现相同的功能......

    【讨论】:

      【解决方案2】:

      jsonb_accessor 意味着您不必为了简单的访问器操作而手动处理 JSON。如果您想分配给line_items,请像往常一样使用update!

      contract.update!(line_items: [{user: "Joe"}])
      

      如果您想附加到单个合同的line_items,请在 Ruby 中添加到数组并更新。

      contract = Contract.last
      line_items = contract.line_items + [{user: "Joe"}]
      contract.update!(line_items: line_items)
      

      如果您想在 SQL 中完成所有操作,jsonb_accessor 不会为您提供任何帮助。您必须自己编写 SQL。要添加到数组,请使用jsonb_insert

      Contract
        .where(...)
        .update_all(
          q[jsonb_insert(data, '{"line_items", -1}', '{user: "Joe"}', true)]
        )
      

      '{"line_items", -1}' 表示在键“line_items”的最后一个元素处插入,true 必须在该点之后插入。

      【讨论】:

        猜你喜欢
        • 2018-05-17
        • 1970-01-01
        • 2017-08-23
        • 2016-12-24
        • 1970-01-01
        • 2018-03-22
        • 1970-01-01
        • 1970-01-01
        • 2021-02-28
        相关资源
        最近更新 更多