2011-02-09 8 views
18

así que tengo una columna serializada: dimensiones, y en mi migración, me gustaría configurar el campo para que sea un hash predeterminado.predeterminado para la columna serializada en la migración de registro activo

he intentado ...

create_table :shipping_profiles do |t| 
     t.string  :dimensions_in, :default => {:width => 0, :height => 0, :depth => 0} 

y justo

t.string :dimensions_in, :default => Hash.new() 

pero los campos terminan nula. ¿cómo puedo establecer un objeto serializado predeterminado para este campo en la creación, o al menos asegurarme de que mi atributo de serialización sea siempre un hash?

Respuesta

33

Cuando Rails serializa un hash para guardar en el db, todo lo que hace es convertirlo a YAML para que pueda almacenarse como una cadena. Para conseguir que esto funcione en la migración, todo lo que necesita hacer es convertir el hash para yaml ...

t.string :dimensions_in, :default => {:width => 0, :height => 0, :depth => 0}.to_yaml 

O, alternativamente, la puso en el modelo después de la inicialización ...

class ShippingProfile < ActiveRecord::Base 

    after_initialize :set_default_dimensions 

    private 

    def set_default_dimensions 
     self.dimensions_in ||= {:width => 0, :height => 0, :depth => 0} 
    end 

end 
+0

after_initialize es una gran solución! ¡Gracias! – brewster

+3

¡También es bueno saber sobre el truco del yaml en las migraciones, gracias! – opsb

+0

Grandes respuestas ... – dastanko

4

Probé este código y funcionó para mí. Esto aprovecha la forma en que ActiveRecord envía los métodos del modelo sincronizados dinámicamente a las columnas de la tabla.

class MyModel < ActiveRecord::Base 

    def dimensions_in 
    attributes["dimensions_in"] ||= {:width => 0, :height => 0, :depth => 0} 
    end 

end 
+0

¡Genial! Se puede utilizar como valor predeterminado sin especificar el valor predeterminado en la migración –

+0

esto no funciona con atributos que se serializan como 'serialize: dimensions_in, Hash' ya que el atributo vuelve como el tipo de objeto y por lo tanto es" presente ". Tendrá que hacer algo como 'atributos ['dimensions_in']. Presente? ? atributos ['dimensions_in']: {width: 0, height: 0, depth: 0} ' –

+0

Still on Rails 2;), gracias por esto – CodeGroover

7

También puede especificar una clase predeterminada para la columna serializada. Ver the docs.

class MyModel < ActiveRecord::Base 
    serialize :dimensions_in, Hash 
end 

he encontrado que after_initialize bloques pueden causar un gran rendimiento golpeó, sobre todo si lo que usted necesita para MyModel.all (por ejemplo: para una exportación a granel)

Sin la clase: MyModel.new.dimensions_in => nil

Con una clase Hash predeterminada: MyModel.new.dimensions_in => {}

+2

¿Pero cómo pasar los valores predeterminados a través de este método? –

+0

@ZuhaibAli De los documentos: "el valor predeterminado para ese atributo será una nueva instancia de esa clase". Entonces, con este método, es solo una instancia nueva y no puede ser algo personalizado. –

Cuestiones relacionadas