2012-01-11 23 views
8

¿Hay un método Ruby o Activerecord que pueda escribir y leer un hash desde y hacia un campo de base de datos?¿Cómo puedo almacenar un hash en mi base de datos?

Necesito escribir una utilidad web para aceptar datos POST y guardarlos en una base de datos, y luego extraerlos de la base de datos en su formato hash original. Pero, idealmente, sin "saber" qué es la estructura. En otras palabras, mi almacén de datos debe ser independiente de cualquier conjunto particular de claves hash.

Por ejemplo, una vez que la aplicación externa podría publicar una entrada en mi aplicación:

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

Pero otra vez la aplicación externa podría publicar una entrada en mi aplicación:

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

Así que mi utilidad necesita ahorrar un hash arbitrario a un campo text en la base de datos, luego, luego, recree el hash de lo que se guardó.

Respuesta

5

Puede utilizar la serialización con 3 options: Marshal en formato binario, YAML y JSON formatos de almacén de datos legibles por humanos.

Una vez que esté probando cada uno de los métodos, no se olvide de medir el tiempo para serializar y deserializar también. Si necesita recuperar los datos en formato de origen, JSON es la mejor opción para usar, ya que no necesita deserializarlo, sino usarlo como una cadena.

8

Hay dos maneras de hacer esto:

  1. serializar su hash y almacenarlo en un campo de texto.
  2. Divida el hash y almacene cada clave en una fila separada.

El problema con el primer enfoque es que encontrar y manipular es difícil y costoso. Por ejemplo, prefija un "0" antes de que el número de teléfono de todos los empleados que trabajan en Foo Inc. será una pesadilla, en comparación con el almacenamiento de los datos en formato de tabla regular.

Su esquema sería:

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

Por lo tanto, para almacenar

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

puede hacer:

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

Los inconvenientes de este enfoque: Carriles no soporta de forma nativa este tipo de un esquema

18

Rails 4 agrega compatibilidad con el tipo de datos Postgres hstore que le permitirá agregar hashes directamente a su base de datos (postgres).

Si está utilizando los carriles 4 y Postgres, puede utilizar hstore en su migración:

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

def down 
    remove_column :table, :column 
end 

que ejecutan comandos permitirá hstore en Postgres, por lo que sólo tiene que hacer esto una vez.

Esto le permitirá almacenar un hash en :column como lo haría con cualquier otro tipo de datos.

+0

¿es compatible con hashes/json anidados? – courtsimas

0

Rails 4 tiene una nueva característica llamada Store, por lo que puede usarla fácilmente para resolver su problema. Puede definir un descriptor de acceso para él y se recomienda que declare la columna de la base de datos utilizada para la tienda serializada como un texto, por lo que hay mucho espacio. El ejemplo 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' 
Cuestiones relacionadas