2011-07-05 1 views
7

모든 속성을 업데이트하려는 경우 사용자가 워크 플로우 또는 컨트롤러에서 AASM 젬을 사용하는 방법을 알고 싶을뿐만 아니라 제대로 작동하려면 워크 플로/AASM 콜백이 필요합니다.워크 플로우 또는 AASM과 같은 보석에 대한 우수 사례

현재, 나는 다음과 같이 사용 : 느낌이 좋지 않습니다

class ModelController < ApplicationController 
    def update 
     @model = model.find(params[:id]) 

     if params[:application]['state'].present? 
     if params[:application]['state'] == "published" 
      @model.publish! 
     end 
     end 
     if @model.update_attributes(params[:application]); ... end 
    end 
    end 

는, 무엇을 더 나은 해결책이 될 것인가?

답변

0

물건이 없으면 작은 것이지만 해시 리턴은 없으므로 전화를 끊을 수 있습니까?

나는 그것이 당신이 묻고있는 것이 아니라는 것을 알고 있습니다. 한 가지 대안은 모델에 필터를 넣고 상태를 확인하는 것입니다. 이로 인해 귀하의 컨트롤러는 귀하의 상태가 저장되는 기본 저장 장치에 눈이 멀게됩니다. 보조 노트에

, 우리는 여기에 AASM를 사용하고 나는 내가 보통 한 상태에서 다른 상태로의 전환을 처리하고 명시 적으로 이름이 여러 작업을 정의

3

을 :) 사랑 해요.

def publish 
    # as the comment below states: your action 
    # will have to do some error catching and possibly 
    # redirecting; this goes only to illustrate my point 
    @story = Story.find(params[:id]) 
    if @story.may_publish? 
    @story.publish! 
    else 
    # Throw an error as transition is not legal 
    end 
end 

routes.rb에서 그 선언 : /stories/1234/publish

+0

참고

it "should cancel" do put "/api/ampaigns/#{@campaign.id}", {campaign: {status: "cancel"}, format: :json}, valid_session response.code.should == "204" end 

출판 "하고 AASM은 예외를 제기 할 것입니다. 그렇지 않으면 합리적으로 들립니다. 오늘 아침에 니키 피커 야. – jaydel

+1

이건 의사 코드 야. 이것은 일반적인 패턴을 설명하기위한 것입니다. – Wukerplank

0

내가 원하는 :

resources :stories do 
    member do 
    put :publish 
    end 
end 

이제 경로는 이야기를 어떻게 정확하게 반영하고 귀하의 경우에는 난 당신이 publish 작업을 추가 제안 내 모델을 업데이트 한 후 새 상태로 되돌릴 수 있습니다. 컨트롤러에서 "뚱뚱한"작업없이이 작업을 수행 할 수있는 가장 쉬운 방법이었으며 워크 플로가 변경되면 앞으로 나아갈 수 있습니다.

class Article < ActiveRecord::Base 
    include Workflow 
    attr_accessible :workflow_state, :workflow_event # etc 
    validates_inclusion_of :workflow_event, in: %w(submit approve reject), allow_nil: true 
    after_validation :send_workflow_event 

    def workflow_event 
    @workflow_event 
    end 

    def workflow_event=(workflow_event) 
    @workflow_event = workflow_event 
    end 

    # this method should be private, normally, but I wanted to 
    # group the meaningful code together for this example 
    def send_workflow_event 
    if @workflow_event && self.send("can_#{@workflow_event}?") 
     self.send("#{@worklow_event}!") 
    end 
    end 

    # I pulled this from the workflow website, to use that example instead. 
    workflow do 
    state :new do 
     event :submit, :transitions_to => :awaiting_review 
    end 
    state :awaiting_review do 
     event :review, :transitions_to => :being_reviewed 
    end 
    state :being_reviewed do 
     event :accept, :transitions_to => :accepted 
     event :reject, :transitions_to => :rejected 
    end 
    state :accepted 
    state :rejected 
    end 
end 
2

aasm_state setter (또는 예제에서는 상태) 모델을 덮어 쓰면 이벤트 이름을 사용할 수 있습니다. 그런 다음 유효한 이벤트인지 확인한 다음 전환이 유효한지 확인합니다. 일치하지 않으면 올바른 오류 메시지를 추가합니다.

요청 스펙이 경우에 당신이 "에 상태"X "에서 전환을하지 않을 수도 있다는 모델 사양

it "should invoke the cancel method" do 
    campaign.update_attribute(:status, "cancel") 
    campaign.canceled?.should be_true 
end 
it "should add an error for illegal transition" do 
    campaign.update_attribute(:status, "complete") 
    campaign.errors.should include :status 
    campaign.errors[:status].should == ["status cannot transition from pending to complete"] 
end 
it "should add an error for invalid status type" do 
    campaign.update_attribute(:status, "foobar") 
    campaign.errors.should include :status 
    campaign.errors[:status].should == ["status of foobar is not valid. Legal values are pending, active, canceled, completed"] 
end 

모델은

class Campaign < ActiveRecord::Base 
    include AASM 
    aasm column: :status do 
    state :pending, :initial => true 
    state :active 
    state :canceled 
    state :completed 
    # Events 
    event :activate do 
     transitions from: :pending, to: :active 
    end 
    event :complete do 
     transitions from: :active, to: [:completed] 
    end 
    event :cancel do 
     transitions from: [:pending, :active], to: :canceled 
    end 
    end 
    def status=(value) 
    if self.class.method_defined?(value) 
     if self.send("may_#{value}?") 
     self.send(value) 
     else 
     errors.add(:status, "status cannot transition from #{status} to #{value}") 
     end 

    else 
     errors.add(:status, "status of #{value} is not valid. Legal values are #{aasm.states.map(&:name).join(", ")}") 
    end 
    end 
end