2011-02-09 11 views
18

quindi ho una colonna serializzata: dimensioni, e nella mia migrazione, vorrei impostare il campo come un hash predefinito.default per la colonna serializzata nella migrazione activerecord

ho provato ...

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

e proprio

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

ma i campi finiscono nullo. come posso impostare un oggetto serializzato di default per questo campo alla creazione, o almeno assicurarmi che il mio attributo serialize sia sempre un hash?

risposta

33

Quando Rails serializza un hash da salvare nel db, tutto ciò che fa è convertirlo in YAML in modo che possa essere memorizzato come una stringa. Per arrivare a questo lavoro nella migrazione, tutto quello che dovete fare è di convertire l'hash per yaml ...

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

Oppure, in alternativa, lo mise nel modello dopo l'inizializzazione ...

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 è una grande soluzione! Grazie! – brewster

+3

ottimo per conoscere il trucco yaml nelle migrazioni, grazie! – opsb

+0

Grandi risposte ... – dastanko

4

Ho provato questo codice e ha funzionato per me. Questo sfrutta il modo in cui ActiveRecord invia dinamicamente i metodi del modello sincronizzati alle colonne della tabella.

class MyModel < ActiveRecord::Base 

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

end 
+0

Ottimo! Può essere usato come valore di default senza specificare la migrazione predefinita –

+0

questo non funziona con attributi serializzati come 'serialize: dimensions_in, Hash' come l'attributo ritorna come il tipo di oggetto e quindi è" presente ". Dovrai fare qualcosa come 'attributes ['dimensions_in'] .presente? ? attributes ['dimensions_in']: {width: 0, height: 0, depth: 0} ' –

+0

Still on Rails 2;), grazie per questo – CodeGroover

7

È inoltre possibile specificare una classe predefinita per la colonna serializzata. Vedi the docs.

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

Ho scoperto che after_initialize blocchi possono causare un enorme prestazioni colpito, soprattutto se si sarebbe mai bisogno di MyModel.all (ad esempio: per un'esportazione bulk)

Senza la classe: MyModel.new.dimensions_in => nil

Con una classe predefinita Hash: MyModel.new.dimensions_in => {}

+2

Ma come passare i valori predefiniti con questo metodo? –

+0

@ZuhaibAli Dalla documentazione: "il valore predefinito per quell'attributo sarà una nuova istanza di quella classe." Quindi con questo metodo è solo una nuova istanza e non può essere qualcosa di personalizzato. –

Problemi correlati