将变量传递给Rails StateMachine gem过渡
是否可以在转换中发送变量? 即
@car.crash!(:crashed_by => current_user)
我在我的模型中有回调,但我需要向他们发送启动过渡的用户
after_crash do |car, transition| # Log the car crashers name end
我无法访问current_user,因为我在模型中而不是Controller / View。
在你说之前……我知道我知道。
不要尝试访问模型中的会话变量
我知道了。
但是,每当您希望创建一个记录或审核某些内容的回调时,您很可能想知道是谁造成的? 通常,我的控制器中有一些东西像…
@foo.some_method(current_user)
我的Foo模型会期望一些用户发起some_method但是我如何通过StateMachine gem转换呢?
如果您指的是state_machine gem – https://github.com/pluginaweek/state_machine – 那么它支持事件的参数
after_crash do |car, transition| Log.crash(:car => car, :driver => transition.args.first) end
我遇到了所有其他答案的麻烦,然后我发现你可以简单地覆盖课堂上的事件。
class Car state_machine do ... event :crash do transition any => :crashed end end def crash(current_driver) logger.debug(current_driver) super end end
只需确保在自定义方法中调用“super”
我不认为您可以将params传递给具有该gem的事件,因此您可以尝试将current_user存储在@car(临时)上,以便您的审计回调可以访问它。
在控制器中
@car.driver = current_user
在回调中
after_crash do |car, transition| create_audit_log car.driver, transition end
或类似的规定.. :)
我使用了事务,而不是更新对象并在一次调用中更改状态。 例如,在更新操作中,
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
另一种常见模式(参见state_machine文档 )可以使您不必在控制器和模型之间传递变量,这是在回调方法中动态定义状态检查方法。 在上面给出的示例中,这不会非常优雅,但在模型需要处理不同状态的相同变量的情况下可能更为优雅。 例如,如果您的Car模型中有“崩溃”,“被盗”和“借入”状态,所有这些状态都可以与负责人联系在一起,您可以:
state :crashed, :stolen, :borrowed do def blameable? true end state all - [:crashed, :stolen, :borrowed] do def blameable? false end
然后在控制器中,您可以执行以下操作:
car.blame_person(person) if car.blameable?