ruby-on-rails - validates - ruby callbacks
Rails 3: ¿Debería guardar explícitamente un objeto en una devolución de llamada after_create? (1)
Esto parece una tarea para before_create
para mí. Si tiene que guardar en su devolución de llamada after_*
, es probable que desee utilizar una devolución de llamada before_*
lugar.
En before_create
no before_create
que llamar a save
, ya que el guardado ocurre después de que el código de devolución de llamada se ejecute por ti.
Y en lugar de guardar y luego consultar para ver si obtienes 2 o más objetos, deberías consultar un objeto que chocará antes de guardar.
En código psuedo, lo que tienes ahora:
after creation
now that I''m saved, find all tasks in my room and at my time
did I find more than one?
Am I the first one?
yes: add note about another task, then save again
no: everything is fine, no need to re-save any edits
Lo que deberías tener:
before creation
is there at least 1 task in this room at the same time?
yes: add note about another task
no: everything is fine, allow saving without modification
Algo más como esto:
before_create :check_room_schedule
def check_room_schedule
conflicting_task = Task.for_date(self.day)
.for_room(self.room)
.where(begin: self.begin) # unsure what logic you need here...
.first
if conflicting_task
self.notes =
"There is another meeting in this room beginning at #{conflicting_task.begin.strftime("%I:%M%P")}."
end
end
Código relevante: http://pastebin.com/EnLJUJ8G
class Task < ActiveRecord::Base
after_create :check_room_schedule
...
scope :for_date, lambda { |date| where(day: date) }
scope :for_room, lambda { |room| where(room: room) }
scope :room_stats, lambda { |room| where(room: room) }
scope :gear_stats, lambda { |gear| where(gear: gear) }
def check_room_schedule
@tasks = Task.for_date(self.day).for_room(self.room).list_in_asc_order
@self_position = @tasks.index(self)
if @tasks.length <= 2
if @self_position == 0
self.notes = "There is another meeting in
this room beginning at # {@tasks[1].begin.strftime("%I:%M%P")}."
self.save
end
end
end
private
def self.list_in_asc_order
order(''begin asc'')
end
end
Estoy haciendo una pequeña aplicación de tareas. Cada tarea está asignada a una habitación. Una vez que agregue una tarea, quiero utilizar una devolución de llamada para verificar si hay tareas en la misma sala antes y después de la tarea que acabo de agregar (aunque mi código solo maneja un caso marginal en este momento).
Así que decidí usar after_create (ya que el usuario lo comprobará manualmente si lo editan, por lo tanto no after_save) para poder usar dos ámbitos y un método de clase para consultar las tareas del día, en la sala, y ordenarlas por hora. Luego encuentro el objeto en la matriz y empiezo a usar sentencias if.
Tengo que guardar explícitamente el objeto. Funciona. Pero se siente raro que estoy haciendo eso. No tengo demasiada experiencia (primera aplicación), así que no estoy seguro de si esto está mal visto o si es convencional. He buscado un montón y he revisado un libro de referencia, pero no he visto nada tan específico.
Gracias.