Uso de Rails serialize para guardar hash en la base de datos


Estoy tratando de guardar un id de asignación de hash a una serie de intentos en mi aplicación rails. Mi migración a la base de datos para acomodar esta nueva columna:

class AddMultiWrongToUser < ActiveRecord::Migration
  def self.up
    add_column :users, :multi_wrong, :string
  end

  def self.down
    remove_column :users, :multi_wrong
  end
end

En mi modelo tengo:

class User < ActiveRecord::Base 
 serialize :multi_wrong, Hash
end

Pero cuando uso la consola rails para probar esto haciendo:

user = User.create()
user.multi_wrong = {"test"=>"123"}
user.save

La salida es false. ¿Qué está pasando aquí?

Author: cmwright, 2011-07-14

3 answers

El tipo de columna es incorrecto. Debe usar Texto en lugar de Cadena. Por lo tanto, su migración debe ser:

 def self.up
   add_column :users, :multi_wrong, :text
 end

Entonces Rails lo convertirá correctamente en YAML para usted (y realizará una serialización adecuada). Los campos de cadenas tienen un tamaño limitado y solo contienen valores especialmente pequeños.

 166
Author: Benjamin Tan Wei Hao,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-10-30 16:40:46

ACTUALIZADO:

La implementación exacta dependerá de su base de datos, pero PostgreSQL ahora tiene json y jsonb columnas que pueden almacenar de forma nativa sus datos hash/object y le permiten consultar contra el JSON con ActiveRecord!

Cambia tu migración y listo.

class Migration0001
  def change
    add_column :users, :location_data, :json, default: {}
  end
end

ORIGINAL:

Para obtener más detalles: rieles docs && apidock

Asegúrese de que su columna es :text y no :string

Migración:

$ rails g migration add_location_data_to_users location_data:text

Debería crear:

class Migration0001
  def change
    add_column :users, :location_data, :text
  end
end

Tu Clase Se Vería Como:

class User < ActiveRecord::Base
  serialize :location_data
end

Acciones Disponibles:

b = User.new
b.location_data = [1,2,{foot: 3, bart: "noodles"}]
b.save

Más Impresionante?!

Utilizar postgresql hstore

class AddHstore < ActiveRecord::Migration  
  def up
    enable_extension :hstore
  end

  def down
    disable_extension :hstore
  end
end 

class Migration0001
  def change
    add_column :users, :location_data, :hstore
  end
end

Con hstore puede establecer atributos en el campo serializado

class User < ActiveRecord::Base  
  # setup hstore
  store_accessor :location_data, :city, :state
end
 59
Author: Blair Anderson,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-04-16 05:58:11

Rails 4 tiene una nueva característica llamada Store, por lo que puede usarla fácilmente para resolver su problema. Puede definir un accessor para él y se recomienda declarar la columna de la base de datos utilizada para el almacén serializado como 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'
 14
Author: Aboozar Rajabi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-04-18 16:32:06