【问题标题】:A rails field that is an array of JSON objects?作为 JSON 对象数组的 rails 字段?
【发布时间】:2016-07-06 08:44:05
【问题描述】:

我有一个 Damage 表,其中包含以下字段:

  • 说明
  • 损坏日期

我想添加另一个字段来存储Damagepoints,它们是如下所示的 JSON 对象:

{ top: 50, left: 100 }

顶部和左侧是图表上damagepoint 的坐标。 damagepoints 由用户使用 Javascript 添加/删除。

但是,我想在一个字段中存储这些damagepoints 的数组,如下所示:

@damage.damagepoints = [{left: 40, top: 99}, {left: 100, top: 35}, {left: 150, top: 95}]

我不想使用具有has_many 关系的Damagepoint 表来执行此操作,因为对此的所有更改都将使用Javascript 完成,并且如果Damagepoints 由用户创建或删除,我只想从客户端传递damagepoints 的更新数组,并用新数组替换数据库中的旧数组。如果我使用has_many 关系,我必须删除所有Damagepoints 并在每次更新数组时创建一个新的(因为它太复杂了,删除/添加特定的损坏点没有任何好处,因为我不需要跟踪历史)。

存储@damage.damagepoints(上图)等数据的最简单方法是什么?我需要做的就是将它(通过控制器)传递给 html5 数据属性,以便 Javascript 可以使用它来将现有的damagepoints 添加到图表中(基于它们的坐标),然后传递一个当用户单击“保存”按钮时,通过 AJAX 调用将更新的数组(来自 html5 数据属性)返回到控制器。

我正在使用 Rails 4.2 和 Postresql。

谢谢!

【问题讨论】:

    标签: javascript ruby-on-rails ruby json postgresql


    【解决方案1】:

    在写入数据库之前序列化数据并在读取时反序列化。您可以覆盖模型中的 getter 和 setter。

    两个不错的序列化选项是JSONYAML

    Rails 带有 json gem,因此您可以在任何对象或数组上调用 to_json。然后你需要阅读它,JSON.parse(some_json)

    同样,Rails 带有yaml,因此您可以使用YAML.dump(text)YAML.load(text)。在我看来,YAML 比 JSON 更易于阅读,但如果您将数据传递给 Javascript,则 JSON 是标准。

    【讨论】:

    • 谢谢,我可以在数据库中使用普通的string 字段吗?
    【解决方案2】:

    当您使用 postgres 时,您很幸运:postgres 有一个原生的 json 类型。这比使用序列化将数据存储为某种形式的编码字符串要好得多,因为 postgres 具有丰富的运算符系列,允许您查询该 json 数据。

    如果您使用的是 postgres 9.4,那么您也可以使用 jsonb 类型。这通常更好,因为它存储了数据的处理版本(即它不必一遍又一遍地重新解析数据)并且它允许索引。

    Rails 开箱即用地支持此功能(请参阅here),您只需添加一个 json(b) 类型的列。如果您的迁移包含

    create_table :damages do |t|
      t.string :description
      t.jsonb :damage_points
    end
    

    然后

    Damage.create(damage_points:  [{left: 40, top: 99}, {left: 100, top: 35}])
    

    将创建一个损坏点数据存储为 json 的行。唯一需要注意的是,尽管您的输入数据在哈希值中有符号作为键,但在从数据库中获取时,您总是会得到字符串作为键。

    【讨论】:

    • 谢谢!澄清一下,如果用户对damage_points 进行更改,然后通过 AJAX 调用将其作为哈希数组传递给控制器​​,我可以设置 `Damage.damage_points = nil' 然后设置 'Damage.create(damage_points : [{ ... }]'?我想避免创建或删除特定的damage_points,因为这会带来很多麻烦而收获甚微。再次感谢!
    • 是的 - 重新分配到 damage_points 将完全覆盖已经存在的内容。也不需要先设置为零。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-04-18
    • 1970-01-01
    • 2020-04-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多