将变量传递给 Rails StateMachine gem 转换

发布于 2024-09-15 10:06:41 字数 552 浏览 8 评论 0原文

是否可以在转换中发送变量?即

@car.crash!(:crashed_by => current_user)

我的模型中有回调,但我需要向它们发送发起转换的用户

after_crash do |car, transition|
  # Log the car crashers name
end

,我无法访问 current_user,因为我位于模型中而不是控制器/视图中。

在你说之前……我知道我知道。

不要尝试访问模型中的会话变量

我明白了。

但是,每当您希望创建一个记录或审核某些内容的回调时,您很可能想知道是谁造成的?通常我的控制器中有一些东西可以做类似的事情......

@foo.some_method(current_user)

并且我的 Foo 模型会期望一些用户发起 some_method 但我如何通过 StateMachine gem 的转换来做到这一点?

Is it possible to send variables in the the transition? i.e.

@car.crash!(:crashed_by => current_user)

I have callbacks in my model but I need to send them the user who instigated the transition

after_crash do |car, transition|
  # Log the car crashers name
end

I can't access current_user because I'm in the Model and not the Controller/View.

And before you say it... I know I know.

Don't try to access session variables in the model

I get it.

However, whenever you wish to create a callback that logs or audits something then it's quite likely you're going to want to know who caused it? Ordinarily I'd have something in my controller that did something like...

@foo.some_method(current_user)

and my Foo model would be expecting some user to instigate some_method but how do I do this with a transition with the StateMachine gem?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

避讳 2024-09-22 10:06:41

如果您指的是 state_machine gem - https://github.com/pluginaweek/state_machine - 那么它支持事件参数

after_crash do |car, transition|
  Log.crash(car: car, crashed_by: transition.args.first)
end

If you are referring to the state_machine gem - https://github.com/pluginaweek/state_machine - then it supports arguments to events

after_crash do |car, transition|
  Log.crash(car: car, crashed_by: transition.args.first)
end
缘字诀 2024-09-22 10:06:41

我对所有其他答案都遇到了麻烦,然后我发现您可以简单地覆盖类中的事件。

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”

I was having trouble with all of the other answers, and then I found that you can simply override the event in the class.

class Car
  state_machine do
    ...
    event :crash do
      transition any => :crashed
    end
  end
  def crash(current_driver)
    logger.debug(current_driver)
    super
  end
end

Just make sure to call "super" in your custom method

╭ゆ眷念 2024-09-22 10:06:41

我认为您无法使用该 gem 将参数传递给事件,因此也许您可以尝试将 current_user (暂时)存储在 @car 上,以便您的审核回调可以访问它。

在控制器中

@car.driver = current_user

在回调中

after_crash do |car, transition|
   create_audit_log car.driver, transition
end

或者类似的东西..:)

I don't think you can pass params to events with that gem, so maybe you could try storing the current_user on @car (temporarily) so that your audit callback can access it.

In controller

@car.driver = current_user

In callback

after_crash do |car, transition|
   create_audit_log car.driver, transition
end

Or something along those lines.. :)

暮色兮凉城 2024-09-22 10:06:41

我使用事务,而不是在一次调用中更新对象并更改状态。例如,在更新操作中,

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

I used transactions, instead of updating the object and changing the state in one call. For example, in update action,

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
清晨说晚安 2024-09-22 10:06:41

另一种常见模式(请参阅 state_machine 文档)可以让您不必在控制器和模型之间传递变量:在回调方法中动态定义状态检查方法。在上面给出的示例中,这不是很优雅,但在模型需要在不同状态下处理相同变量的情况下可能更可取。例如,如果您的汽车模型中有“崩溃”、“被盗”和“借用”状态,所有这些状态都可以与负责人关联,您可以:

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?

Another common pattern (see the state_machine docs) that saves you from having to pass variables between the controller and model is to dynamically define a state-checking method within the callback method. This wouldn't be very elegant in the example given above, but might be preferable in cases where the model needs to handle the same variable(s) in different states. For example, if you have 'crashed', 'stolen', and 'borrowed' states in your Car model, all of which can be associated with a responsible Person, you could have:

state :crashed, :stolen, :borrowed do
  def blameable?
    true
  end

state all - [:crashed, :stolen, :borrowed] do
  def blameable?
    false
  end

Then in the controller, you can do something like:

car.blame_person(person) if car.blameable?
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文