2011-07-05 7 views
7

me gustaría saber cómo ustedes utilizar el flujo de trabajo o la gema AASM en el controlador si desea actualizar todos los atributos, sino que también necesitan las devoluciones de llamada AASM de flujo de trabajo/para disparar correctamente.mejor práctica para joyas como flujo de trabajo o AASM

actualmente, lo uso como esto:

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 

que no se siente bien, lo que sería una solución mejor?

Respuesta

0

Es una pequeña cosa, pero un retorno de hash nil si la cosa no está presente, por lo que podría eliminar la llamada a presentar?

que se dan cuenta que no es lo que estás pidiendo, por supuesto. Una alternativa es colocar un filtro de antes en el modelo y verificar allí el estado. Eso deja su controlador ciego al almacenamiento subyacente de su estado.

En una nota lateral, utilizamos AASM aquí y me encanta :)

3

que suelo definir varias acciones que manejar la transición de un estado a otro y tienen nombres explícitos. En su caso le sugiero que se agrega una acción 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 

declarar que en su routes.rb:

resources :stories do 
    member do 
    put :publish 
    end 
end 

Ahora su ruta refleja exactamente lo que ocurre con una historia: /stories/1234/publish

+0

nota que en este caso puede que no tenga una transición del estado "x" a " publicado "y AASM levantará una excepción. De lo contrario, suena razonable. Chico, yo soy un nitpicker esta mañana: P – jaydel

+1

derecho, esto es pseudo-código. Esto solo pretende ilustrar un patrón general. – Wukerplank

0

quería mi modelo para devolver el nuevo estado después de haber sido actualizado, y ésta era la manera más fácil de lo que podía pensar hacer esto sin una gran cantidad de "grasa" de los controladores, y hace que sea más fácil en el futuro si los cambios de flujo de trabajo:

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

puede invalidar el colocador modelos aasm_state (o el estado en mi ejemplo) para que pueda aceptar nombres de eventos. Luego verificamos si es un evento válido y luego verificamos si la transición es válida. Si no lo están, agregamos el mensaje de error correcto.

Una especificación solicitud

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

El modelo 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 

El modelo

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 
Cuestiones relacionadas