5

I'm using http://github.com/geekq/workflow to provide a state machine. I'm using ActiveRecord to save state, which means I have a "workflow_state" attribute in the model. I think I want a named_scope for each event in the state machine, so I can find all objects in a given state. For example, assuming a very simple state machine:

workflow do
  state :new do
    event :time_passes, :transitions_to => :old
  end
  state :old do
    event :death_arrives, :transitions_to => :dead
  end
  state :dead
end

I want named scopes for each state. However, that's not DRY... What I want to end up with is something like:

named_scope :new, :conditions => ['workflow_state = ?', 'new']
named_scope :old, :conditions => ['workflow_state = ?', 'old']
named_scope :dead, :conditions => ['workflow_state = ?', 'dead']

But with a few lines that don't depend on the current list of states.

I can see that Model#workflow_spec.states.keys gives me each state. But what I think I need is a wierd lambda where the name of the scope is a variable. And I have no idea how to do that. At all. Been staring at this for hours and playing with irb, but I think there's a piece of knowledge about metaprogramming that I just don't have. Help, please!

Lucas, below, gives the answer - but we also need to change a symbol to a string:

  workflow_spec.states.keys.each do |state|
     named_scope state, :conditions => ['workflow_state = ?', state.to_s] 
  end
JezC
  • 1,868
  • 17
  • 19

2 Answers2

3

Try something like this on the top of your class body

workflow_spec.states.keys.each do |state|
   named_scope state, :conditions => ['workflow_state = ?', state] 
end
Harish Shetty
  • 64,083
  • 21
  • 152
  • 198
Lucas
  • 1,190
  • 8
  • 13
  • Minor tweak and that seems to work. And not a lambda in sight: workflow_spec.states.keys.each do |state| named_scope state, :conditions => ['workflow_state = ?', state.to_s] end Thanks! – JezC Feb 03 '10 at 20:22
0

Scopes are now by default supported by the gem itself. Now it adds automatically generated scopes with names based on states names:

class Order < ActiveRecord::Base
  include Workflow
  workflow do
    state :approved
    state :pending
    state :clear
  end
end

# returns all orders with `approved` state
Order.with_approved_state

# returns all orders with `pending` state
Order.with_pending_state

# returns all orders with `clear` state
Order.with_clear_state

Source: https://github.com/geekq/workflow

Shiva
  • 11,485
  • 2
  • 67
  • 84