ruby on rails - Pasando variables a las transiciones de gemas de Rails StateMachine
ruby-on-rails state-machine (5)
Estaba teniendo problemas con todas las otras respuestas, y luego descubrí que simplemente puede anular el evento en la clase.
class Car
state_machine do
...
event :crash do
transition any => :crashed
end
end
def crash(current_driver)
logger.debug(current_driver)
super
end
end
Solo asegúrate de llamar "super" en tu método personalizado
¿Es posible enviar variables en la transición? es decir
@car.crash!(:crashed_by => current_user)
Tengo devoluciones de llamada en mi modelo pero debo enviarles el usuario que instigó la transición
after_crash do |car, transition|
# Log the car crashers name
end
No puedo acceder a current_user porque estoy en el Modelo y no en el Controlador / Vista.
Y antes de que lo digas ... Lo sé, lo sé.
No intente acceder a las variables de sesión en el modelo
Lo entiendo.
Sin embargo, siempre que desee crear una devolución de llamada que registre o audite algo, es muy probable que desee saber quién lo causó. Normalmente tendría algo en mi controlador que hizo algo como ...
@foo.some_method(current_user)
y mi modelo Foo estaría esperando que algún usuario instigara algún método, pero ¿cómo hago esto con una transición con la gema StateMachine?
No creo que pueda pasar parámetros a los eventos con esa gema, así que tal vez podría intentar almacenar current_user en @car (temporalmente) para que su devolución de llamada de auditoría pueda acceder a él.
En el controlador
@car.driver = current_user
En devolución de llamada
after_crash do |car, transition|
create_audit_log car.driver, transition
end
O algo por el estilo.. :)
Otro patrón común (consulte los https://github.com/pluginaweek/state_machine ) que le evita tener que pasar variables entre el controlador y el modelo es definir dinámicamente un método de verificación de estado dentro del método de devolución de llamada. Esto no sería muy elegante en el ejemplo anterior, pero podría ser preferible en los casos en que el modelo necesite manejar las mismas variables en diferentes estados. Por ejemplo, si tiene los estados ''estrellados'', ''robados'' y ''prestados'' en su modelo de Coche, todos los cuales pueden estar asociados con una Persona responsable, podría tener:
state :crashed, :stolen, :borrowed do
def blameable?
true
end
state all - [:crashed, :stolen, :borrowed] do
def blameable?
false
end
Luego en el controlador, puedes hacer algo como:
car.blame_person(person) if car.blameable?
Si se está refiriendo a la gema state_machine - https://github.com/pluginaweek/state_machine - entonces soporta argumentos para eventos
after_crash do |car, transition|
Log.crash(:car => car, :driver => transition.args.first)
end
Utilicé transacciones, en lugar de actualizar el objeto y cambiar el estado en una llamada. Por ejemplo, en la acción de actualización,
ActiveRecord::Base.transaction do
if @car.update_attribute!(:crashed_by => current_user)
if @car.crash!()
format.html { redirect_to @car }
else
raise ActiveRecord::Rollback
else
raise ActiveRecord::Rollback
end
end