Ruby on rails 检查状态是否超过aasm中的另一个状态?

Ruby on rails 检查状态是否超过aasm中的另一个状态?,ruby-on-rails,aasm,Ruby On Rails,Aasm,假设有一个具有4种状态的对象 :new :in_process :done :verified 还有一种方法,仅当对象处于大于:in_process 我该怎么做这张支票?我想可能是什么 def some_action return unless my_object.state > :in_process #do some work end 但这只是比较字符串 我是否遗漏了什么,或者是否有一种实际的方式来执行这样的检查 谢谢。这里的问题是您在状态机中没有订单。您需要提供并声明一个

假设有一个具有4种状态的对象

:new
:in_process
:done
:verified
还有一种方法,仅当对象处于大于
:in_process

我该怎么做这张支票?我想可能是什么

def some_action
  return unless my_object.state > :in_process
  #do some work
end
但这只是比较字符串

我是否遗漏了什么,或者是否有一种实际的方式来执行这样的检查


谢谢。

这里的问题是您在状态机中没有订单。您需要提供并声明一个

我会坚持这个解决方案:

  • 首先在模型中声明常量,包含状态(按顺序!),因此:
    状态=[:新建,:正在处理,:完成,:已验证]

  • 稍后,在您的模型中:


  • 忽略非线性状态机的问题,我发现在一些使用简单状态机的项目中,以下内容可以很好地满足我的需求:

    # Check if the stage is in or before the supplied stage (stage_to_check).
    def in_or_before_stage?(stage_to_check)
      if stage_to_check.present? && self.stage.present?
        STAGES_IN_ORDER.reverse.lazy.drop_while { |stg| stg != stage_to_check }.include?(self.stage)
      else
        false
      end
    end
    
    有时也需要另一种检查:

    # Check if the stage is in or after the supplied stage (stage_to_check).
    def in_or_after_stage?(stage_to_check)
      if stage_to_check.present? && self.stage.present?
        # Get all the stages that are in and after the stage we want to check (stage_to_check),
        # and then see if the stage is in that list (well, technically in a lazy enumerable).
        STAGES_IN_ORDER.lazy.drop_while { |stg| stg != stage_to_check }.include?(self.stage)
      else
        false
      end
    end
    
    其中“STAGES_IN_ORDER”只是一个数组,其中STAGES的顺序从初始到最终

    我们只是从列表中删除项目,然后检查对象的当前阶段是否在结果列表中。如果我们想知道它是在某个阶段中还是在某个阶段之前,我们将删除后面的阶段,直到我们到达提供的测试阶段;如果我们想知道它是在某个给定阶段之后,我们将从列表的前面删除项


    我意识到您可能不再需要这个答案,但希望它能帮助其他人=]

    如果您注意在AASM中定义正确的顺序,并确保不覆盖任何状态(例如,指定额外选项),则可以使用它们

    下面的mixin定义了
    Model.done\u或
    之前的和
    Model.in\u或
    之后的等范围,以及
    m.done\u或
    之前的方法

    module AASMLinearity
      def self.included(base)
        base.extend(ClassMethods)
      end
    
      module ClassMethods
        def aasm(*args, &block)
          r = super(*args, &block)
          if block
            states = r.state_machine.states.map(&:name)
            column = r.attribute_name
            states.each_with_index do |state, i|
              scope "#{state}_or_after", ->{ where(column => states[i..-1]) }
              scope "#{state}_or_before", ->{ where(column => states[0..i]) }
    
              define_method "#{state}_or_after?", ->{ states[i..-1].include? read_attribute(column).to_sym }
              define_method "#{state}_or_before?", ->{ states[0..i].include? read_attribute(column).to_sym }
            end
          end
          r
        end
      end
    end
    

    您可以将其放入类似于
    app/models/concerns/aasm_linear.rb
    ,以及
    包含AASMLinearity
    之后,但在状态机定义之前。

    有趣的解决方案。我认为这将对我的特定情况起作用,但也有一些事情要考虑。1) 你在复制州的声明;一次在aasm声明中,另一次在数组中。2) 一个状态机可能有多个“分支”,这仅仅说明了一个分支的情况。1)是的-我知道这一点,但是您需要以某种方式声明顺序。2) 当存在分支时,可能会出现一些实际上不可比较的状态。考虑一下:哪一个元素大8或6?事实上,我们不知道。我相信这里需要线性排序假设,甚至考虑这样的问题。
    module AASMLinearity
      def self.included(base)
        base.extend(ClassMethods)
      end
    
      module ClassMethods
        def aasm(*args, &block)
          r = super(*args, &block)
          if block
            states = r.state_machine.states.map(&:name)
            column = r.attribute_name
            states.each_with_index do |state, i|
              scope "#{state}_or_after", ->{ where(column => states[i..-1]) }
              scope "#{state}_or_before", ->{ where(column => states[0..i]) }
    
              define_method "#{state}_or_after?", ->{ states[i..-1].include? read_attribute(column).to_sym }
              define_method "#{state}_or_before?", ->{ states[0..i].include? read_attribute(column).to_sym }
            end
          end
          r
        end
      end
    end