2010-09-16 9 views
5

Estoy tratando de entender las devoluciones de llamadas de registro activo, pero no funcionan, como quiero.¿Cómo configuro atributos en un objeto ActiveRecord antes de guardarlo?

p. Ej.

Modelo

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 

esto no funciona si una instancia de un objeto en la consola y tratar de guardarlo, la operación de almacenamiento devuelve "falso" :(

Qué le pasa a este código? gracias de antemano :)

EDIT: parece que hay algo mal con la llamada "before_save", si uso "after_save", el código funciona ... pero el atributo no se guarda (obviamente) Eso es realmente extraño

EDIT 2 Extraño ... los registros de desarrollo muestra este

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 

pero que es realmente extraño, porque si se quita la línea attr_accessible Yo todavía sale este error ...

EDITAR 3 Si alguien pregunta, sí, yo estoy tratando de actualizar una existente registro.

EDITAR 4 Sí, me gusta editar Si escribo en la consola

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

¿Por qué quiere decir con esto no funciona, ¿cuáles son los errores? Puede comprobar llamando a yourobject.errors después de yourobject.save – Mike

+0

oh, está bien Tengo este myobject.errors # tabaluga

+0

¿Qué tal 'myobject.errors.inspect' ?? – PeterWong

Respuesta

8

El problema con su devolución de llamada es que devuelve false si item1 o item2 son falsos.

De la documentación Active Record Callbacks:

Si el valor de retorno de una devolución de llamada before_validation se puede evaluar a false, el proceso se abortará y Base#save regresará false.

La solución es simple; true volver al final de su devolución de llamada, así:

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

gracias, gracias, gracias! Por cierto. a todos ustedes si van a venir a Berlín, déjenme una línea, ganaron una bebida :) – tabaluga

+0

Esto es realmente genial, comencé a perder la cordura cuando estaba tratando de imprimir/poner/p auto al final de la devolución de llamada método y se dio cuenta de que hacerlo devolvería nada, lo que haría estallar la devolución de llamada. suspira! ¡Gracias! –

0

Por favor, intente:

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

hmmmm, no funciona :( pero gracias por ayudar :) – tabaluga

0

En el método privado, trate

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

Buhuuu, eso tampoco funciona ... pero gracias por su esfuerzo :) – tabaluga

+0

¿Usted? intente agregar la referencia automática en la solución @PeterWong? – Yannis

+1

El tuyo debería ser equivalente al mío ... Debería haber otros problemas. @tabaluga, ¿'item1',' item2' está configurado correctamente (verdadero y falso como esperaba). ¿Y la columna 'done' está en valor booleano? o ¿te importaría agregar algunos registros de depuración para ver si las variables cambian como esperabas? – PeterWong

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

gracias, gracias, gracias – tabaluga

Cuestiones relacionadas