Ruby on rails 转换上的状态机验证

Ruby on rails 转换上的状态机验证,ruby-on-rails,ruby-on-rails-3,state-machine,Ruby On Rails,Ruby On Rails 3,State Machine,使用状态机gem,我希望验证只在转换上运行。例如: # Configured elsewhere: # StateMachine::Callback.bind_to_object = true class Walrus > ActiveRecord::Base state_machine :life_cycle, :initial => :fetus do state :fetus state :child state :adult state

使用状态机gem,我希望验证只在转换上运行。例如:

# Configured elsewhere:
# StateMachine::Callback.bind_to_object = true

class Walrus > ActiveRecord::Base
  state_machine :life_cycle, :initial => :fetus do
    state :fetus
    state :child
    state :adult
    state :dead

    event :coming_of_age do
      transition :child => :adult
    end


    before_transition :child => :adult do
      validate :coming_of_age_party_in_the_future
    end
  end
end
如果我将该验证附加到成人状态,那么一旦该日期过去,它将失败。但我只需要它在转换期间有效。我可以补充如下内容:

validate :coming_of_age_party_in_the_future, if: 'adult? && life_cycle_was == "child"'
但这似乎没有抓住转型的关键


另外,由于我在回调中绑定到对象,它如何有条件地调用类方法“validate”?(由于回调中的许多方法都是私有的,所以绑定是必需的。)

您是否考虑过使用
转换if::x
功能

它应该是这样工作的:

event :coming_of_age do
  transition :child => :adult, if: :coming_of_age_party_in_the_future
end

您可以在

中的“示例”(靠近顶部)中看到“类定义”一节,或者在“语法灵活性”(相当低)中看到“转换上下文”一节,如果我有很多这样的内容怎么办?如果我想验证转换,rails验证器是不可能的吗?看起来是一个很常见的用例,但从技术上来说,它不是。您可以创建一个方法来保存嵌套在case语句中的所有验证,或者按照您提到的方式执行,但是,我假设您希望不允许/阻止转换本身,因此,我主张在转换中使用“保护”逻辑——如果只是出于可读性的原因,那么添加检查转换的自定义方法是否更好?像
life\u cycle\u was==“child”和&成人?
对我来说,验证是为了确保一致性和正确性。一个与持久化数据相关的构造,与其说是对数据和状态机的操作,不如说是转换,尤其是关于操作,所以应该使用它们自己的保护机制。但这是有争议的个人品味。如果条件足够简洁,你可以只做
If:lambda{thing}conditional}