如何在我的数据库中存储哈希?

时间:2012-01-11 08:19:42

标签: ruby activerecord hash

是否有可以在数据库字段中写入和读取哈希值的Ruby或Activerecord方法?

我需要编写一个Web实用程序来接受POST数据并将其保存到数据库中,然后再以原始哈希形式从数据库中提取它。但理想情况下,不要“了解”结构是什么。换句话说,我的数据存储需要独立于任何特定的散列键集。

例如,有一次外部应用可能会POST到我的应用:

"user" => "Bill",
"city" => "New York"

但是外部应用程序可能会再次发布到我的应用程序:

"company" => "Foo Inc",
"telephone" => "555-5555"

因此,我的实用程序需要将任意哈希保存到数据库中的text字段,然后,根据保存的内容重新创建哈希值。

5 个答案:

答案 0 :(得分:18)

Rails 4增加了对Postgres hstore数据类型的支持,它允许您将哈希值直接添加到(postgres)数据库中。

如果您使用的是Rails 4和Postgres,则可以在迁移中使用hstore

def up
  execute "create extension hstore"
  add_column :table, :column, :hstore
end

def down
  remove_column :table, :column
end

该执行命令将在Postgres中启用hstore,因此您只需执行一次。

这使您可以在:column中存储哈希,就像使用任何其他数据类型一样。

答案 1 :(得分:8)

有两种方法可以做到这一点:

  1. 序列化您的哈希并将其存储在文本字段中。
  2. 拆分哈希并将每个密钥存储在一个单独的行中。
  3. 第一种方法的问题在于查找和操作既困难又昂贵。例如,与以常规表格格式存储数据相比,在Foo Inc.工作的所有员工的电话号码之前的前缀为“0”将是一场噩梦。

    您的架构将是:

    employees (id, created_at, updated_at)
    employee_details (id, employee_id, key, value)
    

    所以,存储

    "company" => "Foo Inc",
    "telephone" => "555-5555"
    

    你会这样做:

    employees: 1, 2012-01-01, 2012-01-01
    employee_details (1, 1, "company", "Foo Inc"), (2, 1, "telephone", "555-5555")
    

    这种方法的缺点:Rails本身不支持这种模式。

答案 2 :(得分:5)

您可以使用3 options的序列化:二进制格式的Marshal,YAML和JSON人类可读的数据存储格式。

一旦尝试了每种方法,不要忘记测量序列化和反序列化的时间。如果你需要以原始格式提取数据,JSON是不错的选择,因为你不需要对它进行反序列化,而是将它作为字符串本身使用。

答案 3 :(得分:3)

您正在寻找serialization。它将帮助您完全按照自己的意愿行事。

答案 4 :(得分:0)

Rails 4有一个名为Store的新功能,因此您可以轻松使用它来解决您的问题。您可以为它定义一个访问器,建议您将用于序列化商店的数据库列声明为文本,这样就有足够的空间。 original示例:

class User < ActiveRecord::Base
  store :settings, accessors: [ :color, :homepage ], coder: JSON
end

u = User.new(color: 'black', homepage: '37signals.com')
u.color                          # Accessor stored attribute
u.settings[:country] = 'Denmark' # Any attribute, even if not specified with an accessor

# There is no difference between strings and symbols for accessing custom attributes
u.settings[:country]  # => 'Denmark'
u.settings['country'] # => 'Denmark'