2011-07-05 29 views
7

tôi muốn biết cách bạn sử dụng quy trình làm việc hoặc đá quý AASM trong bộ điều khiển nếu bạn muốn cập nhật tất cả thuộc tính, nhưng cũng cần luồng công việc/cuộc gọi lại AASM để kích hoạt đúng cách.thực hành tốt nhất cho đá quý như quy trình làm việc hoặc AASM

hiện nay, tôi sử dụng nó như thế này:

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 

mà không cảm thấy đúng, điều gì sẽ là một giải pháp tốt hơn?

Trả lời

0

Đó là một điều nhỏ nhưng hàm băm trả về 0 nếu điều này không có, vì vậy bạn có thể xóa cuộc gọi hiện tại?

Tôi nhận ra đó không phải là những gì bạn đang yêu cầu, tất nhiên. Một cách khác là đặt một bộ lọc trước vào mô hình và kiểm tra trạng thái của bạn ở đó. Điều đó khiến bộ điều khiển của bạn bị mù với lưu trữ cơ bản về trạng thái của bạn.

Trên một mặt lưu ý, chúng tôi sử dụng AASM ở đây và tôi yêu nó :)

3

tôi thường xác định nhiều hành động có thể xử lý việc chuyển đổi từ một tiểu bang khác và có tên rõ ràng. Trong trường hợp của bạn tôi sẽ đề nghị bạn thêm một hành động publish:

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 

Khai báo rằng trong routes.rb của bạn:

resources :stories do 
    member do 
    put :publish 
    end 
end 

Bây giờ con đường của bạn phản ánh chính xác những gì xảy ra với một câu chuyện: /stories/1234/publish

+0

lưu ý rằng trong trường hợp này, bạn có thể không có một sự chuyển đổi từ trạng thái "x" để " được xuất bản "và AASM sẽ tăng ngoại lệ. Nếu không, âm thanh hợp lý. Boy, tôi là một người sáng lập nitpicker sáng nay: P – jaydel

+1

Phải, đây là mã giả. Điều này chỉ có nghĩa là minh họa một mô hình chung. – Wukerplank

0

tôi muốn mô hình của tôi để trả về trạng thái mới sau khi được cập nhật, và đây là cách dễ nhất tôi có thể nghĩ để làm điều này mà không cần nhiều "chất béo" trong bộ điều khiển, và dễ dàng hơn nếu tiến trình công việc của bạn thay đổi:

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

Bạn có thể ghi đè lên các mô hình aasm_state setter (hoặc trạng thái trong ví dụ của tôi) để nó có thể chấp nhận tên sự kiện. Sau đó, chúng tôi kiểm tra xem đó có phải là sự kiện hợp lệ không, sau đó kiểm tra xem liệu quá trình chuyển đổi có hợp lệ hay không. Nếu họ không phải là chúng tôi thêm thông báo lỗi chính xác.

Một yêu cầu đặc tả

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 

Mô hình

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 
Các vấn đề liên quan