2010-09-16 9 views
5

Sto cercando di capire i callback dei record attivi, ma non funzionano, come vorrei.Come si impostano gli attributi in un oggetto ActiveRecord prima di salvarlo?

ad es.

Modello

Checklist<ActiveRecord... 
attr_accessible :item1, :item2, :done # they are all boolean 

before_save :check_done 

private 
def check_done 
    if item1 && item2 
    write_attribute :done, true 
    else 
    write_attribute :done, false 
    end 
end 

questo non funziona se un'istanza di un oggetto nella console e cercare di salvarlo, l'operazione di salvataggio restituisce "false" :(

Cosa c'è di sbagliato in questo codice? grazie in anticipo :)

EDIT: sembra che ci sia qualcosa che non va con la chiamata "before_save", se uso "after_save", il codice funziona ... ma l'attributo non viene salvata (ovviamente). Questo è davvero strano

EDIT 2 Wierd ... i registri di sviluppo mostra questo

FROM sqlite_master 
WHERE type = 'table' AND NOT name = 'sqlite_sequence' 
[0m 
    [1m[35mChecklist Load (0.2ms)[0m SELECT "checklists".* FROM "checklists" ORDER BY checklists.id DESC LIMIT 1 
WARNING: Can't mass-assign protected attributes: id 

ma che è davvero strano, perché se tolgo la linea attr_accessible io ancora ottengo questo errore ...

EDIT 3 Se qualcuno chiede, sì, io sto cercando di aggiornare un esistente record.

EDIT 4 Sì, mi piace modificare Se scriv nella console

c.save => # false 
c.errors => #<OrderedHash {}> 
+0

Perché vuoi dire con questo non funziona, quali sono gli errori? Puoi controllare chiamando yourobject.errors dopo yourobject.save – Mike

+0

oh, ok Ho ottenuto questo myobject.errors # tabaluga

+0

Che ne dici di 'myobject.errors.inspect' ?? – PeterWong

risposta

8

Il problema con il callback è che restituisce false se item1 o item2 è falso.

Dalla documentazione Active Record Callbacks:

Se il valore di ritorno di un before_validation richiamata può essere valutato per false, il processo verrà interrotto e Base#save tornerà false.

La soluzione è semplice; tornare true alla fine del vostro richiamata, in questo modo:

def check_done 
    self.done = (item1 && item2) 
    return true 
end 
+3

grazie, grazie, grazie! BTW. a tutti voi se vieni a Berlino, mandami un messaggio, ti sei guadagnato da bere :) – tabaluga

+0

Questo è davvero fantastico, ho iniziato a perdere la sanità mentale mentre stavo cercando di stampare/puts/p self alla fine del callback metodo e si rese conto che facendo ciò sarebbe tornato nil che avrebbe fatto esplodere la richiamata. sospira! Grazie! –

0

per favore prova:

def check_done 
    if item1 && item2 
    done = true 
    else 
    done = false 
    end 
end 
+0

hmmmm, non funziona :( ma grazie per l'aiuto :) – tabaluga

0

Nel vostro metodo privato, provare

def check_done 
    self.done = (self.item1 && self.item2) ? true : false 
end 
+0

Buhuuu, che non funziona neanche ... ma grazie per i vostri sforzi :) – tabaluga

+0

prova aggiungendo l'auto-riferimento nella soluzione @PeterWong? – Yannis

+1

Il tuo dovrebbe essere equivalente al mio ... Ci dovrebbero essere altri problemi. @tabaluga, 'item1',' item2' è impostato correttamente (vero e falso come previsto). E la colonna 'done' è in valore booleano? o ti dispiacerebbe aggiungere dei registri di debug per vedere se le variabili cambiano come ti aspettavi? – PeterWong

2
before_save { |record| 
    record.done = item1 && item2 
} 
+1

grazie, grazie, grazie – tabaluga

Problemi correlati