Ruby on rails 将变量传递给Rails状态机gem转换

Ruby on rails 将变量传递给Rails状态机gem转换,ruby-on-rails,state-machine,Ruby On Rails,State Machine,是否可以在转换中发送变量?i、 e @car.crash!(:crashed_by => current_user) 我的模型中有回调,但我需要将发起转换的用户发送给它们 after_crash do |car, transition| # Log the car crashers name end 我无法访问当前用户,因为我在模型中,而不是控制器/视图中 在你说之前。。。我知道我知道 不要尝试访问模型中的会话变量 我明白了 然而,无论何时,只要您希望创建一个记录或审核某些内容的回

是否可以在转换中发送变量?i、 e

@car.crash!(:crashed_by => current_user)
我的模型中有回调,但我需要将发起转换的用户发送给它们

after_crash do |car, transition|
  # Log the car crashers name
end
我无法访问当前用户,因为我在模型中,而不是控制器/视图中

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

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

我明白了

然而,无论何时,只要您希望创建一个记录或审核某些内容的回调,那么很可能您想知道是谁导致了它?通常我的控制器里会有一些类似于

@foo.some_method(current_user)

我的Foo模型希望一些用户能够使用某种方法,但是我如何使用状态机gem进行转换呢?

我不认为您可以使用该gem将参数传递给事件,所以您可以尝试将当前用户存储在@car上(暂时),以便您的审计回调可以访问它

内部控制器

@car.driver = current_user
收回

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

或者是类似的东西……)

如果您指的是状态机gem,那么它支持事件的参数

after_crash do |car, transition|
  Log.crash(car: car, crashed_by: 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”

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

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?

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

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

谢谢你,基兰。这基本上就是我最后所做的。由于该属性没有永久性-您是否考虑过如何在不在DB中创建新字段的情况下执行此操作?您可以尝试为:driver添加attr_访问器,但我不确定回调是否会重新加载/使用模型的“fresh”实例(并因此擦除临时变量).巧合的是,我在谷歌搜索中再次遇到了自己的问题,这个答案非常有用。谢谢。我认为这肯定比User.current好,我看到其他人遇到这种问题时会执行。用户交互属于控制器层。这很好,但您必须正确拼写转换。上面的解决方案有一个额外的“s”。要清楚,您可以按照OP显示的方式传递参数,例如
@car.crash!(:crash\u by=>当前用户)
。有一些对话是关于如何理解街区里的论点,以防人们还在读这篇文章。一个新的维护版本的gem似乎可以在。几乎相同的语法等等。我不确定这是否是原文的一个分支。我今天碰巧遇到了这个问题,并将其用于我的最新项目。这是迄今为止最简单、最直接的答案。