ruby-on-rails state-machine

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