2011-07-05 6 views
7

Chciałbym wiedzieć, jak wy korzystacie przepływ pracy lub klejnot AASM w kontrolerze, jeśli chcecie zaktualizować wszystkie atrybuty, ale także potrzebujesz wywołań zwrotnych workflow/AASM do odpalenia prawidłowo.najlepsza praktyka dla klejnotów takich jak workflow lub AASM

obecnie używam go tak:

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 

że nie czuje się dobrze, co byłoby lepszym rozwiązaniem?

Odpowiedz

0

To drobiazg, ale skrót nie ma wartości zerowej, jeśli coś nie jest obecne, więc można usunąć wezwanie do przedstawienia?

Rozumiem, że nie o to pytasz, oczywiście. Jedną z możliwości jest umieszczenie filtru "przed" w modelu i sprawdzenie statusu. To sprawia, że ​​kontroler jest ślepy na podstawowe miejsce przechowywania twojego statusu.

Na marginesie, używamy AASM tutaj i kocham to :)

3

zwykle zdefiniować wiele działań, które zajmują przejścia z jednego stanu do drugiego i mają wyraźne nazwy. W twoim przypadku proponuję dodać publish działania:

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 

deklaruje, że w swojej routes.rb:

resources :stories do 
    member do 
    put :publish 
    end 
end 

Teraz trasa odzwierciedla dokładnie to, co dzieje się z historią: /stories/1234/publish

+0

pamiętać, że w tym przypadku nie może mieć przejścia ze stanu "X" do " opublikowane "i AASM zgłosi wyjątek. W przeciwnym razie brzmi rozsądnie. Chłopie, dziś rano jestem nitpicker: P – jaydel

+1

W porządku, to jest pseudo-kod. Ma to jedynie na celu zilustrowanie ogólnego wzorca. – Wukerplank

0

chciałem mój model, aby przywrócić nowy stan po aktualizacji i był to najłatwiejszy sposób, w jaki mógłbym to zrobić bez zbytniego "tłuszczu" w kontrolerach, a to ułatwiłoby dalsze działanie w przypadku zmiany przepływu pracy:

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

Można zastąpić modele aasm_state Setter (lub stan w moim przykładzie), aby można było akceptować nazwy zdarzeń. Następnie sprawdzamy, czy jest to poprawne zdarzenie, a następnie sprawdzamy, czy przejście jest prawidłowe. Jeśli nie, dodajemy poprawny komunikat o błędzie.

Żądanie Spec

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

Model Spec

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 

Model

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 
Powiązane problemy