Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Named scopes for states in state_machine

I use state_machine with ActiveRecord on one of my Rails 3.1 application. I found the syntax to access records with different states to be cumbersome. Is it possible to define each state to be the scope at the same time without writing scope definitions by hand?

Consider following example:

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
like image 383
Andrew Avatar asked Nov 20 '11 04:11

Andrew


2 Answers

I'm adding the following to my models:

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

Not sure if you count this as "writing scope definitions by hand?"

like image 78
Lars Haugseth Avatar answered Sep 22 '22 03:09

Lars Haugseth


Just in case, if somebody is still looking for this, there are following methods added while defining 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)

I like to use this because there will never be conflict with state name. You can find more information on state_machine's ActiveRecord integration page.

Bonus is that it allows to pass array so I often do something like:

scope :cancelled, lambda { with_state([:cancelled_by_user, :cancelled_by_staff]) }
like image 34
Lucas Avatar answered Sep 24 '22 03:09

Lucas