Estoy tratando de asignar un número aleatorio a un atributo llamado position antes de que se guarden los objetos de mi Product . No puedo hacer que la devolución de llamada funcione correctamente. No hay errores en la consola, simplemente falla silenciosamente.
Aquí está mi modelo
class Product < ApplicationRecord validates_presence_of :position before_save { assign_position } private def assign_position self.position = rand(150) end endeste es mi esquema
create_table "products", force: :cascade do |t| t.string "name" t.integer "position" endAquí hay una semilla de ejemplo que estoy usando para probar la devolución de llamada antes de guardar.
Product.create(name: "Rose Deep Hydration Facial Toner")No hay errores, pero la salida de la consola cuando compruebo después de crear la semilla
irb(main):079:0> Product.find_by_name("Rose Deep Hydration Facial Toner").position Product Load (1.8ms) SELECT "products".* FROM "products" WHERE "products"."name" = $1 ORDER BY "products"."created_at" DESC LIMIT $2 [["name", "Rose Deep Hydration Facial Toner"], ["LIMIT", 1]] => nilTengo otras devoluciones de llamada en la aplicación que funcionan bien. No puedo entender por qué este no funciona.
Su problema es que las validaciones ocurren antes de que se activen las devoluciones de llamada before_save . Tienes esto:
validates_presence_of :position pero la position seguirá siendo nil cuando se verifique esa validación.
Creo que desea utilizar una devolución de llamada before_validation en lugar de before_save :
class Product < ApplicationRecord before_validation :assign_position validates_presence_of :position private def assign_position self.position = rand(150) end end Tenga en cuenta que se assign_position a la asignación de posición cada vez que valide un Producto, por lo que actualizar un error tipográfico en el nombre (por ejemplo) cambiará la position . Es posible que desee dejar la posición en paz si ya está configurada o si está modificando una instancia existente.