2014-10-31 47 views
2

假設有4個州檢查狀態是否經過了aasm中的另一個狀態?

:new 
:in_process 
:done 
:verified 

還有當對象是比:in_process

我如何去這樣做檢查更大的狀態只應被執行對象的方法?我認爲這可能是

def some_action 
    return unless my_object.state > :in_process 
    #do some work 
end 

但這只是比較字符串。

我是否錯過了某些東西或者是否有執行此類檢查的實際方法?

謝謝。

回答

0

這裏的問題是您沒有在狀態機內部進行訂購。您需要提供並聲明一個。

我會堅持這種解決方案:(!按順序)

  1. 先聲明模型中的常數,包含狀態,所以: STATES = [:new, :in_process, :done, :verified]

  2. 後來,你的模型裏面:

 

def current_state_index 
    return state_index(self.state) 
end 

def state_index(state) 
    return STATES.index(state) 
end 

def some_action 
    return unless current_state_index > state_index(:in_process) 
    #do some work end 
end 
+0

有趣的解決方案。我認爲它適用於我的特殊情況,但有一些事情需要考慮。 1)你複製了州申報的地方;一次在aasm聲明中,另一次在數組中。 2)狀態機可能有多個「分支」,這只是一個分支情況。 – 2014-11-03 14:37:14

+0

1)是 - 我知道這一點,但是您需要以某種方式聲明訂單。 2)有分支時,可能會出現一些狀態實際上沒有可比性。考慮這個:http://faculty.kutztown.edu/rieksts/225/study/spring07/test3-ans_files/image006.jpg哪個元素大8或6?其實 - 我們不知道。我認爲在這裏需要假設線性排序來考慮這個問題。 – Esse 2014-11-03 23:56:06

2

忽略非線性狀態機的問題,我發現以下很好地滿足我的需要的幾個項目,簡單的狀態機工作:

# 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」僅僅是一個數組,其階段按從初始到最終的順序排列。

我們只是從列表中刪除項目,然後檢查我們的對象的當前舞臺是否在我們的結果列表中。如果我們想知道它是在某個階段還是在某個階段之前,我們會移除後續階段,直到達到我們提供的測試階段,如果我們想知道它是否在給定階段之後,我們會從列表的前面移除項目。

我知道你可能不需要這個答案了,但希望它可以幫助別人=]

0

如果一個負責在AASM定義正確的順序並確保重寫任何狀態(以例如指定額外的選項),可以使用它們。

以下mixin定義的範圍如Model.done_or_beforeModel.in_process_or_after以及m.done_or_before?等方法。

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_linearity.rbinclude AASMLinearityinclude AASM後,但的statemachine定義之前。