如何使用ActiveRecord json字段类型

Fre*_*Ben 13 postgresql activerecord json ruby-on-rails ruby-on-rails-4

我有一个Rails模型,它有一个类型为"json"的数据库列:

create_table "games", force: true do |t|
  t.json     "game_board"
  t.datetime "created_at", null: false
  t.datetime "updated_at", null: false
end
Run Code Online (Sandbox Code Playgroud)

大!现在我该如何使用它?它真的像处理这样的领域一样Hash简单吗?

self.game_board[:player1] = 1
self.game_board[:cards] = cards.to_hash
Run Code Online (Sandbox Code Playgroud)

如果我写这个,那么一切都会按预期工作,所以在未来的客户API调用中我可以这样做吗?:

self.game_board[:player] # And get back the 1 that I put here before
Run Code Online (Sandbox Code Playgroud)

性能如何呢?game_board即使从未读过该字段,每次都会对整个序列进行反序列化吗?每当我改变"Hash"的一部分时,是否会重写该字段(IOW是数据库写入)

And*_*iep 23

是的,ActiveRecord允许json在其模型中将Postgres的" 字段"简单地用作Hashes.但是,有几件事需要考虑:

  1. 哈希可能在初始化NULL
    在你create_table迁移你让现场:game_boardNULL.因此,在第一次使用时,:game_board模型实例的字段将是,NULL并且在使用之前必须首先初始化哈希.(见下面的例子)

  2. 在JSON中,所有键都是字符串
    因此,在保存(和重新加载)时,如果您之前使用过符号或数字,则所有键都将转换为字符串.因此,为防止出现不需要的行为,建议使用String-keys,除非您的ORM配置为符号化所有键.


你的例子:

self.game_board         ||= {}
self.game_board[:player1] = 1
self.game_board[:cards]   = cards.to_hash

# after reload from database (access via String-key):
self.game_board['player1']  # And retrieve value 1 (that we put here before)
Run Code Online (Sandbox Code Playgroud)


@表演:

  1. 是的,每次ActiveRecord从数据库中读取条目并创建模型实例时,JSON字段都会被反序列化为Hashes.但是如果你认为这对你的应用程序来说是性能影响,你应该使用文本字段并在需要时序列化/反序列化JSON/Hashes,或者更好的是,根本不使用ActiveRecord.通过创建大量类和使用魔术方法,ActiveRecord创建了很多开销,您不必担心JSON的反序列化.便利有其成本.

  2. 是的,每次更改Hash中的值时,(整个)JSON字段都会被替换并使用新的序列化版本进行更新.
    关于此的两点说明:

    • 即使在Postgres本身(不仅在ActiveRecord中),到目前为止还没有对某些JSON元素执行更新的可能性.比较这个Stackoverflow问题
    • 通常,JSON字段应该与固定结构一起使用,或者至少以可管理的大小使用,并且字段类型不应该是文档存储,例如.在MongoDB中.比较Postgres文档