Skip to content

Instantly share code, notes, and snippets.

@manishdas
Forked from the-architect/contact.rb
Created September 15, 2011 19:10
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save manishdas/1220175 to your computer and use it in GitHub Desktop.
Save manishdas/1220175 to your computer and use it in GitHub Desktop.
Automatically create scopes for all available state_machine states in Rails 3.1
class Contact < ActiveRecord::Base
state_machine :state, :initial => :imported do
state :imported
state :contacted
state :verified
state :prospect
state :deleted
end
include StateMachineScopes
state_machine_scopes :state
end
module StateMachineScopes
class MethodAlreadyDefinedError < StandardError; end
class StateMachineNotFoundError < StandardError; end
module ClassMethods
def all_states(machine = :state)
state_machines[machine.to_sym].states.keys.sort
end
def state_machine_scopes(*which)
options = which.last.is_a?(Hash) ? which.pop : {}
prefix = options.delete(:prefix)
if which.any?
which.each do |machine_name|
define_scopes_for(machine_name, prefix)
end
else
state_machines.keys.each do |machine_name|
define_scopes_for(machine_name, prefix)
end
end
end
private
def define_scopes_for(machine_name, prefix)
state_machines[machine_name.to_sym].states.keys.each do |state|
scope_name = [prefix, machine_name, state].compact.join('_')
if self.respond_to? scope_name
raise MethodAlreadyDefinedError.new("Already defined method called \"#{scope_name}\"")
end
self.class_eval do
scope :"#{scope_name}", where(:state => state)
end
end
end
end
def self.included(klass)
if klass.respond_to?(:state_machines)
klass.extend(ClassMethods)
else
raise StateMachineNotFoundError.new("\"#{klass.name}\" does not seem to have any state machines.")
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment