2011-11-20 19 views
10

Uso state_machine con ActiveRecord en una de las aplicaciones de mi Rails 3.1. Encontré la sintaxis para acceder a los registros con diferentes estados para ser engorroso. ¿Es posible definir cada estado como el alcance al mismo tiempo sin escribir definiciones de alcance a mano?Ámbitos con nombre para estados en state_machine

Considerar siguiente ejemplo:

class User < ActiveRecord:Base 
    state_machine :status, :initial => :foo do 
    state :foo 
    state :bar 

    # ... 
    end 
end 

# state_machine syntax: 
User.with_status :foo 
User.with_status :bar 

# desired syntax: 
User.foo 
User.bar 

Respuesta

2

También necesitaba esta funcionalidad, pero state_machine no tiene nada similar. Aunque encontré esto gist, pero aasm parece una mejor alternativa de máquina de estado en este caso.

+0

Gracias, esto es útil en esencia. Encontré que la gema 'state_machine' es mejor en mi caso, excepto este problema con los ámbitos. – Andrew

16

estoy añadiendo lo siguiente a mis modelos:

state_machine.states.map do |state| 
    scope state.name, :conditions => { :state => state.name.to_s } 
end 

No está seguro de si se cuenta esto como "escritura definición del alcance de la mano?"

+0

Tenga en cuenta que este código Lars debe agregarse después del bloque state_machine. – tomaszbak

8

Por si acaso, si alguien todavía está buscando esto, no están siguiendo métodos añaden mientras se define state_machine:

class Vehicle < ActiveRecord::Base 
    named_scope :with_states, lambda {|*states| {:conditions => {:state => states}}} 
    # with_states also aliased to with_state 

    named_scope :without_states, lambda {|*states| {:conditions => ['state NOT IN (?)', states]}} 
    # without_states also aliased to without_state 
end 

# to use this: 
Vehicle.with_state(:parked) 

me gusta usar esto porque nunca habrá conflicto con el nombre del estado. Puede encontrar más información en state_machine's ActiveRecord integration page.

ventaja es que permite pasar matriz de modo que hago a menudo algo como:

scope :cancelled, lambda { with_state([:cancelled_by_user, :cancelled_by_staff]) } 
+0

El OP ya lo sabe. Él está preguntando si puede crear diferentes ámbitos con nombre: 'Vehicle.parked' en lugar de' Vehicle.with_state (: estacionado) '. –

+0

thnx para bonificación))) eso es todo! – cubbiu

+0

Tenga en cuenta que en Rails 3, named_scope ha cambiado de nombre a scope. – cubbiu

0

te mostraré una manera que puede ser utilizado si el modelo tiene múltiples state_machines también.

Funciona incluso en el caso en que sus estados sean enteros.

def Yourmodel.generate_scopes_for_state_machines state_machines.each_pair do |machine_name, that_machine| 
    that_machine.states.map do |state| 
     # puts "will create these scopes: #{machine_name}_#{state.name} state: #{state.value} " 
     # puts "will create these scopes: #{machine_name}_#{state.name} state: #{state.name.to_s} " 
     # Price.scope "#{machine_name}_#{state.name}", :conditions => { machine_name => state.name.to_s } 
     Price.scope "#{machine_name}_#{state.name}", :conditions => { machine_name => state.value } 
    end end end 

Yourmodel.generate_scopes_for_state_machines 
Cuestiones relacionadas