├── init.rb ├── Gemfile ├── examples ├── doc │ ├── css │ │ └── common.css │ ├── Car_state.png │ ├── AutoShop_state.png │ ├── Vehicle_state.png │ ├── TrafficLight_state.png │ ├── frames.html │ ├── file_list.html │ ├── class_list.html │ └── top-level-namespace.html ├── Car_state.png ├── Vehicle_state.png ├── AutoShop_state.png ├── Gemfile ├── TrafficLight_state.png ├── rails-rest │ ├── view_new.html.erb │ ├── view_edit.html.erb │ ├── migration.rb │ ├── view_show.html.erb │ ├── view_index.html.erb │ ├── model.rb │ ├── controller.rb │ └── view__form.html.erb ├── traffic_light.rb ├── Gemfile.lock ├── auto_shop.rb ├── merb-rest │ ├── view_new.html.erb │ ├── view_show.html.erb │ ├── view_index.html.erb │ ├── model.rb │ ├── view_edit.html.erb │ └── controller.rb ├── car.rb └── vehicle.rb ├── lib ├── state_machine │ ├── version.rb │ ├── core_ext.rb │ ├── initializers │ │ ├── merb.rb │ │ └── rails.rb │ ├── core_ext │ │ └── class │ │ │ └── state_machine.rb │ ├── yard │ │ ├── templates.rb │ │ ├── handlers.rb │ │ ├── templates │ │ │ └── default │ │ │ │ └── class │ │ │ │ └── html │ │ │ │ ├── state_machines.erb │ │ │ │ └── setup.rb │ │ └── handlers │ │ │ ├── event.rb │ │ │ ├── state.rb │ │ │ ├── base.rb │ │ │ └── transition.rb │ ├── initializers.rb │ ├── yard.rb │ ├── integrations │ │ ├── mongoid │ │ │ ├── locale.rb │ │ │ └── versions.rb │ │ ├── mongo_mapper │ │ │ ├── locale.rb │ │ │ └── versions.rb │ │ ├── active_model │ │ │ ├── locale.rb │ │ │ ├── versions.rb │ │ │ ├── observer.rb │ │ │ └── observer_update.rb │ │ ├── active_record │ │ │ └── locale.rb │ │ ├── data_mapper │ │ │ └── versions.rb │ │ ├── sequel │ │ │ └── versions.rb │ │ └── base.rb │ ├── error.rb │ ├── core.rb │ ├── helper_module.rb │ ├── matcher_helpers.rb │ ├── assertions.rb │ ├── path_collection.rb │ ├── graph.rb │ ├── machine_collection.rb │ └── eval_helpers.rb ├── tasks │ ├── state_machine.rake │ └── state_machine.rb ├── yard-state_machine.rb └── state_machine.rb ├── .yardopts ├── .gitignore ├── gemfiles ├── default.gemfile ├── active_model_3.0.0.gemfile ├── active_model_3.0.5.gemfile ├── active_model_3.1.1.gemfile ├── active_model_3.2.1.gemfile ├── active_model_3.2.12.gemfile ├── graphviz_0.9.17.gemfile ├── graphviz_0.9.21.gemfile ├── graphviz_1.0.0.gemfile ├── graphviz_1.0.3.gemfile ├── graphviz_1.0.8.gemfile ├── mongo_mapper_0.9.0.gemfile ├── active_model_3.2.13.rc1.gemfile ├── mongoid_3.0.0.gemfile ├── mongoid_3.1.0.gemfile ├── mongoid_3.0.22.gemfile ├── mongo_mapper_0.5.5.gemfile ├── mongo_mapper_0.5.8.gemfile ├── mongo_mapper_0.6.0.gemfile ├── mongo_mapper_0.6.10.gemfile ├── mongo_mapper_0.7.0.gemfile ├── mongo_mapper_0.7.5.gemfile ├── mongo_mapper_0.8.4.gemfile ├── mongo_mapper_0.8.6.gemfile ├── mongo_mapper_0.10.0.gemfile ├── mongoid_2.0.0.gemfile ├── mongoid_2.1.4.gemfile ├── mongoid_2.2.4.gemfile ├── mongoid_2.3.3.gemfile ├── mongoid_2.4.0.gemfile ├── mongoid_2.4.10.gemfile ├── mongoid_2.5.2.gemfile ├── mongoid_2.6.0.gemfile ├── mongo_mapper_0.11.2.gemfile ├── mongo_mapper_0.12.0.gemfile ├── mongo_mapper_0.8.0.gemfile ├── mongo_mapper_0.8.3.gemfile ├── sequel_2.11.0.gemfile ├── sequel_2.12.0.gemfile ├── sequel_2.8.0.gemfile ├── sequel_3.0.0.gemfile ├── sequel_3.10.0.gemfile ├── sequel_3.13.0.gemfile ├── sequel_3.14.0.gemfile ├── sequel_3.23.0.gemfile ├── sequel_3.24.0.gemfile ├── sequel_3.29.0.gemfile ├── sequel_3.34.0.gemfile ├── sequel_3.35.0.gemfile ├── sequel_3.4.0.gemfile ├── sequel_3.44.0.gemfile ├── active_record_3.1.1.gemfile ├── active_model_4.0.0.gemfile ├── active_record_2.0.0.gemfile ├── active_record_2.0.5.gemfile ├── active_record_2.1.0.gemfile ├── active_record_2.1.2.gemfile ├── active_record_2.2.3.gemfile ├── active_record_2.3.5.gemfile ├── active_record_3.0.0.gemfile ├── active_record_3.0.5.gemfile ├── active_record_3.2.12.gemfile ├── active_record_2.3.12.gemfile ├── active_record_3.2.13.rc1.gemfile ├── data_mapper_0.9.4.gemfile ├── data_mapper_1.0.0.gemfile ├── data_mapper_1.0.1.gemfile ├── data_mapper_1.0.2.gemfile ├── data_mapper_1.1.0.gemfile ├── data_mapper_1.2.0.gemfile ├── data_mapper_0.9.7.gemfile ├── data_mapper_0.10.2.gemfile ├── data_mapper_0.9.11.gemfile ├── active_record_4.0.0.gemfile ├── default.gemfile.lock ├── graphviz_1.0.3.gemfile.lock ├── graphviz_1.0.8.gemfile.lock ├── graphviz_0.9.17.gemfile.lock ├── graphviz_0.9.21.gemfile.lock ├── graphviz_1.0.0.gemfile.lock ├── sequel_2.8.0.gemfile.lock ├── sequel_3.0.0.gemfile.lock ├── sequel_3.4.0.gemfile.lock ├── sequel_2.11.0.gemfile.lock ├── sequel_2.12.0.gemfile.lock ├── sequel_3.10.0.gemfile.lock ├── sequel_3.13.0.gemfile.lock ├── sequel_3.14.0.gemfile.lock ├── sequel_3.23.0.gemfile.lock ├── sequel_3.24.0.gemfile.lock ├── sequel_3.29.0.gemfile.lock ├── sequel_3.34.0.gemfile.lock ├── sequel_3.35.0.gemfile.lock ├── sequel_3.44.0.gemfile.lock ├── active_model_3.0.0.gemfile.lock ├── active_model_3.0.5.gemfile.lock ├── active_model_3.1.1.gemfile.lock ├── active_model_3.2.12.gemfile.lock ├── active_model_3.2.13.rc1.gemfile.lock ├── mongo_mapper_0.5.8.gemfile.lock ├── mongo_mapper_0.6.0.gemfile.lock ├── mongo_mapper_0.5.5.gemfile.lock ├── mongo_mapper_0.7.0.gemfile.lock ├── mongo_mapper_0.6.10.gemfile.lock ├── mongo_mapper_0.7.5.gemfile.lock ├── active_record_2.0.0.gemfile.lock ├── active_record_2.0.5.gemfile.lock ├── active_record_2.1.0.gemfile.lock ├── active_record_2.1.2.gemfile.lock ├── active_record_2.2.3.gemfile.lock ├── active_record_2.3.5.gemfile.lock ├── active_record_2.3.12.gemfile.lock ├── mongo_mapper_0.8.4.gemfile.lock ├── mongo_mapper_0.8.6.gemfile.lock ├── mongo_mapper_0.8.0.gemfile.lock ├── mongo_mapper_0.8.3.gemfile.lock ├── mongo_mapper_0.9.0.gemfile.lock ├── mongoid_3.0.22.gemfile.lock ├── mongoid_3.1.0.gemfile.lock ├── mongoid_3.0.0.gemfile.lock ├── mongoid_2.1.4.gemfile.lock ├── mongoid_2.2.4.gemfile.lock ├── mongoid_2.3.3.gemfile.lock ├── mongoid_2.4.0.gemfile.lock ├── mongoid_2.5.2.gemfile.lock ├── mongoid_2.6.0.gemfile.lock ├── mongoid_2.4.10.gemfile.lock ├── mongo_mapper_0.10.0.gemfile.lock ├── mongo_mapper_0.11.2.gemfile.lock ├── mongo_mapper_0.12.0.gemfile.lock ├── mongoid_2.0.0.gemfile.lock ├── active_record_3.0.5.gemfile.lock ├── active_record_3.1.1.gemfile.lock ├── active_record_3.2.12.gemfile.lock ├── active_record_3.0.0.gemfile.lock ├── active_record_3.2.13.rc1.gemfile.lock ├── data_mapper_0.10.2.gemfile.lock ├── data_mapper_1.1.0.gemfile.lock ├── data_mapper_1.2.0.gemfile.lock ├── data_mapper_1.0.0.gemfile.lock ├── data_mapper_1.0.1.gemfile.lock ├── data_mapper_1.0.2.gemfile.lock ├── data_mapper_0.9.7.gemfile.lock ├── data_mapper_0.9.4.gemfile.lock ├── data_mapper_0.9.11.gemfile.lock ├── active_model_4.0.0.gemfile.lock └── active_record_4.0.0.gemfile.lock ├── test ├── test_helper.rb ├── files │ ├── switch.rb │ └── en.yml └── unit │ ├── helper_module_test.rb │ ├── invalid_parallel_transition_test.rb │ ├── invalid_event_test.rb │ ├── state_machine_test.rb │ ├── matcher_helpers_test.rb │ ├── error_test.rb │ ├── assertions_test.rb │ ├── integrations │ └── base_test.rb │ ├── graph_test.rb │ ├── integrations_test.rb │ └── invalid_transition_test.rb ├── LICENSE ├── state_machine.gemspec ├── Rakefile └── .travis.yml /init.rb: -------------------------------------------------------------------------------- 1 | require 'state_machine' 2 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source "http://www.rubygems.org" 2 | 3 | gemspec 4 | -------------------------------------------------------------------------------- /examples/doc/css/common.css: -------------------------------------------------------------------------------- 1 | /* Override this file with custom rules */ -------------------------------------------------------------------------------- /lib/state_machine/version.rb: -------------------------------------------------------------------------------- 1 | module StateMachine 2 | VERSION = '1.2.0' 3 | end 4 | -------------------------------------------------------------------------------- /lib/tasks/state_machine.rake: -------------------------------------------------------------------------------- 1 | require File.join("#{File.dirname(__FILE__)}/state_machine") 2 | -------------------------------------------------------------------------------- /lib/yard-state_machine.rb: -------------------------------------------------------------------------------- 1 | require 'state_machine/core' 2 | require 'state_machine/yard' 3 | -------------------------------------------------------------------------------- /.yardopts: -------------------------------------------------------------------------------- 1 | --title "state_machine" 2 | --readme README.md 3 | - 4 | CHANGELOG.md 5 | LICENSE 6 | -------------------------------------------------------------------------------- /examples/Car_state.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pluginaweek/state_machine/HEAD/examples/Car_state.png -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.gem 2 | .bundle/ 3 | .rbx/ 4 | .yardoc/ 5 | coverage/ 6 | /doc/ 7 | test/*.log 8 | /Gemfile.lock 9 | -------------------------------------------------------------------------------- /examples/Vehicle_state.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pluginaweek/state_machine/HEAD/examples/Vehicle_state.png -------------------------------------------------------------------------------- /examples/doc/Car_state.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pluginaweek/state_machine/HEAD/examples/doc/Car_state.png -------------------------------------------------------------------------------- /examples/AutoShop_state.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pluginaweek/state_machine/HEAD/examples/AutoShop_state.png -------------------------------------------------------------------------------- /examples/Gemfile: -------------------------------------------------------------------------------- 1 | source "http://www.rubygems.org" 2 | 3 | gem 'yard' 4 | gem 'state_machine' 5 | gem 'ruby-graphviz' 6 | -------------------------------------------------------------------------------- /examples/TrafficLight_state.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pluginaweek/state_machine/HEAD/examples/TrafficLight_state.png -------------------------------------------------------------------------------- /examples/doc/AutoShop_state.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pluginaweek/state_machine/HEAD/examples/doc/AutoShop_state.png -------------------------------------------------------------------------------- /examples/doc/Vehicle_state.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pluginaweek/state_machine/HEAD/examples/doc/Vehicle_state.png -------------------------------------------------------------------------------- /examples/doc/TrafficLight_state.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pluginaweek/state_machine/HEAD/examples/doc/TrafficLight_state.png -------------------------------------------------------------------------------- /examples/rails-rest/view_new.html.erb: -------------------------------------------------------------------------------- 1 |

New user

2 | 3 | <%= render 'form' %> 4 | 5 | <%= link_to 'Back', users_path %> 6 | -------------------------------------------------------------------------------- /gemfiles/default.gemfile: -------------------------------------------------------------------------------- 1 | # This file was generated by Appraisal 2 | 3 | source "http://www.rubygems.org" 4 | 5 | 6 | 7 | gemspec :path=>"../" -------------------------------------------------------------------------------- /lib/state_machine/core_ext.rb: -------------------------------------------------------------------------------- 1 | # Loads all of the extensions to be made to Ruby core classes 2 | require 'state_machine/core_ext/class/state_machine' 3 | -------------------------------------------------------------------------------- /lib/state_machine/initializers/merb.rb: -------------------------------------------------------------------------------- 1 | Merb::Plugins.add_rakefiles("#{File.dirname(__FILE__)}/../../tasks/state_machine") if defined?(Merb::Plugins) 2 | -------------------------------------------------------------------------------- /examples/rails-rest/view_edit.html.erb: -------------------------------------------------------------------------------- 1 |

Editing user

2 | 3 | <%= render 'form' %> 4 | 5 | <%= link_to 'Show', @user %> | 6 | <%= link_to 'Back', users_path %> 7 | -------------------------------------------------------------------------------- /lib/state_machine/core_ext/class/state_machine.rb: -------------------------------------------------------------------------------- 1 | require 'state_machine/macro_methods' 2 | 3 | Class.class_eval do 4 | include StateMachine::MacroMethods 5 | end 6 | -------------------------------------------------------------------------------- /lib/state_machine/yard/templates.rb: -------------------------------------------------------------------------------- 1 | require 'yard' 2 | 3 | YARD::Templates::Engine.register_template_path File.expand_path(File.join(File.dirname(__FILE__), 'templates')) 4 | -------------------------------------------------------------------------------- /gemfiles/active_model_3.0.0.gemfile: -------------------------------------------------------------------------------- 1 | # This file was generated by Appraisal 2 | 3 | source "http://www.rubygems.org" 4 | 5 | gem "activemodel", "3.0.0" 6 | 7 | gemspec :path=>"../" -------------------------------------------------------------------------------- /gemfiles/active_model_3.0.5.gemfile: -------------------------------------------------------------------------------- 1 | # This file was generated by Appraisal 2 | 3 | source "http://www.rubygems.org" 4 | 5 | gem "activemodel", "3.0.5" 6 | 7 | gemspec :path=>"../" -------------------------------------------------------------------------------- /gemfiles/active_model_3.1.1.gemfile: -------------------------------------------------------------------------------- 1 | # This file was generated by Appraisal 2 | 3 | source "http://www.rubygems.org" 4 | 5 | gem "activemodel", "3.1.1" 6 | 7 | gemspec :path=>"../" -------------------------------------------------------------------------------- /gemfiles/active_model_3.2.1.gemfile: -------------------------------------------------------------------------------- 1 | # This file was generated by Appraisal 2 | 3 | source "http://www.rubygems.org" 4 | 5 | gem "activemodel", "3.2.1" 6 | 7 | gemspec :path=>"../" -------------------------------------------------------------------------------- /gemfiles/active_model_3.2.12.gemfile: -------------------------------------------------------------------------------- 1 | # This file was generated by Appraisal 2 | 3 | source "http://www.rubygems.org" 4 | 5 | gem "activemodel", "3.2.12" 6 | 7 | gemspec :path=>"../" -------------------------------------------------------------------------------- /gemfiles/graphviz_0.9.17.gemfile: -------------------------------------------------------------------------------- 1 | # This file was generated by Appraisal 2 | 3 | source "http://www.rubygems.org" 4 | 5 | gem "ruby-graphviz", "0.9.17" 6 | 7 | gemspec :path=>"../" -------------------------------------------------------------------------------- /gemfiles/graphviz_0.9.21.gemfile: -------------------------------------------------------------------------------- 1 | # This file was generated by Appraisal 2 | 3 | source "http://www.rubygems.org" 4 | 5 | gem "ruby-graphviz", "0.9.21" 6 | 7 | gemspec :path=>"../" -------------------------------------------------------------------------------- /gemfiles/graphviz_1.0.0.gemfile: -------------------------------------------------------------------------------- 1 | # This file was generated by Appraisal 2 | 3 | source "http://www.rubygems.org" 4 | 5 | gem "ruby-graphviz", "1.0.0" 6 | 7 | gemspec :path=>"../" -------------------------------------------------------------------------------- /gemfiles/graphviz_1.0.3.gemfile: -------------------------------------------------------------------------------- 1 | # This file was generated by Appraisal 2 | 3 | source "http://www.rubygems.org" 4 | 5 | gem "ruby-graphviz", "1.0.3" 6 | 7 | gemspec :path=>"../" -------------------------------------------------------------------------------- /gemfiles/graphviz_1.0.8.gemfile: -------------------------------------------------------------------------------- 1 | # This file was generated by Appraisal 2 | 3 | source "http://www.rubygems.org" 4 | 5 | gem "ruby-graphviz", "1.0.8" 6 | 7 | gemspec :path=>"../" -------------------------------------------------------------------------------- /gemfiles/mongo_mapper_0.9.0.gemfile: -------------------------------------------------------------------------------- 1 | # This file was generated by Appraisal 2 | 3 | source "http://www.rubygems.org" 4 | 5 | gem "mongo_mapper", "0.9.0" 6 | 7 | gemspec :path=>"../" -------------------------------------------------------------------------------- /test/test_helper.rb: -------------------------------------------------------------------------------- 1 | if ENV['COVERAGE'] 2 | require 'simplecov' 3 | SimpleCov.start { add_filter '/test/' } 4 | end 5 | 6 | require 'test/unit' 7 | require 'state_machine' 8 | -------------------------------------------------------------------------------- /gemfiles/active_model_3.2.13.rc1.gemfile: -------------------------------------------------------------------------------- 1 | # This file was generated by Appraisal 2 | 3 | source "http://www.rubygems.org" 4 | 5 | gem "activemodel", "3.2.13.rc1" 6 | 7 | gemspec :path=>"../" -------------------------------------------------------------------------------- /gemfiles/mongoid_3.0.0.gemfile: -------------------------------------------------------------------------------- 1 | # This file was generated by Appraisal 2 | 3 | source "http://www.rubygems.org" 4 | 5 | gem "activemodel", "3.2.13.rc1" 6 | gem "mongoid", "3.0.0" 7 | 8 | gemspec :path=>"../" -------------------------------------------------------------------------------- /gemfiles/mongoid_3.1.0.gemfile: -------------------------------------------------------------------------------- 1 | # This file was generated by Appraisal 2 | 3 | source "http://www.rubygems.org" 4 | 5 | gem "activemodel", "3.2.13.rc1" 6 | gem "mongoid", "3.1.0" 7 | 8 | gemspec :path=>"../" -------------------------------------------------------------------------------- /examples/rails-rest/migration.rb: -------------------------------------------------------------------------------- 1 | class CreateUsers < ActiveRecord::Migration 2 | def change 3 | create_table :users do |t| 4 | t.string :name, :state, :access_state 5 | end 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /gemfiles/mongoid_3.0.22.gemfile: -------------------------------------------------------------------------------- 1 | # This file was generated by Appraisal 2 | 3 | source "http://www.rubygems.org" 4 | 5 | gem "activemodel", "3.2.13.rc1" 6 | gem "mongoid", "3.0.22" 7 | 8 | gemspec :path=>"../" -------------------------------------------------------------------------------- /gemfiles/mongo_mapper_0.5.5.gemfile: -------------------------------------------------------------------------------- 1 | # This file was generated by Appraisal 2 | 3 | source "http://www.rubygems.org" 4 | 5 | gem "activesupport", "2.3.11" 6 | gem "mongo_mapper", "0.5.5" 7 | 8 | gemspec :path=>"../" -------------------------------------------------------------------------------- /gemfiles/mongo_mapper_0.5.8.gemfile: -------------------------------------------------------------------------------- 1 | # This file was generated by Appraisal 2 | 3 | source "http://www.rubygems.org" 4 | 5 | gem "activesupport", "2.3.11" 6 | gem "mongo_mapper", "0.5.8" 7 | 8 | gemspec :path=>"../" -------------------------------------------------------------------------------- /gemfiles/mongo_mapper_0.6.0.gemfile: -------------------------------------------------------------------------------- 1 | # This file was generated by Appraisal 2 | 3 | source "http://www.rubygems.org" 4 | 5 | gem "activesupport", "2.3.11" 6 | gem "mongo_mapper", "0.6.0" 7 | 8 | gemspec :path=>"../" -------------------------------------------------------------------------------- /gemfiles/mongo_mapper_0.6.10.gemfile: -------------------------------------------------------------------------------- 1 | # This file was generated by Appraisal 2 | 3 | source "http://www.rubygems.org" 4 | 5 | gem "activesupport", "2.3.11" 6 | gem "mongo_mapper", "0.6.10" 7 | 8 | gemspec :path=>"../" -------------------------------------------------------------------------------- /gemfiles/mongo_mapper_0.7.0.gemfile: -------------------------------------------------------------------------------- 1 | # This file was generated by Appraisal 2 | 3 | source "http://www.rubygems.org" 4 | 5 | gem "activesupport", "2.3.11" 6 | gem "mongo_mapper", "0.7.0" 7 | 8 | gemspec :path=>"../" -------------------------------------------------------------------------------- /gemfiles/mongo_mapper_0.7.5.gemfile: -------------------------------------------------------------------------------- 1 | # This file was generated by Appraisal 2 | 3 | source "http://www.rubygems.org" 4 | 5 | gem "activesupport", "2.3.11" 6 | gem "mongo_mapper", "0.7.5" 7 | 8 | gemspec :path=>"../" -------------------------------------------------------------------------------- /gemfiles/mongo_mapper_0.8.4.gemfile: -------------------------------------------------------------------------------- 1 | # This file was generated by Appraisal 2 | 3 | source "http://www.rubygems.org" 4 | 5 | gem "activesupport", "2.3.11" 6 | gem "mongo_mapper", "0.8.4" 7 | 8 | gemspec :path=>"../" -------------------------------------------------------------------------------- /gemfiles/mongo_mapper_0.8.6.gemfile: -------------------------------------------------------------------------------- 1 | # This file was generated by Appraisal 2 | 3 | source "http://www.rubygems.org" 4 | 5 | gem "activesupport", "2.3.11" 6 | gem "mongo_mapper", "0.8.6" 7 | 8 | gemspec :path=>"../" -------------------------------------------------------------------------------- /gemfiles/mongo_mapper_0.10.0.gemfile: -------------------------------------------------------------------------------- 1 | # This file was generated by Appraisal 2 | 3 | source "http://www.rubygems.org" 4 | 5 | gem "activemodel", "3.2.13.rc1" 6 | gem "mongo_mapper", "0.10.0" 7 | 8 | gemspec :path=>"../" -------------------------------------------------------------------------------- /lib/state_machine/initializers.rb: -------------------------------------------------------------------------------- 1 | # Load each application initializer 2 | Dir["#{File.dirname(__FILE__)}/initializers/*.rb"].sort.each do |path| 3 | require "state_machine/initializers/#{File.basename(path)}" 4 | end 5 | -------------------------------------------------------------------------------- /lib/state_machine/yard.rb: -------------------------------------------------------------------------------- 1 | module StateMachine 2 | # YARD plugin for automated documentation 3 | module YARD 4 | end 5 | end 6 | 7 | require 'state_machine/yard/handlers' 8 | require 'state_machine/yard/templates' 9 | -------------------------------------------------------------------------------- /gemfiles/mongoid_2.0.0.gemfile: -------------------------------------------------------------------------------- 1 | # This file was generated by Appraisal 2 | 3 | source "http://www.rubygems.org" 4 | 5 | gem "activemodel", "~> 3.1.0" 6 | gem "mongo", "~> 1.7.0" 7 | gem "mongoid", "2.0.0" 8 | 9 | gemspec :path=>"../" -------------------------------------------------------------------------------- /gemfiles/mongoid_2.1.4.gemfile: -------------------------------------------------------------------------------- 1 | # This file was generated by Appraisal 2 | 3 | source "http://www.rubygems.org" 4 | 5 | gem "activemodel", "~> 3.1.0" 6 | gem "mongo", "~> 1.7.0" 7 | gem "mongoid", "2.1.4" 8 | 9 | gemspec :path=>"../" -------------------------------------------------------------------------------- /gemfiles/mongoid_2.2.4.gemfile: -------------------------------------------------------------------------------- 1 | # This file was generated by Appraisal 2 | 3 | source "http://www.rubygems.org" 4 | 5 | gem "activemodel", "~> 3.1.0" 6 | gem "mongo", "~> 1.7.0" 7 | gem "mongoid", "2.2.4" 8 | 9 | gemspec :path=>"../" -------------------------------------------------------------------------------- /gemfiles/mongoid_2.3.3.gemfile: -------------------------------------------------------------------------------- 1 | # This file was generated by Appraisal 2 | 3 | source "http://www.rubygems.org" 4 | 5 | gem "activemodel", "~> 3.1.0" 6 | gem "mongo", "~> 1.7.0" 7 | gem "mongoid", "2.3.3" 8 | 9 | gemspec :path=>"../" -------------------------------------------------------------------------------- /gemfiles/mongoid_2.4.0.gemfile: -------------------------------------------------------------------------------- 1 | # This file was generated by Appraisal 2 | 3 | source "http://www.rubygems.org" 4 | 5 | gem "activemodel", "3.2.13.rc1" 6 | gem "mongo", "~> 1.7.0" 7 | gem "mongoid", "2.4.0" 8 | 9 | gemspec :path=>"../" -------------------------------------------------------------------------------- /gemfiles/mongoid_2.4.10.gemfile: -------------------------------------------------------------------------------- 1 | # This file was generated by Appraisal 2 | 3 | source "http://www.rubygems.org" 4 | 5 | gem "activemodel", "3.2.13.rc1" 6 | gem "mongo", "~> 1.7.0" 7 | gem "mongoid", "2.4.10" 8 | 9 | gemspec :path=>"../" -------------------------------------------------------------------------------- /gemfiles/mongoid_2.5.2.gemfile: -------------------------------------------------------------------------------- 1 | # This file was generated by Appraisal 2 | 3 | source "http://www.rubygems.org" 4 | 5 | gem "activemodel", "3.2.13.rc1" 6 | gem "mongo", "~> 1.7.0" 7 | gem "mongoid", "2.5.2" 8 | 9 | gemspec :path=>"../" -------------------------------------------------------------------------------- /gemfiles/mongoid_2.6.0.gemfile: -------------------------------------------------------------------------------- 1 | # This file was generated by Appraisal 2 | 3 | source "http://www.rubygems.org" 4 | 5 | gem "activemodel", "3.2.13.rc1" 6 | gem "mongo", "~> 1.7.0" 7 | gem "mongoid", "2.6.0" 8 | 9 | gemspec :path=>"../" -------------------------------------------------------------------------------- /gemfiles/mongo_mapper_0.11.2.gemfile: -------------------------------------------------------------------------------- 1 | # This file was generated by Appraisal 2 | 3 | source "http://www.rubygems.org" 4 | 5 | gem "activemodel", "3.2.13.rc1" 6 | gem "mongo", "~> 1.7.0" 7 | gem "mongo_mapper", "0.11.2" 8 | 9 | gemspec :path=>"../" -------------------------------------------------------------------------------- /gemfiles/mongo_mapper_0.12.0.gemfile: -------------------------------------------------------------------------------- 1 | # This file was generated by Appraisal 2 | 3 | source "http://www.rubygems.org" 4 | 5 | gem "activemodel", "3.2.13.rc1" 6 | gem "mongo", "~> 1.7.0" 7 | gem "mongo_mapper", "0.12.0" 8 | 9 | gemspec :path=>"../" -------------------------------------------------------------------------------- /examples/traffic_light.rb: -------------------------------------------------------------------------------- 1 | require 'state_machine' 2 | 3 | class TrafficLight 4 | state_machine :initial => :stop do 5 | event :cycle do 6 | transition :stop => :proceed, :proceed => :caution, :caution => :stop 7 | end 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /gemfiles/mongo_mapper_0.8.0.gemfile: -------------------------------------------------------------------------------- 1 | # This file was generated by Appraisal 2 | 3 | source "http://www.rubygems.org" 4 | 5 | gem "activesupport", "2.3.11" 6 | gem "mongo", "1.0.1" 7 | gem "plucky", "0.3.0" 8 | gem "mongo_mapper", "0.8.0" 9 | 10 | gemspec :path=>"../" -------------------------------------------------------------------------------- /gemfiles/mongo_mapper_0.8.3.gemfile: -------------------------------------------------------------------------------- 1 | # This file was generated by Appraisal 2 | 3 | source "http://www.rubygems.org" 4 | 5 | gem "activesupport", "2.3.11" 6 | gem "mongo", "1.0.1" 7 | gem "plucky", "0.3.3" 8 | gem "mongo_mapper", "0.8.3" 9 | 10 | gemspec :path=>"../" -------------------------------------------------------------------------------- /examples/Gemfile.lock: -------------------------------------------------------------------------------- 1 | GEM 2 | remote: http://www.rubygems.org/ 3 | specs: 4 | ruby-graphviz (1.0.0) 5 | state_machine (1.2.0) 6 | yard (0.7.5) 7 | 8 | PLATFORMS 9 | ruby 10 | 11 | DEPENDENCIES 12 | ruby-graphviz 13 | state_machine 14 | yard 15 | -------------------------------------------------------------------------------- /lib/state_machine/integrations/mongoid/locale.rb: -------------------------------------------------------------------------------- 1 | filename = "#{File.dirname(__FILE__)}/../active_model/locale.rb" 2 | translations = eval(IO.read(File.expand_path(filename)), binding, filename) 3 | translations[:en][:mongoid] = translations[:en].delete(:activemodel) 4 | translations 5 | -------------------------------------------------------------------------------- /gemfiles/sequel_2.11.0.gemfile: -------------------------------------------------------------------------------- 1 | # This file was generated by Appraisal 2 | 3 | source "http://www.rubygems.org" 4 | 5 | gem "sqlite3-ruby", "1.3.1", :platform=>[:ruby, :mswin, :mingw] 6 | gem "jdbc-sqlite3", "3.7.2", :platform=>:jruby 7 | gem "sequel", "2.11.0" 8 | 9 | gemspec :path=>"../" -------------------------------------------------------------------------------- /gemfiles/sequel_2.12.0.gemfile: -------------------------------------------------------------------------------- 1 | # This file was generated by Appraisal 2 | 3 | source "http://www.rubygems.org" 4 | 5 | gem "sqlite3-ruby", "1.3.1", :platform=>[:ruby, :mswin, :mingw] 6 | gem "jdbc-sqlite3", "3.7.2", :platform=>:jruby 7 | gem "sequel", "2.12.0" 8 | 9 | gemspec :path=>"../" -------------------------------------------------------------------------------- /gemfiles/sequel_2.8.0.gemfile: -------------------------------------------------------------------------------- 1 | # This file was generated by Appraisal 2 | 3 | source "http://www.rubygems.org" 4 | 5 | gem "sqlite3-ruby", "1.3.1", :platform=>[:ruby, :mswin, :mingw] 6 | gem "jdbc-sqlite3", "3.7.2", :platform=>:jruby 7 | gem "sequel", "2.8.0" 8 | 9 | gemspec :path=>"../" -------------------------------------------------------------------------------- /gemfiles/sequel_3.0.0.gemfile: -------------------------------------------------------------------------------- 1 | # This file was generated by Appraisal 2 | 3 | source "http://www.rubygems.org" 4 | 5 | gem "sqlite3-ruby", "1.3.1", :platform=>[:ruby, :mswin, :mingw] 6 | gem "jdbc-sqlite3", "3.7.2", :platform=>:jruby 7 | gem "sequel", "3.0.0" 8 | 9 | gemspec :path=>"../" -------------------------------------------------------------------------------- /gemfiles/sequel_3.10.0.gemfile: -------------------------------------------------------------------------------- 1 | # This file was generated by Appraisal 2 | 3 | source "http://www.rubygems.org" 4 | 5 | gem "sqlite3-ruby", "1.3.1", :platform=>[:ruby, :mswin, :mingw] 6 | gem "jdbc-sqlite3", "3.7.2", :platform=>:jruby 7 | gem "sequel", "3.10.0" 8 | 9 | gemspec :path=>"../" -------------------------------------------------------------------------------- /gemfiles/sequel_3.13.0.gemfile: -------------------------------------------------------------------------------- 1 | # This file was generated by Appraisal 2 | 3 | source "http://www.rubygems.org" 4 | 5 | gem "sqlite3-ruby", "1.3.1", :platform=>[:ruby, :mswin, :mingw] 6 | gem "jdbc-sqlite3", "3.7.2", :platform=>:jruby 7 | gem "sequel", "3.13.0" 8 | 9 | gemspec :path=>"../" -------------------------------------------------------------------------------- /gemfiles/sequel_3.14.0.gemfile: -------------------------------------------------------------------------------- 1 | # This file was generated by Appraisal 2 | 3 | source "http://www.rubygems.org" 4 | 5 | gem "sqlite3-ruby", "1.3.1", :platform=>[:ruby, :mswin, :mingw] 6 | gem "jdbc-sqlite3", "3.7.2", :platform=>:jruby 7 | gem "sequel", "3.14.0" 8 | 9 | gemspec :path=>"../" -------------------------------------------------------------------------------- /gemfiles/sequel_3.23.0.gemfile: -------------------------------------------------------------------------------- 1 | # This file was generated by Appraisal 2 | 3 | source "http://www.rubygems.org" 4 | 5 | gem "sqlite3-ruby", "1.3.1", :platform=>[:ruby, :mswin, :mingw] 6 | gem "jdbc-sqlite3", "3.7.2", :platform=>:jruby 7 | gem "sequel", "3.23.0" 8 | 9 | gemspec :path=>"../" -------------------------------------------------------------------------------- /gemfiles/sequel_3.24.0.gemfile: -------------------------------------------------------------------------------- 1 | # This file was generated by Appraisal 2 | 3 | source "http://www.rubygems.org" 4 | 5 | gem "sqlite3-ruby", "1.3.1", :platform=>[:ruby, :mswin, :mingw] 6 | gem "jdbc-sqlite3", "3.7.2", :platform=>:jruby 7 | gem "sequel", "3.24.0" 8 | 9 | gemspec :path=>"../" -------------------------------------------------------------------------------- /gemfiles/sequel_3.29.0.gemfile: -------------------------------------------------------------------------------- 1 | # This file was generated by Appraisal 2 | 3 | source "http://www.rubygems.org" 4 | 5 | gem "sqlite3-ruby", "1.3.1", :platform=>[:ruby, :mswin, :mingw] 6 | gem "jdbc-sqlite3", "3.7.2", :platform=>:jruby 7 | gem "sequel", "3.29.0" 8 | 9 | gemspec :path=>"../" -------------------------------------------------------------------------------- /gemfiles/sequel_3.34.0.gemfile: -------------------------------------------------------------------------------- 1 | # This file was generated by Appraisal 2 | 3 | source "http://www.rubygems.org" 4 | 5 | gem "sqlite3-ruby", "1.3.1", :platform=>[:ruby, :mswin, :mingw] 6 | gem "jdbc-sqlite3", "3.7.2", :platform=>:jruby 7 | gem "sequel", "3.34.0" 8 | 9 | gemspec :path=>"../" -------------------------------------------------------------------------------- /gemfiles/sequel_3.35.0.gemfile: -------------------------------------------------------------------------------- 1 | # This file was generated by Appraisal 2 | 3 | source "http://www.rubygems.org" 4 | 5 | gem "sqlite3-ruby", "1.3.1", :platform=>[:ruby, :mswin, :mingw] 6 | gem "jdbc-sqlite3", "3.7.2", :platform=>:jruby 7 | gem "sequel", "3.35.0" 8 | 9 | gemspec :path=>"../" -------------------------------------------------------------------------------- /gemfiles/sequel_3.4.0.gemfile: -------------------------------------------------------------------------------- 1 | # This file was generated by Appraisal 2 | 3 | source "http://www.rubygems.org" 4 | 5 | gem "sqlite3-ruby", "1.3.1", :platform=>[:ruby, :mswin, :mingw] 6 | gem "jdbc-sqlite3", "3.7.2", :platform=>:jruby 7 | gem "sequel", "3.4.0" 8 | 9 | gemspec :path=>"../" -------------------------------------------------------------------------------- /gemfiles/sequel_3.44.0.gemfile: -------------------------------------------------------------------------------- 1 | # This file was generated by Appraisal 2 | 3 | source "http://www.rubygems.org" 4 | 5 | gem "sqlite3-ruby", "1.3.1", :platform=>[:ruby, :mswin, :mingw] 6 | gem "jdbc-sqlite3", "3.7.2", :platform=>:jruby 7 | gem "sequel", "3.44.0" 8 | 9 | gemspec :path=>"../" -------------------------------------------------------------------------------- /lib/state_machine/integrations/mongo_mapper/locale.rb: -------------------------------------------------------------------------------- 1 | filename = "#{File.dirname(__FILE__)}/../active_model/locale.rb" 2 | translations = eval(IO.read(File.expand_path(filename)), binding, filename) 3 | translations[:en][:mongo_mapper] = translations[:en].delete(:activemodel) 4 | translations 5 | -------------------------------------------------------------------------------- /gemfiles/active_record_3.1.1.gemfile: -------------------------------------------------------------------------------- 1 | # This file was generated by Appraisal 2 | 3 | source "http://www.rubygems.org" 4 | 5 | gem "sqlite3", "1.3.6", :platform=>[:ruby, :mswin, :mingw] 6 | gem "activerecord", "3.1.1" 7 | gem "activerecord-jdbcsqlite3-adapter", "1.2.7", :platform=>:jruby 8 | 9 | gemspec :path=>"../" -------------------------------------------------------------------------------- /gemfiles/active_model_4.0.0.gemfile: -------------------------------------------------------------------------------- 1 | # This file was generated by Appraisal 2 | 3 | source "http://www.rubygems.org" 4 | 5 | gem "activemodel", "4.0.0.beta", :git=>"git://github.com/rails/rails.git", :ref=>"4e286bf" 6 | gem "rails-observers", "0.1.1" 7 | gem "protected_attributes", "1.0.0" 8 | 9 | gemspec :path=>"../" -------------------------------------------------------------------------------- /gemfiles/active_record_2.0.0.gemfile: -------------------------------------------------------------------------------- 1 | # This file was generated by Appraisal 2 | 3 | source "http://www.rubygems.org" 4 | 5 | gem "sqlite3-ruby", "1.3.1", :platform=>[:ruby, :mswin, :mingw] 6 | gem "activerecord", "2.0.0" 7 | gem "activerecord-jdbcsqlite3-adapter", "1.2.7", :platform=>:jruby 8 | 9 | gemspec :path=>"../" -------------------------------------------------------------------------------- /gemfiles/active_record_2.0.5.gemfile: -------------------------------------------------------------------------------- 1 | # This file was generated by Appraisal 2 | 3 | source "http://www.rubygems.org" 4 | 5 | gem "sqlite3-ruby", "1.3.1", :platform=>[:ruby, :mswin, :mingw] 6 | gem "activerecord", "2.0.5" 7 | gem "activerecord-jdbcsqlite3-adapter", "1.2.7", :platform=>:jruby 8 | 9 | gemspec :path=>"../" -------------------------------------------------------------------------------- /gemfiles/active_record_2.1.0.gemfile: -------------------------------------------------------------------------------- 1 | # This file was generated by Appraisal 2 | 3 | source "http://www.rubygems.org" 4 | 5 | gem "sqlite3-ruby", "1.3.1", :platform=>[:ruby, :mswin, :mingw] 6 | gem "activerecord", "2.1.0" 7 | gem "activerecord-jdbcsqlite3-adapter", "1.2.7", :platform=>:jruby 8 | 9 | gemspec :path=>"../" -------------------------------------------------------------------------------- /gemfiles/active_record_2.1.2.gemfile: -------------------------------------------------------------------------------- 1 | # This file was generated by Appraisal 2 | 3 | source "http://www.rubygems.org" 4 | 5 | gem "sqlite3-ruby", "1.3.1", :platform=>[:ruby, :mswin, :mingw] 6 | gem "activerecord", "2.1.2" 7 | gem "activerecord-jdbcsqlite3-adapter", "1.2.7", :platform=>:jruby 8 | 9 | gemspec :path=>"../" -------------------------------------------------------------------------------- /gemfiles/active_record_2.2.3.gemfile: -------------------------------------------------------------------------------- 1 | # This file was generated by Appraisal 2 | 3 | source "http://www.rubygems.org" 4 | 5 | gem "sqlite3-ruby", "1.3.1", :platform=>[:ruby, :mswin, :mingw] 6 | gem "activerecord", "2.2.3" 7 | gem "activerecord-jdbcsqlite3-adapter", "1.2.7", :platform=>:jruby 8 | 9 | gemspec :path=>"../" -------------------------------------------------------------------------------- /gemfiles/active_record_2.3.5.gemfile: -------------------------------------------------------------------------------- 1 | # This file was generated by Appraisal 2 | 3 | source "http://www.rubygems.org" 4 | 5 | gem "sqlite3-ruby", "1.3.1", :platform=>[:ruby, :mswin, :mingw] 6 | gem "activerecord", "2.3.5" 7 | gem "activerecord-jdbcsqlite3-adapter", "1.2.7", :platform=>:jruby 8 | 9 | gemspec :path=>"../" -------------------------------------------------------------------------------- /gemfiles/active_record_3.0.0.gemfile: -------------------------------------------------------------------------------- 1 | # This file was generated by Appraisal 2 | 3 | source "http://www.rubygems.org" 4 | 5 | gem "sqlite3-ruby", "1.3.1", :platform=>[:ruby, :mswin, :mingw] 6 | gem "activerecord", "3.0.0" 7 | gem "activerecord-jdbcsqlite3-adapter", "1.2.7", :platform=>:jruby 8 | 9 | gemspec :path=>"../" -------------------------------------------------------------------------------- /gemfiles/active_record_3.0.5.gemfile: -------------------------------------------------------------------------------- 1 | # This file was generated by Appraisal 2 | 3 | source "http://www.rubygems.org" 4 | 5 | gem "sqlite3-ruby", "1.3.1", :platform=>[:ruby, :mswin, :mingw] 6 | gem "activerecord", "3.0.5" 7 | gem "activerecord-jdbcsqlite3-adapter", "1.2.7", :platform=>:jruby 8 | 9 | gemspec :path=>"../" -------------------------------------------------------------------------------- /gemfiles/active_record_3.2.12.gemfile: -------------------------------------------------------------------------------- 1 | # This file was generated by Appraisal 2 | 3 | source "http://www.rubygems.org" 4 | 5 | gem "sqlite3", "1.3.6", :platform=>[:ruby, :mswin, :mingw] 6 | gem "activerecord", "3.2.12" 7 | gem "activerecord-jdbcsqlite3-adapter", "1.2.7", :platform=>:jruby 8 | 9 | gemspec :path=>"../" -------------------------------------------------------------------------------- /examples/auto_shop.rb: -------------------------------------------------------------------------------- 1 | require 'state_machine' 2 | 3 | class AutoShop 4 | state_machine :initial => :available do 5 | event :tow_vehicle do 6 | transition :available => :busy 7 | end 8 | 9 | event :fix_vehicle do 10 | transition :busy => :available 11 | end 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /gemfiles/active_record_2.3.12.gemfile: -------------------------------------------------------------------------------- 1 | # This file was generated by Appraisal 2 | 3 | source "http://www.rubygems.org" 4 | 5 | gem "sqlite3-ruby", "1.3.1", :platform=>[:ruby, :mswin, :mingw] 6 | gem "activerecord", "2.3.12" 7 | gem "activerecord-jdbcsqlite3-adapter", "1.2.7", :platform=>:jruby 8 | 9 | gemspec :path=>"../" -------------------------------------------------------------------------------- /gemfiles/active_record_3.2.13.rc1.gemfile: -------------------------------------------------------------------------------- 1 | # This file was generated by Appraisal 2 | 3 | source "http://www.rubygems.org" 4 | 5 | gem "sqlite3", "1.3.6", :platform=>[:ruby, :mswin, :mingw] 6 | gem "activerecord", "3.2.13.rc1" 7 | gem "activerecord-jdbcsqlite3-adapter", "1.2.7", :platform=>:jruby 8 | 9 | gemspec :path=>"../" -------------------------------------------------------------------------------- /test/files/switch.rb: -------------------------------------------------------------------------------- 1 | class Switch 2 | def self.name 3 | @name ||= "Switch_#{rand(1000000)}" 4 | end 5 | 6 | state_machine do 7 | event :turn_on do 8 | transition all => :on 9 | end 10 | 11 | event :turn_off do 12 | transition all => :off 13 | end 14 | end 15 | end 16 | -------------------------------------------------------------------------------- /examples/merb-rest/view_new.html.erb: -------------------------------------------------------------------------------- 1 |

New User

2 | 3 | <%= form_for @user, :action => resource(:users) do %> 4 | <%= error_messages %> 5 | 6 |

7 | <%= text_field :name, :label => 'Name' %> 8 |

9 | 10 |

<%= submit 'Create' %>

11 | <% end =%> 12 | 13 | <%= link_to 'Back', resource(:users) %> 14 | -------------------------------------------------------------------------------- /gemfiles/data_mapper_0.9.4.gemfile: -------------------------------------------------------------------------------- 1 | # This file was generated by Appraisal 2 | 3 | source "http://www.rubygems.org" 4 | 5 | gem "dm-core", "0.9.4" 6 | gem "dm-migrations", "0.9.4" 7 | gem "dm-validations", "0.9.4" 8 | gem "dm-observer", "0.9.4" 9 | gem "data_objects", "0.9.4" 10 | gem "do_sqlite3", "0.9.4" 11 | 12 | gemspec :path=>"../" -------------------------------------------------------------------------------- /gemfiles/data_mapper_1.0.0.gemfile: -------------------------------------------------------------------------------- 1 | # This file was generated by Appraisal 2 | 3 | source "http://www.rubygems.org" 4 | 5 | gem "dm-core", "1.0.0" 6 | gem "dm-migrations", "1.0.0" 7 | gem "dm-validations", "1.0.0" 8 | gem "dm-observer", "1.0.0" 9 | gem "dm-transactions", "1.0.0" 10 | gem "dm-sqlite-adapter", "1.0.0" 11 | 12 | gemspec :path=>"../" -------------------------------------------------------------------------------- /gemfiles/data_mapper_1.0.1.gemfile: -------------------------------------------------------------------------------- 1 | # This file was generated by Appraisal 2 | 3 | source "http://www.rubygems.org" 4 | 5 | gem "dm-core", "1.0.1" 6 | gem "dm-migrations", "1.0.1" 7 | gem "dm-validations", "1.0.1" 8 | gem "dm-observer", "1.0.1" 9 | gem "dm-transactions", "1.0.1" 10 | gem "dm-sqlite-adapter", "1.0.1" 11 | 12 | gemspec :path=>"../" -------------------------------------------------------------------------------- /gemfiles/data_mapper_1.0.2.gemfile: -------------------------------------------------------------------------------- 1 | # This file was generated by Appraisal 2 | 3 | source "http://www.rubygems.org" 4 | 5 | gem "dm-core", "1.0.2" 6 | gem "dm-migrations", "1.0.2" 7 | gem "dm-validations", "1.0.2" 8 | gem "dm-observer", "1.0.2" 9 | gem "dm-transactions", "1.0.2" 10 | gem "dm-sqlite-adapter", "1.0.2" 11 | 12 | gemspec :path=>"../" -------------------------------------------------------------------------------- /gemfiles/data_mapper_1.1.0.gemfile: -------------------------------------------------------------------------------- 1 | # This file was generated by Appraisal 2 | 3 | source "http://www.rubygems.org" 4 | 5 | gem "dm-core", "1.1.0" 6 | gem "dm-migrations", "1.1.0" 7 | gem "dm-validations", "1.1.0" 8 | gem "dm-observer", "1.1.0" 9 | gem "dm-transactions", "1.1.0" 10 | gem "dm-sqlite-adapter", "1.1.0" 11 | 12 | gemspec :path=>"../" -------------------------------------------------------------------------------- /gemfiles/data_mapper_1.2.0.gemfile: -------------------------------------------------------------------------------- 1 | # This file was generated by Appraisal 2 | 3 | source "http://www.rubygems.org" 4 | 5 | gem "dm-core", "1.2.0" 6 | gem "dm-migrations", "1.2.0" 7 | gem "dm-validations", "1.2.0" 8 | gem "dm-observer", "1.2.0" 9 | gem "dm-transactions", "1.2.0" 10 | gem "dm-sqlite-adapter", "1.2.0" 11 | 12 | gemspec :path=>"../" -------------------------------------------------------------------------------- /gemfiles/data_mapper_0.9.7.gemfile: -------------------------------------------------------------------------------- 1 | # This file was generated by Appraisal 2 | 3 | source "http://www.rubygems.org" 4 | 5 | gem "extlib", "0.9.8" 6 | gem "dm-core", "0.9.7" 7 | gem "dm-migrations", "0.9.7" 8 | gem "dm-validations", "0.9.7" 9 | gem "dm-observer", "0.9.7" 10 | gem "data_objects", "0.9.7" 11 | gem "do_sqlite3", "0.9.7" 12 | 13 | gemspec :path=>"../" -------------------------------------------------------------------------------- /lib/state_machine/error.rb: -------------------------------------------------------------------------------- 1 | module StateMachine 2 | # An error occurred during a state machine invocation 3 | class Error < StandardError 4 | # The object that failed 5 | attr_reader :object 6 | 7 | def initialize(object, message = nil) #:nodoc: 8 | @object = object 9 | 10 | super(message) 11 | end 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /gemfiles/data_mapper_0.10.2.gemfile: -------------------------------------------------------------------------------- 1 | # This file was generated by Appraisal 2 | 3 | source "http://www.rubygems.org" 4 | 5 | gem "extlib", "0.9.16" 6 | gem "dm-core", "0.10.2" 7 | gem "dm-migrations", "0.10.2" 8 | gem "dm-validations", "0.10.2" 9 | gem "dm-observer", "0.10.2" 10 | gem "data_objects", "0.10.2" 11 | gem "do_sqlite3", "0.10.2" 12 | 13 | gemspec :path=>"../" -------------------------------------------------------------------------------- /gemfiles/data_mapper_0.9.11.gemfile: -------------------------------------------------------------------------------- 1 | # This file was generated by Appraisal 2 | 3 | source "http://www.rubygems.org" 4 | 5 | gem "extlib", "0.9.11" 6 | gem "dm-core", "0.9.11" 7 | gem "dm-migrations", "0.9.11" 8 | gem "dm-validations", "0.9.11" 9 | gem "dm-observer", "0.9.11" 10 | gem "data_objects", "0.9.11" 11 | gem "do_sqlite3", "0.9.11" 12 | 13 | gemspec :path=>"../" -------------------------------------------------------------------------------- /examples/merb-rest/view_show.html.erb: -------------------------------------------------------------------------------- 1 |

2 | Name: 3 | <%=h @user.name %> 4 |

5 | 6 |

7 | State: 8 | <%=h @user.human_state_name %> 9 |

10 | 11 |

12 | Access State: 13 | <%=h @user.human_access_state_name %> 14 |

15 | 16 | <%= link_to 'Edit', resource(@user, :edit) %> | 17 | <%= link_to 'Back', resource(:users) %> 18 | -------------------------------------------------------------------------------- /lib/state_machine/yard/handlers.rb: -------------------------------------------------------------------------------- 1 | module StateMachine 2 | module YARD 3 | # YARD custom handlers for integrating the state_machine DSL with the 4 | # YARD documentation system 5 | module Handlers 6 | end 7 | end 8 | end 9 | 10 | Dir["#{File.dirname(__FILE__)}/handlers/*.rb"].sort.each do |path| 11 | require "state_machine/yard/handlers/#{File.basename(path)}" 12 | end 13 | -------------------------------------------------------------------------------- /gemfiles/active_record_4.0.0.gemfile: -------------------------------------------------------------------------------- 1 | # This file was generated by Appraisal 2 | 3 | source "http://www.rubygems.org" 4 | 5 | gem "sqlite3", "1.3.6" 6 | gem "activerecord", "4.0.0.beta1", :git=>"git://github.com/rails/rails.git", :ref=>"92d6dac" 7 | gem "activerecord-deprecated_finders", "0.0.3" 8 | gem "protected_attributes", "1.0.0" 9 | gem "rails-observers", "0.1.1" 10 | 11 | gemspec :path=>"../" -------------------------------------------------------------------------------- /examples/rails-rest/view_show.html.erb: -------------------------------------------------------------------------------- 1 |

<%= notice %>

2 | 3 |

4 | Name: 5 | <%= @user.name %> 6 |

7 | 8 |

9 | State: 10 | <%= @user.human_state_name %> 11 |

12 | 13 |

14 | Access State: 15 | <%= @user.human_access_state_name %> 16 |

17 | 18 | <%= link_to 'Edit', edit_user_path(@user) %> | 19 | <%= link_to 'Back', users_path %> 20 | -------------------------------------------------------------------------------- /lib/state_machine.rb: -------------------------------------------------------------------------------- 1 | # By default, requiring "state_machine" means that both the core implementation 2 | # *and* extensions to the Ruby core (Class in particular) will be pulled in. 3 | # 4 | # If you want to skip the Ruby core extensions, simply require "state_machine/core" 5 | # and extend StateMachine::MacroMethods in your class. See the README for more 6 | # information. 7 | require 'state_machine/core' 8 | require 'state_machine/core_ext' 9 | -------------------------------------------------------------------------------- /test/files/en.yml: -------------------------------------------------------------------------------- 1 | en: 2 | activerecord: 3 | errors: 4 | messages: 5 | invalid_transition: "cannot transition" 6 | activemodel: 7 | errors: 8 | messages: 9 | invalid_transition: "cannot %{event}" 10 | mongoid: 11 | errors: 12 | messages: 13 | invalid_transition: "cannot transition" 14 | mongo_mapper: 15 | errors: 16 | messages: 17 | invalid_transition: "cannot transition" 18 | -------------------------------------------------------------------------------- /lib/state_machine/integrations/active_model/locale.rb: -------------------------------------------------------------------------------- 1 | {:en => { 2 | :activemodel => { 3 | :errors => { 4 | :messages => { 5 | :invalid => StateMachine::Machine.default_messages[:invalid], 6 | :invalid_event => StateMachine::Machine.default_messages[:invalid_event] % ['%{state}'], 7 | :invalid_transition => StateMachine::Machine.default_messages[:invalid_transition] % ['%{event}'] 8 | } 9 | } 10 | } 11 | }} 12 | -------------------------------------------------------------------------------- /examples/car.rb: -------------------------------------------------------------------------------- 1 | require 'state_machine' 2 | 3 | class Car < Vehicle 4 | state_machine do 5 | event :reverse do 6 | transition [:parked, :idling, :first_gear] => :backing_up 7 | end 8 | 9 | event :park do 10 | transition :backing_up => :parked 11 | end 12 | 13 | event :idle do 14 | transition :backing_up => :idling 15 | end 16 | 17 | event :shift_up do 18 | transition :backing_up => :first_gear 19 | end 20 | end 21 | end 22 | -------------------------------------------------------------------------------- /lib/state_machine/yard/templates/default/class/html/state_machines.erb: -------------------------------------------------------------------------------- 1 |

State Machines

2 | 3 | This class contains <%= state_machines.count %> state machine(s). 4 | 5 | <% state_machines.each do |name, machine| %> 6 |

<%= h(machine[:name]) %>

7 |

<%= h(machine[:description]) %>

8 | 9 | <% if machine[:image] %> 10 | State machine diagram for <%= h(machine[:name]) %> 11 | <% end %> 12 | <% end %> 13 | -------------------------------------------------------------------------------- /examples/doc/frames.html: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 7 | Documentation by YARD 0.7.5 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /lib/state_machine/core.rb: -------------------------------------------------------------------------------- 1 | module StateMachine 2 | # Graphing extensions aren't required, so they're loaded when referenced 3 | autoload :Graph, 'state_machine/graph' 4 | end 5 | 6 | # Load all of the core implementation required to use state_machine. This 7 | # includes: 8 | # * StateMachine::MacroMethods which adds the state_machine DSL to your class 9 | # * A set of initializers for setting state_machine defaults based on the current 10 | # running environment (such as within Rails) 11 | require 'state_machine/macro_methods' 12 | require 'state_machine/initializers' 13 | -------------------------------------------------------------------------------- /gemfiles/default.gemfile.lock: -------------------------------------------------------------------------------- 1 | PATH 2 | remote: /home/aaron/Projects/Personal/pluginaweek/state_machine 3 | specs: 4 | state_machine (1.2.0) 5 | 6 | GEM 7 | remote: http://www.rubygems.org/ 8 | specs: 9 | appraisal (0.5.1) 10 | bundler 11 | rake 12 | multi_json (1.0.4) 13 | rake (0.9.2.2) 14 | simplecov (0.5.4) 15 | multi_json (~> 1.0.3) 16 | simplecov-html (~> 0.5.3) 17 | simplecov-html (0.5.3) 18 | 19 | PLATFORMS 20 | java 21 | ruby 22 | 23 | DEPENDENCIES 24 | appraisal (~> 0.5.0) 25 | rake 26 | simplecov 27 | state_machine! 28 | -------------------------------------------------------------------------------- /test/unit/helper_module_test.rb: -------------------------------------------------------------------------------- 1 | require File.expand_path(File.dirname(__FILE__) + '/../test_helper') 2 | 3 | class HelperModuleTest < Test::Unit::TestCase 4 | def setup 5 | @klass = Class.new 6 | @machine = StateMachine::Machine.new(@klass) 7 | @helper_module = StateMachine::HelperModule.new(@machine, :instance) 8 | end 9 | 10 | def test_should_not_have_a_name 11 | assert_equal '', @helper_module.name.to_s 12 | end 13 | 14 | def test_should_provide_human_readable_to_s 15 | assert_equal "#{@klass} :state instance helpers", @helper_module.to_s 16 | end 17 | end 18 | -------------------------------------------------------------------------------- /examples/merb-rest/view_index.html.erb: -------------------------------------------------------------------------------- 1 |

Listing Users

2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | <% @users.each do |user| %> 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | <% end %> 19 |
NameStateAccess State
<%=h user.name %><%=h user.human_state_name %><%=h user.human_access_state_name %><%= link_to 'Show', resource(user) %><%= link_to 'Edit', resource(user, :edit) %>
20 | 21 |
22 | 23 | <%= link_to 'New User', resource(:users, :new) %> 24 | -------------------------------------------------------------------------------- /test/unit/invalid_parallel_transition_test.rb: -------------------------------------------------------------------------------- 1 | require File.expand_path(File.dirname(__FILE__) + '/../test_helper') 2 | 3 | class InvalidParallelTransitionTest < Test::Unit::TestCase 4 | def setup 5 | @object = Object.new 6 | @events = [:ignite, :disable_alarm] 7 | 8 | @invalid_transition = StateMachine::InvalidParallelTransition.new(@object, @events) 9 | end 10 | 11 | def test_should_have_an_object 12 | assert_equal @object, @invalid_transition.object 13 | end 14 | 15 | def test_should_have_events 16 | assert_equal @events, @invalid_transition.events 17 | end 18 | end 19 | -------------------------------------------------------------------------------- /examples/rails-rest/view_index.html.erb: -------------------------------------------------------------------------------- 1 |

Listing users

2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | <% @users.each do |user| %> 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | <% end %> 21 |
NameStateAccess State
<%= user.name %><%= user.human_state_name %><%= user.human_access_state_name %><%= link_to 'Show', user %><%= link_to 'Edit', edit_user_path(user) %>
22 | 23 |
24 | 25 | <%= link_to 'New User', new_user_path %> 26 | -------------------------------------------------------------------------------- /examples/rails-rest/model.rb: -------------------------------------------------------------------------------- 1 | class User < ActiveRecord::Base 2 | validates_presence_of :name, :state, :access_state 3 | 4 | state_machine :initial => :unregistered do 5 | event :register do 6 | transition :unregistered => :registered 7 | end 8 | 9 | event :unregister do 10 | transition :registered => :unregistered 11 | end 12 | end 13 | 14 | state_machine :access_state, :initial => :enabled do 15 | event :enable do 16 | transition all => :enabled 17 | end 18 | 19 | event :disable do 20 | transition all => :disabled 21 | end 22 | end 23 | end 24 | -------------------------------------------------------------------------------- /lib/state_machine/helper_module.rb: -------------------------------------------------------------------------------- 1 | module StateMachine 2 | # Represents a type of module that defines instance / class methods for a 3 | # state machine 4 | class HelperModule < Module #:nodoc: 5 | def initialize(machine, kind) 6 | @machine = machine 7 | @kind = kind 8 | end 9 | 10 | # Provides a human-readable description of the module 11 | def to_s 12 | owner_class = @machine.owner_class 13 | owner_class_name = owner_class.name && !owner_class.name.empty? ? owner_class.name : owner_class.to_s 14 | "#{owner_class_name} #{@machine.name.inspect} #{@kind} helpers" 15 | end 16 | end 17 | end 18 | -------------------------------------------------------------------------------- /test/unit/invalid_event_test.rb: -------------------------------------------------------------------------------- 1 | require File.expand_path(File.dirname(__FILE__) + '/../test_helper') 2 | 3 | class InvalidEventTest < Test::Unit::TestCase 4 | def setup 5 | @object = Object.new 6 | @invalid_event = StateMachine::InvalidEvent.new(@object, :invalid) 7 | end 8 | 9 | def test_should_have_an_object 10 | assert_equal @object, @invalid_event.object 11 | end 12 | 13 | def test_should_have_an_event 14 | assert_equal :invalid, @invalid_event.event 15 | end 16 | 17 | def test_should_generate_a_message 18 | assert_equal ':invalid is an unknown state machine event', @invalid_event.message 19 | end 20 | end 21 | -------------------------------------------------------------------------------- /gemfiles/graphviz_1.0.3.gemfile.lock: -------------------------------------------------------------------------------- 1 | PATH 2 | remote: /home/aaron/Projects/Personal/pluginaweek/state_machine 3 | specs: 4 | state_machine (1.2.0) 5 | 6 | GEM 7 | remote: http://www.rubygems.org/ 8 | specs: 9 | appraisal (0.5.1) 10 | bundler 11 | rake 12 | multi_json (1.6.1) 13 | rake (10.0.3) 14 | ruby-graphviz (1.0.3) 15 | simplecov (0.7.1) 16 | multi_json (~> 1.0) 17 | simplecov-html (~> 0.7.1) 18 | simplecov-html (0.7.1) 19 | 20 | PLATFORMS 21 | java 22 | ruby 23 | 24 | DEPENDENCIES 25 | appraisal (~> 0.5.0) 26 | rake 27 | ruby-graphviz (= 1.0.3) 28 | simplecov 29 | state_machine! 30 | -------------------------------------------------------------------------------- /gemfiles/graphviz_1.0.8.gemfile.lock: -------------------------------------------------------------------------------- 1 | PATH 2 | remote: /home/aaron/Projects/Personal/pluginaweek/state_machine 3 | specs: 4 | state_machine (1.2.0) 5 | 6 | GEM 7 | remote: http://www.rubygems.org/ 8 | specs: 9 | appraisal (0.5.1) 10 | bundler 11 | rake 12 | multi_json (1.6.1) 13 | rake (10.0.3) 14 | ruby-graphviz (1.0.8) 15 | simplecov (0.7.1) 16 | multi_json (~> 1.0) 17 | simplecov-html (~> 0.7.1) 18 | simplecov-html (0.7.1) 19 | 20 | PLATFORMS 21 | java 22 | ruby 23 | 24 | DEPENDENCIES 25 | appraisal (~> 0.5.0) 26 | rake 27 | ruby-graphviz (= 1.0.8) 28 | simplecov 29 | state_machine! 30 | -------------------------------------------------------------------------------- /gemfiles/graphviz_0.9.17.gemfile.lock: -------------------------------------------------------------------------------- 1 | PATH 2 | remote: /home/aaron/Projects/Personal/pluginaweek/state_machine 3 | specs: 4 | state_machine (1.2.0) 5 | 6 | GEM 7 | remote: http://www.rubygems.org/ 8 | specs: 9 | appraisal (0.5.1) 10 | bundler 11 | rake 12 | multi_json (1.6.1) 13 | rake (10.0.3) 14 | ruby-graphviz (0.9.17) 15 | simplecov (0.7.1) 16 | multi_json (~> 1.0) 17 | simplecov-html (~> 0.7.1) 18 | simplecov-html (0.7.1) 19 | 20 | PLATFORMS 21 | java 22 | ruby 23 | 24 | DEPENDENCIES 25 | appraisal (~> 0.5.0) 26 | rake 27 | ruby-graphviz (= 0.9.17) 28 | simplecov 29 | state_machine! 30 | -------------------------------------------------------------------------------- /gemfiles/graphviz_0.9.21.gemfile.lock: -------------------------------------------------------------------------------- 1 | PATH 2 | remote: /home/aaron/Projects/Personal/pluginaweek/state_machine 3 | specs: 4 | state_machine (1.2.0) 5 | 6 | GEM 7 | remote: http://www.rubygems.org/ 8 | specs: 9 | appraisal (0.5.1) 10 | bundler 11 | rake 12 | multi_json (1.0.4) 13 | rake (0.9.2.2) 14 | ruby-graphviz (0.9.21) 15 | simplecov (0.5.4) 16 | multi_json (~> 1.0.3) 17 | simplecov-html (~> 0.5.3) 18 | simplecov-html (0.5.3) 19 | 20 | PLATFORMS 21 | java 22 | ruby 23 | 24 | DEPENDENCIES 25 | appraisal (~> 0.5.0) 26 | rake 27 | ruby-graphviz (= 0.9.21) 28 | simplecov 29 | state_machine! 30 | -------------------------------------------------------------------------------- /gemfiles/graphviz_1.0.0.gemfile.lock: -------------------------------------------------------------------------------- 1 | PATH 2 | remote: /home/aaron/Projects/Personal/pluginaweek/state_machine 3 | specs: 4 | state_machine (1.2.0) 5 | 6 | GEM 7 | remote: http://www.rubygems.org/ 8 | specs: 9 | appraisal (0.5.1) 10 | bundler 11 | rake 12 | multi_json (1.0.4) 13 | rake (0.9.2.2) 14 | ruby-graphviz (1.0.0) 15 | simplecov (0.5.4) 16 | multi_json (~> 1.0.3) 17 | simplecov-html (~> 0.5.3) 18 | simplecov-html (0.5.3) 19 | 20 | PLATFORMS 21 | java 22 | ruby 23 | 24 | DEPENDENCIES 25 | appraisal (~> 0.5.0) 26 | rake 27 | ruby-graphviz (= 1.0.0) 28 | simplecov 29 | state_machine! 30 | -------------------------------------------------------------------------------- /examples/merb-rest/model.rb: -------------------------------------------------------------------------------- 1 | class User 2 | include DataMapper::Resource 3 | 4 | property :id, Serial 5 | property :name, String 6 | 7 | validates_present :name, :state, :access_state 8 | 9 | state_machine :initial => :unregistered do 10 | event :register do 11 | transition :unregistered => :registered 12 | end 13 | 14 | event :unregister do 15 | transition :registered => :unregistered 16 | end 17 | end 18 | 19 | state_machine :access_state, :initial => :enabled do 20 | event :enable do 21 | transition all => :enabled 22 | end 23 | 24 | event :disable do 25 | transition all => :disabled 26 | end 27 | end 28 | end 29 | -------------------------------------------------------------------------------- /gemfiles/sequel_2.8.0.gemfile.lock: -------------------------------------------------------------------------------- 1 | PATH 2 | remote: /home/aaron/Projects/Personal/pluginaweek/state_machine 3 | specs: 4 | state_machine (1.2.0) 5 | 6 | GEM 7 | remote: http://www.rubygems.org/ 8 | specs: 9 | appraisal (0.5.1) 10 | bundler 11 | rake 12 | jdbc-sqlite3 (3.7.2) 13 | multi_json (1.6.1) 14 | rake (10.0.3) 15 | sequel (2.8.0) 16 | simplecov (0.7.1) 17 | multi_json (~> 1.0) 18 | simplecov-html (~> 0.7.1) 19 | simplecov-html (0.7.1) 20 | sqlite3-ruby (1.3.1) 21 | 22 | PLATFORMS 23 | java 24 | ruby 25 | 26 | DEPENDENCIES 27 | appraisal (~> 0.5.0) 28 | jdbc-sqlite3 (= 3.7.2) 29 | rake 30 | sequel (= 2.8.0) 31 | simplecov 32 | sqlite3-ruby (= 1.3.1) 33 | state_machine! 34 | -------------------------------------------------------------------------------- /gemfiles/sequel_3.0.0.gemfile.lock: -------------------------------------------------------------------------------- 1 | PATH 2 | remote: /home/aaron/Projects/Personal/pluginaweek/state_machine 3 | specs: 4 | state_machine (1.2.0) 5 | 6 | GEM 7 | remote: http://www.rubygems.org/ 8 | specs: 9 | appraisal (0.5.1) 10 | bundler 11 | rake 12 | jdbc-sqlite3 (3.7.2) 13 | multi_json (1.6.1) 14 | rake (10.0.3) 15 | sequel (3.0.0) 16 | simplecov (0.7.1) 17 | multi_json (~> 1.0) 18 | simplecov-html (~> 0.7.1) 19 | simplecov-html (0.7.1) 20 | sqlite3-ruby (1.3.1) 21 | 22 | PLATFORMS 23 | java 24 | ruby 25 | 26 | DEPENDENCIES 27 | appraisal (~> 0.5.0) 28 | jdbc-sqlite3 (= 3.7.2) 29 | rake 30 | sequel (= 3.0.0) 31 | simplecov 32 | sqlite3-ruby (= 1.3.1) 33 | state_machine! 34 | -------------------------------------------------------------------------------- /gemfiles/sequel_3.4.0.gemfile.lock: -------------------------------------------------------------------------------- 1 | PATH 2 | remote: /home/aaron/Projects/Personal/pluginaweek/state_machine 3 | specs: 4 | state_machine (1.2.0) 5 | 6 | GEM 7 | remote: http://www.rubygems.org/ 8 | specs: 9 | appraisal (0.5.1) 10 | bundler 11 | rake 12 | jdbc-sqlite3 (3.7.2) 13 | multi_json (1.6.1) 14 | rake (10.0.3) 15 | sequel (3.4.0) 16 | simplecov (0.7.1) 17 | multi_json (~> 1.0) 18 | simplecov-html (~> 0.7.1) 19 | simplecov-html (0.7.1) 20 | sqlite3-ruby (1.3.1) 21 | 22 | PLATFORMS 23 | java 24 | ruby 25 | 26 | DEPENDENCIES 27 | appraisal (~> 0.5.0) 28 | jdbc-sqlite3 (= 3.7.2) 29 | rake 30 | sequel (= 3.4.0) 31 | simplecov 32 | sqlite3-ruby (= 1.3.1) 33 | state_machine! 34 | -------------------------------------------------------------------------------- /gemfiles/sequel_2.11.0.gemfile.lock: -------------------------------------------------------------------------------- 1 | PATH 2 | remote: /home/aaron/Projects/Personal/pluginaweek/state_machine 3 | specs: 4 | state_machine (1.2.0) 5 | 6 | GEM 7 | remote: http://www.rubygems.org/ 8 | specs: 9 | appraisal (0.5.1) 10 | bundler 11 | rake 12 | jdbc-sqlite3 (3.7.2) 13 | multi_json (1.6.1) 14 | rake (10.0.3) 15 | sequel (2.11.0) 16 | simplecov (0.7.1) 17 | multi_json (~> 1.0) 18 | simplecov-html (~> 0.7.1) 19 | simplecov-html (0.7.1) 20 | sqlite3-ruby (1.3.1) 21 | 22 | PLATFORMS 23 | java 24 | ruby 25 | 26 | DEPENDENCIES 27 | appraisal (~> 0.5.0) 28 | jdbc-sqlite3 (= 3.7.2) 29 | rake 30 | sequel (= 2.11.0) 31 | simplecov 32 | sqlite3-ruby (= 1.3.1) 33 | state_machine! 34 | -------------------------------------------------------------------------------- /gemfiles/sequel_2.12.0.gemfile.lock: -------------------------------------------------------------------------------- 1 | PATH 2 | remote: /home/aaron/Projects/Personal/pluginaweek/state_machine 3 | specs: 4 | state_machine (1.2.0) 5 | 6 | GEM 7 | remote: http://www.rubygems.org/ 8 | specs: 9 | appraisal (0.5.1) 10 | bundler 11 | rake 12 | jdbc-sqlite3 (3.7.2) 13 | multi_json (1.6.1) 14 | rake (10.0.3) 15 | sequel (2.12.0) 16 | simplecov (0.7.1) 17 | multi_json (~> 1.0) 18 | simplecov-html (~> 0.7.1) 19 | simplecov-html (0.7.1) 20 | sqlite3-ruby (1.3.1) 21 | 22 | PLATFORMS 23 | java 24 | ruby 25 | 26 | DEPENDENCIES 27 | appraisal (~> 0.5.0) 28 | jdbc-sqlite3 (= 3.7.2) 29 | rake 30 | sequel (= 2.12.0) 31 | simplecov 32 | sqlite3-ruby (= 1.3.1) 33 | state_machine! 34 | -------------------------------------------------------------------------------- /gemfiles/sequel_3.10.0.gemfile.lock: -------------------------------------------------------------------------------- 1 | PATH 2 | remote: /home/aaron/Projects/Personal/pluginaweek/state_machine 3 | specs: 4 | state_machine (1.2.0) 5 | 6 | GEM 7 | remote: http://www.rubygems.org/ 8 | specs: 9 | appraisal (0.5.1) 10 | bundler 11 | rake 12 | jdbc-sqlite3 (3.7.2) 13 | multi_json (1.6.1) 14 | rake (10.0.3) 15 | sequel (3.10.0) 16 | simplecov (0.7.1) 17 | multi_json (~> 1.0) 18 | simplecov-html (~> 0.7.1) 19 | simplecov-html (0.7.1) 20 | sqlite3-ruby (1.3.1) 21 | 22 | PLATFORMS 23 | java 24 | ruby 25 | 26 | DEPENDENCIES 27 | appraisal (~> 0.5.0) 28 | jdbc-sqlite3 (= 3.7.2) 29 | rake 30 | sequel (= 3.10.0) 31 | simplecov 32 | sqlite3-ruby (= 1.3.1) 33 | state_machine! 34 | -------------------------------------------------------------------------------- /gemfiles/sequel_3.13.0.gemfile.lock: -------------------------------------------------------------------------------- 1 | PATH 2 | remote: /home/aaron/Projects/Personal/pluginaweek/state_machine 3 | specs: 4 | state_machine (1.2.0) 5 | 6 | GEM 7 | remote: http://www.rubygems.org/ 8 | specs: 9 | appraisal (0.5.1) 10 | bundler 11 | rake 12 | jdbc-sqlite3 (3.7.2) 13 | multi_json (1.6.1) 14 | rake (10.0.3) 15 | sequel (3.13.0) 16 | simplecov (0.7.1) 17 | multi_json (~> 1.0) 18 | simplecov-html (~> 0.7.1) 19 | simplecov-html (0.7.1) 20 | sqlite3-ruby (1.3.1) 21 | 22 | PLATFORMS 23 | java 24 | ruby 25 | 26 | DEPENDENCIES 27 | appraisal (~> 0.5.0) 28 | jdbc-sqlite3 (= 3.7.2) 29 | rake 30 | sequel (= 3.13.0) 31 | simplecov 32 | sqlite3-ruby (= 1.3.1) 33 | state_machine! 34 | -------------------------------------------------------------------------------- /gemfiles/sequel_3.14.0.gemfile.lock: -------------------------------------------------------------------------------- 1 | PATH 2 | remote: /home/aaron/Projects/Personal/pluginaweek/state_machine 3 | specs: 4 | state_machine (1.2.0) 5 | 6 | GEM 7 | remote: http://www.rubygems.org/ 8 | specs: 9 | appraisal (0.5.1) 10 | bundler 11 | rake 12 | jdbc-sqlite3 (3.7.2) 13 | multi_json (1.6.1) 14 | rake (10.0.3) 15 | sequel (3.14.0) 16 | simplecov (0.7.1) 17 | multi_json (~> 1.0) 18 | simplecov-html (~> 0.7.1) 19 | simplecov-html (0.7.1) 20 | sqlite3-ruby (1.3.1) 21 | 22 | PLATFORMS 23 | java 24 | ruby 25 | 26 | DEPENDENCIES 27 | appraisal (~> 0.5.0) 28 | jdbc-sqlite3 (= 3.7.2) 29 | rake 30 | sequel (= 3.14.0) 31 | simplecov 32 | sqlite3-ruby (= 1.3.1) 33 | state_machine! 34 | -------------------------------------------------------------------------------- /gemfiles/sequel_3.23.0.gemfile.lock: -------------------------------------------------------------------------------- 1 | PATH 2 | remote: /home/aaron/Projects/Personal/pluginaweek/state_machine 3 | specs: 4 | state_machine (1.2.0) 5 | 6 | GEM 7 | remote: http://www.rubygems.org/ 8 | specs: 9 | appraisal (0.5.1) 10 | bundler 11 | rake 12 | jdbc-sqlite3 (3.7.2) 13 | multi_json (1.6.1) 14 | rake (10.0.3) 15 | sequel (3.23.0) 16 | simplecov (0.7.1) 17 | multi_json (~> 1.0) 18 | simplecov-html (~> 0.7.1) 19 | simplecov-html (0.7.1) 20 | sqlite3-ruby (1.3.1) 21 | 22 | PLATFORMS 23 | java 24 | ruby 25 | 26 | DEPENDENCIES 27 | appraisal (~> 0.5.0) 28 | jdbc-sqlite3 (= 3.7.2) 29 | rake 30 | sequel (= 3.23.0) 31 | simplecov 32 | sqlite3-ruby (= 1.3.1) 33 | state_machine! 34 | -------------------------------------------------------------------------------- /gemfiles/sequel_3.24.0.gemfile.lock: -------------------------------------------------------------------------------- 1 | PATH 2 | remote: /home/aaron/Projects/Personal/pluginaweek/state_machine 3 | specs: 4 | state_machine (1.2.0) 5 | 6 | GEM 7 | remote: http://www.rubygems.org/ 8 | specs: 9 | appraisal (0.5.1) 10 | bundler 11 | rake 12 | jdbc-sqlite3 (3.7.2) 13 | multi_json (1.6.1) 14 | rake (10.0.3) 15 | sequel (3.24.0) 16 | simplecov (0.7.1) 17 | multi_json (~> 1.0) 18 | simplecov-html (~> 0.7.1) 19 | simplecov-html (0.7.1) 20 | sqlite3-ruby (1.3.1) 21 | 22 | PLATFORMS 23 | java 24 | ruby 25 | 26 | DEPENDENCIES 27 | appraisal (~> 0.5.0) 28 | jdbc-sqlite3 (= 3.7.2) 29 | rake 30 | sequel (= 3.24.0) 31 | simplecov 32 | sqlite3-ruby (= 1.3.1) 33 | state_machine! 34 | -------------------------------------------------------------------------------- /gemfiles/sequel_3.29.0.gemfile.lock: -------------------------------------------------------------------------------- 1 | PATH 2 | remote: /home/aaron/Projects/Personal/pluginaweek/state_machine 3 | specs: 4 | state_machine (1.2.0) 5 | 6 | GEM 7 | remote: http://www.rubygems.org/ 8 | specs: 9 | appraisal (0.5.1) 10 | bundler 11 | rake 12 | jdbc-sqlite3 (3.7.2) 13 | multi_json (1.6.1) 14 | rake (10.0.3) 15 | sequel (3.29.0) 16 | simplecov (0.7.1) 17 | multi_json (~> 1.0) 18 | simplecov-html (~> 0.7.1) 19 | simplecov-html (0.7.1) 20 | sqlite3-ruby (1.3.1) 21 | 22 | PLATFORMS 23 | java 24 | ruby 25 | 26 | DEPENDENCIES 27 | appraisal (~> 0.5.0) 28 | jdbc-sqlite3 (= 3.7.2) 29 | rake 30 | sequel (= 3.29.0) 31 | simplecov 32 | sqlite3-ruby (= 1.3.1) 33 | state_machine! 34 | -------------------------------------------------------------------------------- /gemfiles/sequel_3.34.0.gemfile.lock: -------------------------------------------------------------------------------- 1 | PATH 2 | remote: /home/aaron/Projects/Personal/pluginaweek/state_machine 3 | specs: 4 | state_machine (1.2.0) 5 | 6 | GEM 7 | remote: http://www.rubygems.org/ 8 | specs: 9 | appraisal (0.5.1) 10 | bundler 11 | rake 12 | jdbc-sqlite3 (3.7.2) 13 | multi_json (1.6.1) 14 | rake (10.0.3) 15 | sequel (3.34.0) 16 | simplecov (0.7.1) 17 | multi_json (~> 1.0) 18 | simplecov-html (~> 0.7.1) 19 | simplecov-html (0.7.1) 20 | sqlite3-ruby (1.3.1) 21 | 22 | PLATFORMS 23 | java 24 | ruby 25 | 26 | DEPENDENCIES 27 | appraisal (~> 0.5.0) 28 | jdbc-sqlite3 (= 3.7.2) 29 | rake 30 | sequel (= 3.34.0) 31 | simplecov 32 | sqlite3-ruby (= 1.3.1) 33 | state_machine! 34 | -------------------------------------------------------------------------------- /gemfiles/sequel_3.35.0.gemfile.lock: -------------------------------------------------------------------------------- 1 | PATH 2 | remote: /home/aaron/Projects/Personal/pluginaweek/state_machine 3 | specs: 4 | state_machine (1.2.0) 5 | 6 | GEM 7 | remote: http://www.rubygems.org/ 8 | specs: 9 | appraisal (0.5.1) 10 | bundler 11 | rake 12 | jdbc-sqlite3 (3.7.2) 13 | multi_json (1.6.1) 14 | rake (10.0.3) 15 | sequel (3.35.0) 16 | simplecov (0.7.1) 17 | multi_json (~> 1.0) 18 | simplecov-html (~> 0.7.1) 19 | simplecov-html (0.7.1) 20 | sqlite3-ruby (1.3.1) 21 | 22 | PLATFORMS 23 | java 24 | ruby 25 | 26 | DEPENDENCIES 27 | appraisal (~> 0.5.0) 28 | jdbc-sqlite3 (= 3.7.2) 29 | rake 30 | sequel (= 3.35.0) 31 | simplecov 32 | sqlite3-ruby (= 1.3.1) 33 | state_machine! 34 | -------------------------------------------------------------------------------- /gemfiles/sequel_3.44.0.gemfile.lock: -------------------------------------------------------------------------------- 1 | PATH 2 | remote: /home/aaron/Projects/Personal/pluginaweek/state_machine 3 | specs: 4 | state_machine (1.2.0) 5 | 6 | GEM 7 | remote: http://www.rubygems.org/ 8 | specs: 9 | appraisal (0.5.1) 10 | bundler 11 | rake 12 | jdbc-sqlite3 (3.7.2) 13 | multi_json (1.6.1) 14 | rake (10.0.3) 15 | sequel (3.44.0) 16 | simplecov (0.7.1) 17 | multi_json (~> 1.0) 18 | simplecov-html (~> 0.7.1) 19 | simplecov-html (0.7.1) 20 | sqlite3-ruby (1.3.1) 21 | 22 | PLATFORMS 23 | java 24 | ruby 25 | 26 | DEPENDENCIES 27 | appraisal (~> 0.5.0) 28 | jdbc-sqlite3 (= 3.7.2) 29 | rake 30 | sequel (= 3.44.0) 31 | simplecov 32 | sqlite3-ruby (= 1.3.1) 33 | state_machine! 34 | -------------------------------------------------------------------------------- /lib/state_machine/yard/handlers/event.rb: -------------------------------------------------------------------------------- 1 | module StateMachine 2 | module YARD 3 | module Handlers 4 | # Handles and processes #event 5 | class Event < Base 6 | handles method_call(:event) 7 | 8 | def process 9 | if owner.is_a?(StateMachine::Machine) 10 | handler = self 11 | statement = self.statement 12 | names = extract_node_names(statement.parameters(false)) 13 | 14 | names.each do |name| 15 | owner.event(name) do 16 | # Parse the block 17 | handler.parse_block(statement.last.last, :owner => self) 18 | end 19 | end 20 | end 21 | end 22 | end 23 | end 24 | end 25 | end 26 | -------------------------------------------------------------------------------- /lib/state_machine/yard/handlers/state.rb: -------------------------------------------------------------------------------- 1 | module StateMachine 2 | module YARD 3 | module Handlers 4 | # Handles and processes #state 5 | class State < Base 6 | handles method_call(:state) 7 | 8 | def process 9 | if owner.is_a?(StateMachine::Machine) 10 | handler = self 11 | statement = self.statement 12 | names = extract_node_names(statement.parameters(false)) 13 | 14 | names.each do |name| 15 | owner.state(name) do 16 | # Parse the block 17 | handler.parse_block(statement.last.last, :owner => self) 18 | end 19 | end 20 | end 21 | end 22 | end 23 | end 24 | end 25 | end 26 | -------------------------------------------------------------------------------- /gemfiles/active_model_3.0.0.gemfile.lock: -------------------------------------------------------------------------------- 1 | PATH 2 | remote: /home/aaron/Projects/Personal/pluginaweek/state_machine 3 | specs: 4 | state_machine (1.2.0) 5 | 6 | GEM 7 | remote: http://www.rubygems.org/ 8 | specs: 9 | activemodel (3.0.0) 10 | activesupport (= 3.0.0) 11 | builder (~> 2.1.2) 12 | i18n (~> 0.4.1) 13 | activesupport (3.0.0) 14 | appraisal (0.5.1) 15 | bundler 16 | rake 17 | builder (2.1.2) 18 | i18n (0.4.2) 19 | multi_json (1.6.1) 20 | rake (10.0.3) 21 | simplecov (0.7.1) 22 | multi_json (~> 1.0) 23 | simplecov-html (~> 0.7.1) 24 | simplecov-html (0.7.1) 25 | 26 | PLATFORMS 27 | java 28 | ruby 29 | 30 | DEPENDENCIES 31 | activemodel (= 3.0.0) 32 | appraisal (~> 0.5.0) 33 | rake 34 | simplecov 35 | state_machine! 36 | -------------------------------------------------------------------------------- /gemfiles/active_model_3.0.5.gemfile.lock: -------------------------------------------------------------------------------- 1 | PATH 2 | remote: /home/aaron/Projects/Personal/pluginaweek/state_machine 3 | specs: 4 | state_machine (1.2.0) 5 | 6 | GEM 7 | remote: http://www.rubygems.org/ 8 | specs: 9 | activemodel (3.0.5) 10 | activesupport (= 3.0.5) 11 | builder (~> 2.1.2) 12 | i18n (~> 0.4) 13 | activesupport (3.0.5) 14 | appraisal (0.5.1) 15 | bundler 16 | rake 17 | builder (2.1.2) 18 | i18n (0.6.1) 19 | multi_json (1.6.1) 20 | rake (10.0.3) 21 | simplecov (0.7.1) 22 | multi_json (~> 1.0) 23 | simplecov-html (~> 0.7.1) 24 | simplecov-html (0.7.1) 25 | 26 | PLATFORMS 27 | java 28 | ruby 29 | 30 | DEPENDENCIES 31 | activemodel (= 3.0.5) 32 | appraisal (~> 0.5.0) 33 | rake 34 | simplecov 35 | state_machine! 36 | -------------------------------------------------------------------------------- /test/unit/state_machine_test.rb: -------------------------------------------------------------------------------- 1 | require File.expand_path(File.dirname(__FILE__) + '/../test_helper') 2 | 3 | class StateMachineByDefaultTest < Test::Unit::TestCase 4 | def setup 5 | @klass = Class.new 6 | @machine = @klass.state_machine 7 | end 8 | 9 | def test_should_use_state_attribute 10 | assert_equal :state, @machine.attribute 11 | end 12 | end 13 | 14 | class StateMachineTest < Test::Unit::TestCase 15 | def setup 16 | @klass = Class.new 17 | end 18 | 19 | def test_should_allow_state_machines_on_any_class 20 | assert @klass.respond_to?(:state_machine) 21 | end 22 | 23 | def test_should_evaluate_block_within_machine_context 24 | responded = false 25 | @klass.state_machine(:state) do 26 | responded = respond_to?(:event) 27 | end 28 | 29 | assert responded 30 | end 31 | end 32 | -------------------------------------------------------------------------------- /gemfiles/active_model_3.1.1.gemfile.lock: -------------------------------------------------------------------------------- 1 | PATH 2 | remote: /home/aaron/Projects/Personal/pluginaweek/state_machine 3 | specs: 4 | state_machine (1.2.0) 5 | 6 | GEM 7 | remote: http://www.rubygems.org/ 8 | specs: 9 | activemodel (3.1.1) 10 | activesupport (= 3.1.1) 11 | builder (~> 3.0.0) 12 | i18n (~> 0.6) 13 | activesupport (3.1.1) 14 | multi_json (~> 1.0) 15 | appraisal (0.5.1) 16 | bundler 17 | rake 18 | builder (3.0.4) 19 | i18n (0.6.1) 20 | multi_json (1.6.1) 21 | rake (10.0.3) 22 | simplecov (0.7.1) 23 | multi_json (~> 1.0) 24 | simplecov-html (~> 0.7.1) 25 | simplecov-html (0.7.1) 26 | 27 | PLATFORMS 28 | java 29 | ruby 30 | 31 | DEPENDENCIES 32 | activemodel (= 3.1.1) 33 | appraisal (~> 0.5.0) 34 | rake 35 | simplecov 36 | state_machine! 37 | -------------------------------------------------------------------------------- /gemfiles/active_model_3.2.12.gemfile.lock: -------------------------------------------------------------------------------- 1 | PATH 2 | remote: /home/aaron/Projects/Personal/pluginaweek/state_machine 3 | specs: 4 | state_machine (1.2.0) 5 | 6 | GEM 7 | remote: http://www.rubygems.org/ 8 | specs: 9 | activemodel (3.2.12) 10 | activesupport (= 3.2.12) 11 | builder (~> 3.0.0) 12 | activesupport (3.2.12) 13 | i18n (~> 0.6) 14 | multi_json (~> 1.0) 15 | appraisal (0.5.1) 16 | bundler 17 | rake 18 | builder (3.0.4) 19 | i18n (0.6.1) 20 | multi_json (1.6.1) 21 | rake (10.0.3) 22 | simplecov (0.7.1) 23 | multi_json (~> 1.0) 24 | simplecov-html (~> 0.7.1) 25 | simplecov-html (0.7.1) 26 | 27 | PLATFORMS 28 | java 29 | ruby 30 | 31 | DEPENDENCIES 32 | activemodel (= 3.2.12) 33 | appraisal (~> 0.5.0) 34 | rake 35 | simplecov 36 | state_machine! 37 | -------------------------------------------------------------------------------- /lib/state_machine/initializers/rails.rb: -------------------------------------------------------------------------------- 1 | if defined?(Rails) 2 | # Track all of the applicable locales to load 3 | locale_paths = [] 4 | StateMachine::Integrations.all.each do |integration| 5 | locale_paths << integration.locale_path if integration.available? && integration.locale_path 6 | end 7 | 8 | if defined?(Rails::Engine) 9 | # Rails 3.x 10 | class StateMachine::RailsEngine < Rails::Engine 11 | rake_tasks do 12 | load 'tasks/state_machine.rb' 13 | end 14 | end 15 | 16 | if Rails::VERSION::MAJOR == 3 && Rails::VERSION::MINOR == 0 17 | StateMachine::RailsEngine.paths.config.locales = locale_paths 18 | else 19 | StateMachine::RailsEngine.paths['config/locales'] = locale_paths 20 | end 21 | elsif defined?(I18n) 22 | # Rails 2.x 23 | I18n.load_path.unshift(*locale_paths) 24 | end 25 | end 26 | -------------------------------------------------------------------------------- /gemfiles/active_model_3.2.13.rc1.gemfile.lock: -------------------------------------------------------------------------------- 1 | PATH 2 | remote: /home/aaron/Projects/Personal/pluginaweek/state_machine 3 | specs: 4 | state_machine (1.2.0) 5 | 6 | GEM 7 | remote: http://www.rubygems.org/ 8 | specs: 9 | activemodel (3.2.13.rc1) 10 | activesupport (= 3.2.13.rc1) 11 | builder (~> 3.0.0) 12 | activesupport (3.2.13.rc1) 13 | i18n (= 0.6.1) 14 | multi_json (~> 1.0) 15 | appraisal (0.5.1) 16 | bundler 17 | rake 18 | builder (3.0.4) 19 | i18n (0.6.1) 20 | multi_json (1.6.1) 21 | rake (10.0.3) 22 | simplecov (0.7.1) 23 | multi_json (~> 1.0) 24 | simplecov-html (~> 0.7.1) 25 | simplecov-html (0.7.1) 26 | 27 | PLATFORMS 28 | java 29 | ruby 30 | 31 | DEPENDENCIES 32 | activemodel (= 3.2.13.rc1) 33 | appraisal (~> 0.5.0) 34 | rake 35 | simplecov 36 | state_machine! 37 | -------------------------------------------------------------------------------- /gemfiles/mongo_mapper_0.5.8.gemfile.lock: -------------------------------------------------------------------------------- 1 | PATH 2 | remote: /home/aaron/Projects/Personal/pluginaweek/state_machine 3 | specs: 4 | state_machine (1.2.0) 5 | 6 | GEM 7 | remote: http://www.rubygems.org/ 8 | specs: 9 | activesupport (2.3.11) 10 | appraisal (0.5.1) 11 | bundler 12 | rake 13 | jnunemaker-validatable (1.8.0) 14 | mongo (0.16) 15 | mongo_mapper (0.5.8) 16 | activesupport (>= 2.3) 17 | jnunemaker-validatable (= 1.8.0) 18 | mongo (= 0.16) 19 | multi_json (1.0.4) 20 | rake (0.9.2.2) 21 | simplecov (0.5.4) 22 | multi_json (~> 1.0.3) 23 | simplecov-html (~> 0.5.3) 24 | simplecov-html (0.5.3) 25 | 26 | PLATFORMS 27 | java 28 | ruby 29 | 30 | DEPENDENCIES 31 | activesupport (= 2.3.11) 32 | appraisal (~> 0.5.0) 33 | mongo_mapper (= 0.5.8) 34 | rake 35 | simplecov 36 | state_machine! 37 | -------------------------------------------------------------------------------- /gemfiles/mongo_mapper_0.6.0.gemfile.lock: -------------------------------------------------------------------------------- 1 | PATH 2 | remote: /home/aaron/Projects/Personal/pluginaweek/state_machine 3 | specs: 4 | state_machine (1.2.0) 5 | 6 | GEM 7 | remote: http://www.rubygems.org/ 8 | specs: 9 | activesupport (2.3.11) 10 | appraisal (0.5.1) 11 | bundler 12 | rake 13 | jnunemaker-validatable (1.8.1) 14 | mongo (0.16) 15 | mongo_mapper (0.6.0) 16 | activesupport (>= 2.3) 17 | jnunemaker-validatable (= 1.8.1) 18 | mongo (= 0.16) 19 | multi_json (1.0.4) 20 | rake (0.9.2.2) 21 | simplecov (0.5.4) 22 | multi_json (~> 1.0.3) 23 | simplecov-html (~> 0.5.3) 24 | simplecov-html (0.5.3) 25 | 26 | PLATFORMS 27 | java 28 | ruby 29 | 30 | DEPENDENCIES 31 | activesupport (= 2.3.11) 32 | appraisal (~> 0.5.0) 33 | mongo_mapper (= 0.6.0) 34 | rake 35 | simplecov 36 | state_machine! 37 | -------------------------------------------------------------------------------- /gemfiles/mongo_mapper_0.5.5.gemfile.lock: -------------------------------------------------------------------------------- 1 | PATH 2 | remote: /home/aaron/Projects/Personal/pluginaweek/state_machine 3 | specs: 4 | state_machine (1.2.0) 5 | 6 | GEM 7 | remote: http://www.rubygems.org/ 8 | specs: 9 | activesupport (2.3.11) 10 | appraisal (0.5.1) 11 | bundler 12 | rake 13 | jnunemaker-validatable (1.7.4) 14 | mongo (0.15.1) 15 | mongo_mapper (0.5.5) 16 | activesupport (>= 2.3) 17 | jnunemaker-validatable (= 1.7.4) 18 | mongo (= 0.15.1) 19 | multi_json (1.0.4) 20 | rake (0.9.2.2) 21 | simplecov (0.5.4) 22 | multi_json (~> 1.0.3) 23 | simplecov-html (~> 0.5.3) 24 | simplecov-html (0.5.3) 25 | 26 | PLATFORMS 27 | java 28 | ruby 29 | 30 | DEPENDENCIES 31 | activesupport (= 2.3.11) 32 | appraisal (~> 0.5.0) 33 | mongo_mapper (= 0.5.5) 34 | rake 35 | simplecov 36 | state_machine! 37 | -------------------------------------------------------------------------------- /gemfiles/mongo_mapper_0.7.0.gemfile.lock: -------------------------------------------------------------------------------- 1 | PATH 2 | remote: /home/aaron/Projects/Personal/pluginaweek/state_machine 3 | specs: 4 | state_machine (1.2.0) 5 | 6 | GEM 7 | remote: http://www.rubygems.org/ 8 | specs: 9 | activesupport (2.3.11) 10 | appraisal (0.5.1) 11 | bundler 12 | rake 13 | jnunemaker-validatable (1.8.1) 14 | mongo (0.18.3) 15 | mongo_mapper (0.7.0) 16 | activesupport (>= 2.3) 17 | jnunemaker-validatable (= 1.8.1) 18 | mongo (= 0.18.3) 19 | multi_json (1.0.4) 20 | rake (0.9.2.2) 21 | simplecov (0.5.4) 22 | multi_json (~> 1.0.3) 23 | simplecov-html (~> 0.5.3) 24 | simplecov-html (0.5.3) 25 | 26 | PLATFORMS 27 | java 28 | ruby 29 | 30 | DEPENDENCIES 31 | activesupport (= 2.3.11) 32 | appraisal (~> 0.5.0) 33 | mongo_mapper (= 0.7.0) 34 | rake 35 | simplecov 36 | state_machine! 37 | -------------------------------------------------------------------------------- /gemfiles/mongo_mapper_0.6.10.gemfile.lock: -------------------------------------------------------------------------------- 1 | PATH 2 | remote: /home/aaron/Projects/Personal/pluginaweek/state_machine 3 | specs: 4 | state_machine (1.2.0) 5 | 6 | GEM 7 | remote: http://www.rubygems.org/ 8 | specs: 9 | activesupport (2.3.11) 10 | appraisal (0.5.1) 11 | bundler 12 | rake 13 | jnunemaker-validatable (1.8.1) 14 | mongo (0.18.2) 15 | mongo_mapper (0.6.10) 16 | activesupport (>= 2.3) 17 | jnunemaker-validatable (= 1.8.1) 18 | mongo (= 0.18.2) 19 | multi_json (1.0.4) 20 | rake (0.9.2.2) 21 | simplecov (0.5.4) 22 | multi_json (~> 1.0.3) 23 | simplecov-html (~> 0.5.3) 24 | simplecov-html (0.5.3) 25 | 26 | PLATFORMS 27 | java 28 | ruby 29 | 30 | DEPENDENCIES 31 | activesupport (= 2.3.11) 32 | appraisal (~> 0.5.0) 33 | mongo_mapper (= 0.6.10) 34 | rake 35 | simplecov 36 | state_machine! 37 | -------------------------------------------------------------------------------- /examples/rails-rest/controller.rb: -------------------------------------------------------------------------------- 1 | class UsersController < ApplicationController 2 | # GET /users 3 | def index 4 | @users = User.all 5 | end 6 | 7 | # GET /users/1 8 | def show 9 | @user = User.find(params[:id]) 10 | end 11 | 12 | # GET /users/new 13 | def new 14 | @user = User.new 15 | end 16 | 17 | # GET /users/1/edit 18 | def edit 19 | @user = User.find(params[:id]) 20 | end 21 | 22 | # POST /users 23 | def create 24 | @user = User.new(params[:user]) 25 | 26 | if @user.save 27 | redirect_to(@user) 28 | else 29 | render :action => 'new' 30 | end 31 | end 32 | 33 | # PUT /users/1 34 | def update 35 | @user = User.find(params[:id]) 36 | 37 | if @user.update_attributes(params[:user]) 38 | redirect_to(@user) 39 | else 40 | render :action => 'edit' 41 | end 42 | end 43 | end 44 | -------------------------------------------------------------------------------- /examples/vehicle.rb: -------------------------------------------------------------------------------- 1 | require 'state_machine' 2 | 3 | class Vehicle 4 | state_machine :initial => :parked do 5 | event :park do 6 | transition [:idling, :first_gear] => :parked 7 | end 8 | 9 | event :ignite do 10 | transition :stalled => same, :parked => :idling 11 | end 12 | 13 | event :idle do 14 | transition :first_gear => :idling 15 | end 16 | 17 | event :shift_up do 18 | transition :idling => :first_gear, :first_gear => :second_gear, :second_gear => :third_gear 19 | end 20 | 21 | event :shift_down do 22 | transition :third_gear => :second_gear, :second_gear => :first_gear 23 | end 24 | 25 | event :crash do 26 | transition [:first_gear, :second_gear, :third_gear] => :stalled 27 | end 28 | 29 | event :repair do 30 | transition :stalled => :parked 31 | end 32 | end 33 | end 34 | -------------------------------------------------------------------------------- /lib/state_machine/integrations/active_record/locale.rb: -------------------------------------------------------------------------------- 1 | filename = "#{File.dirname(__FILE__)}/../active_model/locale.rb" 2 | translations = eval(IO.read(File.expand_path(filename)), binding, filename) 3 | translations[:en][:activerecord] = translations[:en].delete(:activemodel) 4 | 5 | # Only ActiveRecord 2.3.5+ can pull i18n >= 0.1.3 from system-wide gems (and 6 | # therefore possibly have I18n::VERSION available) 7 | begin 8 | require 'i18n/version' 9 | rescue Exception => ex 10 | end unless ::ActiveRecord::VERSION::MAJOR == 2 && (::ActiveRecord::VERSION::MINOR < 3 || ::ActiveRecord::VERSION::TINY < 5) 11 | 12 | # Only i18n 0.4.0+ has the new %{key} syntax 13 | if !defined?(I18n::VERSION) || I18n::VERSION < '0.4.0' 14 | translations[:en][:activerecord][:errors][:messages].each do |key, message| 15 | message.gsub!('%{', '{{') 16 | message.gsub!('}', '}}') 17 | end 18 | end 19 | 20 | translations 21 | -------------------------------------------------------------------------------- /examples/merb-rest/view_edit.html.erb: -------------------------------------------------------------------------------- 1 |

Editing User

2 | 3 | <%= form_for @user, :action => resource(@user) do %> 4 | <%= error_messages %> 5 | 6 |

7 | <%= text_field :name, :label => 'Name' %> 8 |

9 | 10 |

11 | <%= label :state %>
12 | <%= select :state_event, :selected => @user.state_event.to_s, :collection => @user.state_transitions, :value_method => :event, :text_method => :human_to_name, :prompt => @user.human_state_name %> 13 |

14 | 15 |

16 | <%= label :access_state %>
17 | <%= select :access_state_event, :selected => @user.access_state_event.to_s, :collection => @user.access_state_transitions, :value_method => :event, :text_method => :human_event, :prompt => "don't change" %> 18 |

19 | 20 |

<%= submit 'Update' %>

21 | <% end =%> 22 | 23 | <%= link_to 'Show', resource(@user) %> | 24 | <%= link_to 'Back', resource(:users) %> 25 | -------------------------------------------------------------------------------- /gemfiles/mongo_mapper_0.7.5.gemfile.lock: -------------------------------------------------------------------------------- 1 | PATH 2 | remote: /home/aaron/Projects/Personal/pluginaweek/state_machine 3 | specs: 4 | state_machine (1.2.0) 5 | 6 | GEM 7 | remote: http://www.rubygems.org/ 8 | specs: 9 | activesupport (2.3.11) 10 | appraisal (0.5.1) 11 | bundler 12 | rake 13 | bson (1.0) 14 | jnunemaker-validatable (1.8.4) 15 | activesupport (>= 2.3.4) 16 | mongo (1.0) 17 | bson (= 1.0) 18 | mongo_mapper (0.7.5) 19 | activesupport (>= 2.3.4) 20 | jnunemaker-validatable (= 1.8.4) 21 | mongo (= 1.0) 22 | multi_json (1.0.4) 23 | rake (0.9.2.2) 24 | simplecov (0.5.4) 25 | multi_json (~> 1.0.3) 26 | simplecov-html (~> 0.5.3) 27 | simplecov-html (0.5.3) 28 | 29 | PLATFORMS 30 | java 31 | ruby 32 | 33 | DEPENDENCIES 34 | activesupport (= 2.3.11) 35 | appraisal (~> 0.5.0) 36 | mongo_mapper (= 0.7.5) 37 | rake 38 | simplecov 39 | state_machine! 40 | -------------------------------------------------------------------------------- /test/unit/matcher_helpers_test.rb: -------------------------------------------------------------------------------- 1 | require File.expand_path(File.dirname(__FILE__) + '/../test_helper') 2 | 3 | class MatcherHelpersAllTest < Test::Unit::TestCase 4 | include StateMachine::MatcherHelpers 5 | 6 | def setup 7 | @matcher = all 8 | end 9 | 10 | def test_should_build_an_all_matcher 11 | assert_equal StateMachine::AllMatcher.instance, @matcher 12 | end 13 | end 14 | 15 | class MatcherHelpersAnyTest < Test::Unit::TestCase 16 | include StateMachine::MatcherHelpers 17 | 18 | def setup 19 | @matcher = any 20 | end 21 | 22 | def test_should_build_an_all_matcher 23 | assert_equal StateMachine::AllMatcher.instance, @matcher 24 | end 25 | end 26 | 27 | class MatcherHelpersSameTest < Test::Unit::TestCase 28 | include StateMachine::MatcherHelpers 29 | 30 | def setup 31 | @matcher = same 32 | end 33 | 34 | def test_should_build_a_loopback_matcher 35 | assert_equal StateMachine::LoopbackMatcher.instance, @matcher 36 | end 37 | end 38 | -------------------------------------------------------------------------------- /gemfiles/active_record_2.0.0.gemfile.lock: -------------------------------------------------------------------------------- 1 | PATH 2 | remote: /home/aaron/Projects/Personal/pluginaweek/state_machine 3 | specs: 4 | state_machine (1.2.0) 5 | 6 | GEM 7 | remote: http://www.rubygems.org/ 8 | specs: 9 | activerecord (2.0.0) 10 | activesupport (= 2.0.0) 11 | activerecord-jdbc-adapter (1.2.7) 12 | activerecord-jdbcsqlite3-adapter (1.2.7) 13 | activerecord-jdbc-adapter (~> 1.2.7) 14 | jdbc-sqlite3 (~> 3.7.2) 15 | activesupport (2.0.0) 16 | appraisal (0.5.1) 17 | bundler 18 | rake 19 | jdbc-sqlite3 (3.7.2.1) 20 | multi_json (1.6.1) 21 | rake (10.0.3) 22 | simplecov (0.7.1) 23 | multi_json (~> 1.0) 24 | simplecov-html (~> 0.7.1) 25 | simplecov-html (0.7.1) 26 | sqlite3-ruby (1.3.1) 27 | 28 | PLATFORMS 29 | java 30 | ruby 31 | 32 | DEPENDENCIES 33 | activerecord (= 2.0.0) 34 | activerecord-jdbcsqlite3-adapter (= 1.2.7) 35 | appraisal (~> 0.5.0) 36 | rake 37 | simplecov 38 | sqlite3-ruby (= 1.3.1) 39 | state_machine! 40 | -------------------------------------------------------------------------------- /gemfiles/active_record_2.0.5.gemfile.lock: -------------------------------------------------------------------------------- 1 | PATH 2 | remote: /home/aaron/Projects/Personal/pluginaweek/state_machine 3 | specs: 4 | state_machine (1.2.0) 5 | 6 | GEM 7 | remote: http://www.rubygems.org/ 8 | specs: 9 | activerecord (2.0.5) 10 | activesupport (= 2.0.5) 11 | activerecord-jdbc-adapter (1.2.7) 12 | activerecord-jdbcsqlite3-adapter (1.2.7) 13 | activerecord-jdbc-adapter (~> 1.2.7) 14 | jdbc-sqlite3 (~> 3.7.2) 15 | activesupport (2.0.5) 16 | appraisal (0.5.1) 17 | bundler 18 | rake 19 | jdbc-sqlite3 (3.7.2.1) 20 | multi_json (1.6.1) 21 | rake (10.0.3) 22 | simplecov (0.7.1) 23 | multi_json (~> 1.0) 24 | simplecov-html (~> 0.7.1) 25 | simplecov-html (0.7.1) 26 | sqlite3-ruby (1.3.1) 27 | 28 | PLATFORMS 29 | java 30 | ruby 31 | 32 | DEPENDENCIES 33 | activerecord (= 2.0.5) 34 | activerecord-jdbcsqlite3-adapter (= 1.2.7) 35 | appraisal (~> 0.5.0) 36 | rake 37 | simplecov 38 | sqlite3-ruby (= 1.3.1) 39 | state_machine! 40 | -------------------------------------------------------------------------------- /gemfiles/active_record_2.1.0.gemfile.lock: -------------------------------------------------------------------------------- 1 | PATH 2 | remote: /home/aaron/Projects/Personal/pluginaweek/state_machine 3 | specs: 4 | state_machine (1.2.0) 5 | 6 | GEM 7 | remote: http://www.rubygems.org/ 8 | specs: 9 | activerecord (2.1.0) 10 | activesupport (= 2.1.0) 11 | activerecord-jdbc-adapter (1.2.7) 12 | activerecord-jdbcsqlite3-adapter (1.2.7) 13 | activerecord-jdbc-adapter (~> 1.2.7) 14 | jdbc-sqlite3 (~> 3.7.2) 15 | activesupport (2.1.0) 16 | appraisal (0.5.1) 17 | bundler 18 | rake 19 | jdbc-sqlite3 (3.7.2.1) 20 | multi_json (1.6.1) 21 | rake (10.0.3) 22 | simplecov (0.7.1) 23 | multi_json (~> 1.0) 24 | simplecov-html (~> 0.7.1) 25 | simplecov-html (0.7.1) 26 | sqlite3-ruby (1.3.1) 27 | 28 | PLATFORMS 29 | java 30 | ruby 31 | 32 | DEPENDENCIES 33 | activerecord (= 2.1.0) 34 | activerecord-jdbcsqlite3-adapter (= 1.2.7) 35 | appraisal (~> 0.5.0) 36 | rake 37 | simplecov 38 | sqlite3-ruby (= 1.3.1) 39 | state_machine! 40 | -------------------------------------------------------------------------------- /gemfiles/active_record_2.1.2.gemfile.lock: -------------------------------------------------------------------------------- 1 | PATH 2 | remote: /home/aaron/Projects/Personal/pluginaweek/state_machine 3 | specs: 4 | state_machine (1.2.0) 5 | 6 | GEM 7 | remote: http://www.rubygems.org/ 8 | specs: 9 | activerecord (2.1.2) 10 | activesupport (= 2.1.2) 11 | activerecord-jdbc-adapter (1.2.7) 12 | activerecord-jdbcsqlite3-adapter (1.2.7) 13 | activerecord-jdbc-adapter (~> 1.2.7) 14 | jdbc-sqlite3 (~> 3.7.2) 15 | activesupport (2.1.2) 16 | appraisal (0.5.1) 17 | bundler 18 | rake 19 | jdbc-sqlite3 (3.7.2.1) 20 | multi_json (1.6.1) 21 | rake (10.0.3) 22 | simplecov (0.7.1) 23 | multi_json (~> 1.0) 24 | simplecov-html (~> 0.7.1) 25 | simplecov-html (0.7.1) 26 | sqlite3-ruby (1.3.1) 27 | 28 | PLATFORMS 29 | java 30 | ruby 31 | 32 | DEPENDENCIES 33 | activerecord (= 2.1.2) 34 | activerecord-jdbcsqlite3-adapter (= 1.2.7) 35 | appraisal (~> 0.5.0) 36 | rake 37 | simplecov 38 | sqlite3-ruby (= 1.3.1) 39 | state_machine! 40 | -------------------------------------------------------------------------------- /gemfiles/active_record_2.2.3.gemfile.lock: -------------------------------------------------------------------------------- 1 | PATH 2 | remote: /home/aaron/Projects/Personal/pluginaweek/state_machine 3 | specs: 4 | state_machine (1.2.0) 5 | 6 | GEM 7 | remote: http://www.rubygems.org/ 8 | specs: 9 | activerecord (2.2.3) 10 | activesupport (= 2.2.3) 11 | activerecord-jdbc-adapter (1.2.7) 12 | activerecord-jdbcsqlite3-adapter (1.2.7) 13 | activerecord-jdbc-adapter (~> 1.2.7) 14 | jdbc-sqlite3 (~> 3.7.2) 15 | activesupport (2.2.3) 16 | appraisal (0.5.1) 17 | bundler 18 | rake 19 | jdbc-sqlite3 (3.7.2.1) 20 | multi_json (1.6.1) 21 | rake (10.0.3) 22 | simplecov (0.7.1) 23 | multi_json (~> 1.0) 24 | simplecov-html (~> 0.7.1) 25 | simplecov-html (0.7.1) 26 | sqlite3-ruby (1.3.1) 27 | 28 | PLATFORMS 29 | java 30 | ruby 31 | 32 | DEPENDENCIES 33 | activerecord (= 2.2.3) 34 | activerecord-jdbcsqlite3-adapter (= 1.2.7) 35 | appraisal (~> 0.5.0) 36 | rake 37 | simplecov 38 | sqlite3-ruby (= 1.3.1) 39 | state_machine! 40 | -------------------------------------------------------------------------------- /gemfiles/active_record_2.3.5.gemfile.lock: -------------------------------------------------------------------------------- 1 | PATH 2 | remote: /home/aaron/Projects/Personal/pluginaweek/state_machine 3 | specs: 4 | state_machine (1.2.0) 5 | 6 | GEM 7 | remote: http://www.rubygems.org/ 8 | specs: 9 | activerecord (2.3.5) 10 | activesupport (= 2.3.5) 11 | activerecord-jdbc-adapter (1.2.8) 12 | activerecord-jdbcsqlite3-adapter (1.2.7) 13 | activerecord-jdbc-adapter (~> 1.2.7) 14 | jdbc-sqlite3 (~> 3.7.2) 15 | activesupport (2.3.5) 16 | appraisal (0.5.1) 17 | bundler 18 | rake 19 | jdbc-sqlite3 (3.7.2.1) 20 | multi_json (1.6.1) 21 | rake (10.0.3) 22 | simplecov (0.7.1) 23 | multi_json (~> 1.0) 24 | simplecov-html (~> 0.7.1) 25 | simplecov-html (0.7.1) 26 | sqlite3-ruby (1.3.1) 27 | 28 | PLATFORMS 29 | java 30 | ruby 31 | 32 | DEPENDENCIES 33 | activerecord (= 2.3.5) 34 | activerecord-jdbcsqlite3-adapter (= 1.2.7) 35 | appraisal (~> 0.5.0) 36 | rake 37 | simplecov 38 | sqlite3-ruby (= 1.3.1) 39 | state_machine! 40 | -------------------------------------------------------------------------------- /gemfiles/active_record_2.3.12.gemfile.lock: -------------------------------------------------------------------------------- 1 | PATH 2 | remote: /home/aaron/Projects/Personal/pluginaweek/state_machine 3 | specs: 4 | state_machine (1.2.0) 5 | 6 | GEM 7 | remote: http://www.rubygems.org/ 8 | specs: 9 | activerecord (2.3.12) 10 | activesupport (= 2.3.12) 11 | activerecord-jdbc-adapter (1.2.7) 12 | activerecord-jdbcsqlite3-adapter (1.2.7) 13 | activerecord-jdbc-adapter (~> 1.2.7) 14 | jdbc-sqlite3 (~> 3.7.2) 15 | activesupport (2.3.12) 16 | appraisal (0.5.1) 17 | bundler 18 | rake 19 | jdbc-sqlite3 (3.7.2.1) 20 | multi_json (1.6.1) 21 | rake (10.0.3) 22 | simplecov (0.7.1) 23 | multi_json (~> 1.0) 24 | simplecov-html (~> 0.7.1) 25 | simplecov-html (0.7.1) 26 | sqlite3-ruby (1.3.1) 27 | 28 | PLATFORMS 29 | java 30 | ruby 31 | 32 | DEPENDENCIES 33 | activerecord (= 2.3.12) 34 | activerecord-jdbcsqlite3-adapter (= 1.2.7) 35 | appraisal (~> 0.5.0) 36 | rake 37 | simplecov 38 | sqlite3-ruby (= 1.3.1) 39 | state_machine! 40 | -------------------------------------------------------------------------------- /gemfiles/mongo_mapper_0.8.4.gemfile.lock: -------------------------------------------------------------------------------- 1 | PATH 2 | remote: /home/aaron/Projects/Personal/pluginaweek/state_machine 3 | specs: 4 | state_machine (1.2.0) 5 | 6 | GEM 7 | remote: http://www.rubygems.org/ 8 | specs: 9 | activesupport (2.3.11) 10 | appraisal (0.5.1) 11 | bundler 12 | rake 13 | bson (1.4.0) 14 | bson (1.4.0-java) 15 | jnunemaker-validatable (1.8.4) 16 | activesupport (>= 2.3.4) 17 | mongo (1.4.0) 18 | bson (= 1.4.0) 19 | mongo_mapper (0.8.4) 20 | activesupport (>= 2.3.4) 21 | jnunemaker-validatable (~> 1.8.4) 22 | plucky (~> 0.3.5) 23 | multi_json (1.0.4) 24 | plucky (0.3.8) 25 | mongo (~> 1.3) 26 | rake (0.9.2.2) 27 | simplecov (0.5.4) 28 | multi_json (~> 1.0.3) 29 | simplecov-html (~> 0.5.3) 30 | simplecov-html (0.5.3) 31 | 32 | PLATFORMS 33 | java 34 | ruby 35 | 36 | DEPENDENCIES 37 | activesupport (= 2.3.11) 38 | appraisal (~> 0.5.0) 39 | mongo_mapper (= 0.8.4) 40 | rake 41 | simplecov 42 | state_machine! 43 | -------------------------------------------------------------------------------- /gemfiles/mongo_mapper_0.8.6.gemfile.lock: -------------------------------------------------------------------------------- 1 | PATH 2 | remote: /home/aaron/Projects/Personal/pluginaweek/state_machine 3 | specs: 4 | state_machine (1.2.0) 5 | 6 | GEM 7 | remote: http://www.rubygems.org/ 8 | specs: 9 | activesupport (2.3.11) 10 | appraisal (0.5.1) 11 | bundler 12 | rake 13 | bson (1.4.0) 14 | bson (1.4.0-java) 15 | jnunemaker-validatable (1.8.4) 16 | activesupport (>= 2.3.4) 17 | mongo (1.4.0) 18 | bson (= 1.4.0) 19 | mongo_mapper (0.8.6) 20 | activesupport (>= 2.3.4) 21 | jnunemaker-validatable (~> 1.8.4) 22 | plucky (~> 0.3.6) 23 | multi_json (1.0.4) 24 | plucky (0.3.8) 25 | mongo (~> 1.3) 26 | rake (0.9.2.2) 27 | simplecov (0.5.4) 28 | multi_json (~> 1.0.3) 29 | simplecov-html (~> 0.5.3) 30 | simplecov-html (0.5.3) 31 | 32 | PLATFORMS 33 | java 34 | ruby 35 | 36 | DEPENDENCIES 37 | activesupport (= 2.3.11) 38 | appraisal (~> 0.5.0) 39 | mongo_mapper (= 0.8.6) 40 | rake 41 | simplecov 42 | state_machine! 43 | -------------------------------------------------------------------------------- /gemfiles/mongo_mapper_0.8.0.gemfile.lock: -------------------------------------------------------------------------------- 1 | PATH 2 | remote: /home/aaron/Projects/Personal/pluginaweek/state_machine 3 | specs: 4 | state_machine (1.2.0) 5 | 6 | GEM 7 | remote: http://www.rubygems.org/ 8 | specs: 9 | activesupport (2.3.11) 10 | appraisal (0.5.1) 11 | bundler 12 | rake 13 | bson (1.0.1) 14 | jnunemaker-validatable (1.8.4) 15 | activesupport (>= 2.3.4) 16 | mongo (1.0.1) 17 | bson (= 1.0.1) 18 | mongo_mapper (0.8.0) 19 | activesupport (>= 2.3.4) 20 | jnunemaker-validatable (~> 1.8.4) 21 | plucky (~> 0.3.0) 22 | multi_json (1.0.4) 23 | plucky (0.3.0) 24 | mongo (~> 1.0.1) 25 | rake (0.9.2.2) 26 | simplecov (0.5.4) 27 | multi_json (~> 1.0.3) 28 | simplecov-html (~> 0.5.3) 29 | simplecov-html (0.5.3) 30 | 31 | PLATFORMS 32 | java 33 | ruby 34 | 35 | DEPENDENCIES 36 | activesupport (= 2.3.11) 37 | appraisal (~> 0.5.0) 38 | mongo (= 1.0.1) 39 | mongo_mapper (= 0.8.0) 40 | plucky (= 0.3.0) 41 | rake 42 | simplecov 43 | state_machine! 44 | -------------------------------------------------------------------------------- /gemfiles/mongo_mapper_0.8.3.gemfile.lock: -------------------------------------------------------------------------------- 1 | PATH 2 | remote: /home/aaron/Projects/Personal/pluginaweek/state_machine 3 | specs: 4 | state_machine (1.2.0) 5 | 6 | GEM 7 | remote: http://www.rubygems.org/ 8 | specs: 9 | activesupport (2.3.11) 10 | appraisal (0.5.1) 11 | bundler 12 | rake 13 | bson (1.0.1) 14 | jnunemaker-validatable (1.8.4) 15 | activesupport (>= 2.3.4) 16 | mongo (1.0.1) 17 | bson (= 1.0.1) 18 | mongo_mapper (0.8.3) 19 | activesupport (>= 2.3.4) 20 | jnunemaker-validatable (~> 1.8.4) 21 | plucky (~> 0.3.3) 22 | multi_json (1.0.4) 23 | plucky (0.3.3) 24 | mongo (~> 1.0.1) 25 | rake (0.9.2.2) 26 | simplecov (0.5.4) 27 | multi_json (~> 1.0.3) 28 | simplecov-html (~> 0.5.3) 29 | simplecov-html (0.5.3) 30 | 31 | PLATFORMS 32 | java 33 | ruby 34 | 35 | DEPENDENCIES 36 | activesupport (= 2.3.11) 37 | appraisal (~> 0.5.0) 38 | mongo (= 1.0.1) 39 | mongo_mapper (= 0.8.3) 40 | plucky (= 0.3.3) 41 | rake 42 | simplecov 43 | state_machine! 44 | -------------------------------------------------------------------------------- /lib/state_machine/yard/templates/default/class/html/setup.rb: -------------------------------------------------------------------------------- 1 | require 'tempfile' 2 | 3 | # Define where state machine descriptions will be rendered 4 | def init 5 | super 6 | sections.place(:state_machine_details).before(:children) 7 | end 8 | 9 | # Renders state machine details in the main content of the class's documentation 10 | def state_machine_details 11 | erb(:state_machines) if state_machines 12 | end 13 | 14 | # Gets a list of state machines prased for this class 15 | def state_machines 16 | @state_machines ||= begin 17 | if state_machines = object['state_machines'] 18 | state_machines.each do |name, machine| 19 | serializer.serialize(state_machine_image_path(machine), machine[:image]) if machine[:image] 20 | end 21 | end 22 | end 23 | end 24 | 25 | # Generates the image path for the given machine's visualization 26 | def state_machine_image_path(machine) 27 | base_path = File.dirname(serializer.serialized_path(object)) 28 | image_name = "#{object.name}_#{machine[:name]}" 29 | "#{File.join(base_path, image_name)}.png" 30 | end 31 | -------------------------------------------------------------------------------- /gemfiles/mongo_mapper_0.9.0.gemfile.lock: -------------------------------------------------------------------------------- 1 | PATH 2 | remote: /home/aaron/Projects/Personal/pluginaweek/state_machine 3 | specs: 4 | state_machine (1.2.0) 5 | 6 | GEM 7 | remote: http://www.rubygems.org/ 8 | specs: 9 | activemodel (3.0.10) 10 | activesupport (= 3.0.10) 11 | builder (~> 2.1.2) 12 | i18n (~> 0.5.0) 13 | activesupport (3.0.10) 14 | appraisal (0.5.1) 15 | bundler 16 | rake 17 | bson (1.4.0) 18 | bson (1.4.0-java) 19 | builder (2.1.2) 20 | i18n (0.5.0) 21 | mongo (1.4.0) 22 | bson (= 1.4.0) 23 | mongo_mapper (0.9.0) 24 | activemodel (~> 3.0.0) 25 | activesupport (~> 3.0.0) 26 | plucky (~> 0.3.6) 27 | multi_json (1.0.4) 28 | plucky (0.3.8) 29 | mongo (~> 1.3) 30 | rake (0.9.2.2) 31 | simplecov (0.5.4) 32 | multi_json (~> 1.0.3) 33 | simplecov-html (~> 0.5.3) 34 | simplecov-html (0.5.3) 35 | 36 | PLATFORMS 37 | java 38 | ruby 39 | 40 | DEPENDENCIES 41 | appraisal (~> 0.5.0) 42 | mongo_mapper (= 0.9.0) 43 | rake 44 | simplecov 45 | state_machine! 46 | -------------------------------------------------------------------------------- /gemfiles/mongoid_3.0.22.gemfile.lock: -------------------------------------------------------------------------------- 1 | PATH 2 | remote: /home/aaron/Projects/Personal/pluginaweek/state_machine 3 | specs: 4 | state_machine (1.2.0) 5 | 6 | GEM 7 | remote: http://www.rubygems.org/ 8 | specs: 9 | activemodel (3.2.13.rc1) 10 | activesupport (= 3.2.13.rc1) 11 | builder (~> 3.0.0) 12 | activesupport (3.2.13.rc1) 13 | i18n (= 0.6.1) 14 | multi_json (~> 1.0) 15 | appraisal (0.5.1) 16 | bundler 17 | rake 18 | builder (3.0.4) 19 | i18n (0.6.1) 20 | mongoid (3.0.22) 21 | activemodel (~> 3.1) 22 | moped (~> 1.2) 23 | origin (~> 1.0) 24 | tzinfo (~> 0.3.22) 25 | moped (1.4.2) 26 | multi_json (1.6.1) 27 | origin (1.0.11) 28 | rake (10.0.3) 29 | simplecov (0.7.1) 30 | multi_json (~> 1.0) 31 | simplecov-html (~> 0.7.1) 32 | simplecov-html (0.7.1) 33 | tzinfo (0.3.35) 34 | 35 | PLATFORMS 36 | java 37 | ruby 38 | 39 | DEPENDENCIES 40 | activemodel (= 3.2.13.rc1) 41 | appraisal (~> 0.5.0) 42 | mongoid (= 3.0.22) 43 | rake 44 | simplecov 45 | state_machine! 46 | -------------------------------------------------------------------------------- /gemfiles/mongoid_3.1.0.gemfile.lock: -------------------------------------------------------------------------------- 1 | PATH 2 | remote: /home/aaron/Projects/Personal/pluginaweek/state_machine 3 | specs: 4 | state_machine (1.2.0) 5 | 6 | GEM 7 | remote: http://www.rubygems.org/ 8 | specs: 9 | activemodel (3.2.13.rc1) 10 | activesupport (= 3.2.13.rc1) 11 | builder (~> 3.0.0) 12 | activesupport (3.2.13.rc1) 13 | i18n (= 0.6.1) 14 | multi_json (~> 1.0) 15 | appraisal (0.5.1) 16 | bundler 17 | rake 18 | builder (3.0.4) 19 | i18n (0.6.1) 20 | mongoid (3.1.0) 21 | activemodel (~> 3.2) 22 | moped (~> 1.4.2) 23 | origin (~> 1.0) 24 | tzinfo (~> 0.3.22) 25 | moped (1.4.2) 26 | multi_json (1.6.1) 27 | origin (1.0.11) 28 | rake (10.0.3) 29 | simplecov (0.7.1) 30 | multi_json (~> 1.0) 31 | simplecov-html (~> 0.7.1) 32 | simplecov-html (0.7.1) 33 | tzinfo (0.3.35) 34 | 35 | PLATFORMS 36 | java 37 | ruby 38 | 39 | DEPENDENCIES 40 | activemodel (= 3.2.13.rc1) 41 | appraisal (~> 0.5.0) 42 | mongoid (= 3.1.0) 43 | rake 44 | simplecov 45 | state_machine! 46 | -------------------------------------------------------------------------------- /gemfiles/mongoid_3.0.0.gemfile.lock: -------------------------------------------------------------------------------- 1 | PATH 2 | remote: /home/aaron/Projects/Personal/pluginaweek/state_machine 3 | specs: 4 | state_machine (1.2.0) 5 | 6 | GEM 7 | remote: http://www.rubygems.org/ 8 | specs: 9 | activemodel (3.2.13.rc1) 10 | activesupport (= 3.2.13.rc1) 11 | builder (~> 3.0.0) 12 | activesupport (3.2.13.rc1) 13 | i18n (= 0.6.1) 14 | multi_json (~> 1.0) 15 | appraisal (0.5.1) 16 | bundler 17 | rake 18 | builder (3.0.4) 19 | i18n (0.6.1) 20 | mongoid (3.0.0) 21 | activemodel (~> 3.1) 22 | moped (~> 1.1.1) 23 | origin (~> 1.0.3) 24 | tzinfo (~> 0.3.22) 25 | moped (1.1.6) 26 | multi_json (1.6.1) 27 | origin (1.0.11) 28 | rake (10.0.3) 29 | simplecov (0.7.1) 30 | multi_json (~> 1.0) 31 | simplecov-html (~> 0.7.1) 32 | simplecov-html (0.7.1) 33 | tzinfo (0.3.35) 34 | 35 | PLATFORMS 36 | java 37 | ruby 38 | 39 | DEPENDENCIES 40 | activemodel (= 3.2.13.rc1) 41 | appraisal (~> 0.5.0) 42 | mongoid (= 3.0.0) 43 | rake 44 | simplecov 45 | state_machine! 46 | -------------------------------------------------------------------------------- /examples/rails-rest/view__form.html.erb: -------------------------------------------------------------------------------- 1 | <%= form_for(@user) do |f| %> 2 | <% if @user.errors.any? %> 3 |
4 |

<%= pluralize(@user.errors.count, "error") %> prohibited this user from being saved:

5 | 6 | 11 |
12 | <% end %> 13 | 14 |
15 | <%= f.label :name %>
16 | <%= f.text_field :name %> 17 |
18 | 19 | <% unless @user.new_record? %> 20 |
21 | <%= f.label :state %>
22 | <%= f.collection_select :state_event, @user.state_transitions, :event, :human_to_name, :include_blank => @user.human_state_name %> 23 |
24 | 25 |
26 | <%= f.label :access_state %>
27 | <%= f.collection_select :access_state_event, @user.access_state_transitions, :event, :human_event, :include_blank => "don't change" %> 28 |
29 | <% end %> 30 | 31 |
32 | <%= f.submit %> 33 |
34 | <% end %> 35 | -------------------------------------------------------------------------------- /gemfiles/mongoid_2.1.4.gemfile.lock: -------------------------------------------------------------------------------- 1 | PATH 2 | remote: /home/aaron/Projects/Personal/pluginaweek/state_machine 3 | specs: 4 | state_machine (1.2.0) 5 | 6 | GEM 7 | remote: http://www.rubygems.org/ 8 | specs: 9 | activemodel (3.1.11) 10 | activesupport (= 3.1.11) 11 | builder (~> 3.0.0) 12 | i18n (~> 0.6) 13 | activesupport (3.1.11) 14 | multi_json (~> 1.0) 15 | appraisal (0.5.1) 16 | bundler 17 | rake 18 | bson (1.7.1) 19 | bson (1.7.1-java) 20 | builder (3.0.4) 21 | i18n (0.6.1) 22 | mongo (1.7.1) 23 | bson (~> 1.7.1) 24 | mongoid (2.1.4) 25 | activemodel (~> 3.0) 26 | mongo (~> 1.3) 27 | tzinfo (~> 0.3.22) 28 | multi_json (1.6.1) 29 | rake (10.0.3) 30 | simplecov (0.7.1) 31 | multi_json (~> 1.0) 32 | simplecov-html (~> 0.7.1) 33 | simplecov-html (0.7.1) 34 | tzinfo (0.3.35) 35 | 36 | PLATFORMS 37 | java 38 | ruby 39 | 40 | DEPENDENCIES 41 | activemodel (~> 3.1.0) 42 | appraisal (~> 0.5.0) 43 | mongo (~> 1.7.0) 44 | mongoid (= 2.1.4) 45 | rake 46 | simplecov 47 | state_machine! 48 | -------------------------------------------------------------------------------- /gemfiles/mongoid_2.2.4.gemfile.lock: -------------------------------------------------------------------------------- 1 | PATH 2 | remote: /home/aaron/Projects/Personal/pluginaweek/state_machine 3 | specs: 4 | state_machine (1.2.0) 5 | 6 | GEM 7 | remote: http://www.rubygems.org/ 8 | specs: 9 | activemodel (3.1.11) 10 | activesupport (= 3.1.11) 11 | builder (~> 3.0.0) 12 | i18n (~> 0.6) 13 | activesupport (3.1.11) 14 | multi_json (~> 1.0) 15 | appraisal (0.5.1) 16 | bundler 17 | rake 18 | bson (1.7.1) 19 | bson (1.7.1-java) 20 | builder (3.0.4) 21 | i18n (0.6.1) 22 | mongo (1.7.1) 23 | bson (~> 1.7.1) 24 | mongoid (2.2.4) 25 | activemodel (~> 3.0) 26 | mongo (~> 1.3) 27 | tzinfo (~> 0.3.22) 28 | multi_json (1.6.1) 29 | rake (10.0.3) 30 | simplecov (0.7.1) 31 | multi_json (~> 1.0) 32 | simplecov-html (~> 0.7.1) 33 | simplecov-html (0.7.1) 34 | tzinfo (0.3.35) 35 | 36 | PLATFORMS 37 | java 38 | ruby 39 | 40 | DEPENDENCIES 41 | activemodel (~> 3.1.0) 42 | appraisal (~> 0.5.0) 43 | mongo (~> 1.7.0) 44 | mongoid (= 2.2.4) 45 | rake 46 | simplecov 47 | state_machine! 48 | -------------------------------------------------------------------------------- /gemfiles/mongoid_2.3.3.gemfile.lock: -------------------------------------------------------------------------------- 1 | PATH 2 | remote: /home/aaron/Projects/Personal/pluginaweek/state_machine 3 | specs: 4 | state_machine (1.2.0) 5 | 6 | GEM 7 | remote: http://www.rubygems.org/ 8 | specs: 9 | activemodel (3.1.11) 10 | activesupport (= 3.1.11) 11 | builder (~> 3.0.0) 12 | i18n (~> 0.6) 13 | activesupport (3.1.11) 14 | multi_json (~> 1.0) 15 | appraisal (0.5.1) 16 | bundler 17 | rake 18 | bson (1.7.1) 19 | bson (1.7.1-java) 20 | builder (3.0.4) 21 | i18n (0.6.1) 22 | mongo (1.7.1) 23 | bson (~> 1.7.1) 24 | mongoid (2.3.3) 25 | activemodel (~> 3.1) 26 | mongo (~> 1.3) 27 | tzinfo (~> 0.3.22) 28 | multi_json (1.6.1) 29 | rake (10.0.3) 30 | simplecov (0.7.1) 31 | multi_json (~> 1.0) 32 | simplecov-html (~> 0.7.1) 33 | simplecov-html (0.7.1) 34 | tzinfo (0.3.35) 35 | 36 | PLATFORMS 37 | java 38 | ruby 39 | 40 | DEPENDENCIES 41 | activemodel (~> 3.1.0) 42 | appraisal (~> 0.5.0) 43 | mongo (~> 1.7.0) 44 | mongoid (= 2.3.3) 45 | rake 46 | simplecov 47 | state_machine! 48 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2006-2012 Aaron Pfeifer 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining 4 | a copy of this software and associated documentation files (the 5 | "Software"), to deal in the Software without restriction, including 6 | without limitation the rights to use, copy, modify, merge, publish, 7 | distribute, sublicense, and/or sell copies of the Software, and to 8 | permit persons to whom the Software is furnished to do so, subject to 9 | the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be 12 | included in all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 17 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 18 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 19 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 20 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /gemfiles/mongoid_2.4.0.gemfile.lock: -------------------------------------------------------------------------------- 1 | PATH 2 | remote: /home/aaron/Projects/Personal/pluginaweek/state_machine 3 | specs: 4 | state_machine (1.2.0) 5 | 6 | GEM 7 | remote: http://www.rubygems.org/ 8 | specs: 9 | activemodel (3.2.13.rc1) 10 | activesupport (= 3.2.13.rc1) 11 | builder (~> 3.0.0) 12 | activesupport (3.2.13.rc1) 13 | i18n (= 0.6.1) 14 | multi_json (~> 1.0) 15 | appraisal (0.5.1) 16 | bundler 17 | rake 18 | bson (1.7.1) 19 | bson (1.7.1-java) 20 | builder (3.0.4) 21 | i18n (0.6.1) 22 | mongo (1.7.1) 23 | bson (~> 1.7.1) 24 | mongoid (2.4.0) 25 | activemodel (~> 3.1) 26 | mongo (~> 1.3) 27 | tzinfo (~> 0.3.22) 28 | multi_json (1.6.1) 29 | rake (10.0.3) 30 | simplecov (0.7.1) 31 | multi_json (~> 1.0) 32 | simplecov-html (~> 0.7.1) 33 | simplecov-html (0.7.1) 34 | tzinfo (0.3.35) 35 | 36 | PLATFORMS 37 | java 38 | ruby 39 | 40 | DEPENDENCIES 41 | activemodel (= 3.2.13.rc1) 42 | appraisal (~> 0.5.0) 43 | mongo (~> 1.7.0) 44 | mongoid (= 2.4.0) 45 | rake 46 | simplecov 47 | state_machine! 48 | -------------------------------------------------------------------------------- /gemfiles/mongoid_2.5.2.gemfile.lock: -------------------------------------------------------------------------------- 1 | PATH 2 | remote: /home/aaron/Projects/Personal/pluginaweek/state_machine 3 | specs: 4 | state_machine (1.2.0) 5 | 6 | GEM 7 | remote: http://www.rubygems.org/ 8 | specs: 9 | activemodel (3.2.13.rc1) 10 | activesupport (= 3.2.13.rc1) 11 | builder (~> 3.0.0) 12 | activesupport (3.2.13.rc1) 13 | i18n (= 0.6.1) 14 | multi_json (~> 1.0) 15 | appraisal (0.5.1) 16 | bundler 17 | rake 18 | bson (1.7.1) 19 | bson (1.7.1-java) 20 | builder (3.0.4) 21 | i18n (0.6.1) 22 | mongo (1.7.1) 23 | bson (~> 1.7.1) 24 | mongoid (2.5.2) 25 | activemodel (~> 3.1) 26 | mongo (~> 1.7) 27 | tzinfo (~> 0.3.22) 28 | multi_json (1.6.1) 29 | rake (10.0.3) 30 | simplecov (0.7.1) 31 | multi_json (~> 1.0) 32 | simplecov-html (~> 0.7.1) 33 | simplecov-html (0.7.1) 34 | tzinfo (0.3.35) 35 | 36 | PLATFORMS 37 | java 38 | ruby 39 | 40 | DEPENDENCIES 41 | activemodel (= 3.2.13.rc1) 42 | appraisal (~> 0.5.0) 43 | mongo (~> 1.7.0) 44 | mongoid (= 2.5.2) 45 | rake 46 | simplecov 47 | state_machine! 48 | -------------------------------------------------------------------------------- /gemfiles/mongoid_2.6.0.gemfile.lock: -------------------------------------------------------------------------------- 1 | PATH 2 | remote: /home/aaron/Projects/Personal/pluginaweek/state_machine 3 | specs: 4 | state_machine (1.2.0) 5 | 6 | GEM 7 | remote: http://www.rubygems.org/ 8 | specs: 9 | activemodel (3.2.13.rc1) 10 | activesupport (= 3.2.13.rc1) 11 | builder (~> 3.0.0) 12 | activesupport (3.2.13.rc1) 13 | i18n (= 0.6.1) 14 | multi_json (~> 1.0) 15 | appraisal (0.5.1) 16 | bundler 17 | rake 18 | bson (1.7.1) 19 | bson (1.7.1-java) 20 | builder (3.0.4) 21 | i18n (0.6.1) 22 | mongo (1.7.1) 23 | bson (~> 1.7.1) 24 | mongoid (2.6.0) 25 | activemodel (~> 3.1) 26 | mongo (~> 1.7) 27 | tzinfo (~> 0.3.22) 28 | multi_json (1.6.1) 29 | rake (10.0.3) 30 | simplecov (0.7.1) 31 | multi_json (~> 1.0) 32 | simplecov-html (~> 0.7.1) 33 | simplecov-html (0.7.1) 34 | tzinfo (0.3.35) 35 | 36 | PLATFORMS 37 | java 38 | ruby 39 | 40 | DEPENDENCIES 41 | activemodel (= 3.2.13.rc1) 42 | appraisal (~> 0.5.0) 43 | mongo (~> 1.7.0) 44 | mongoid (= 2.6.0) 45 | rake 46 | simplecov 47 | state_machine! 48 | -------------------------------------------------------------------------------- /gemfiles/mongoid_2.4.10.gemfile.lock: -------------------------------------------------------------------------------- 1 | PATH 2 | remote: /home/aaron/Projects/Personal/pluginaweek/state_machine 3 | specs: 4 | state_machine (1.2.0) 5 | 6 | GEM 7 | remote: http://www.rubygems.org/ 8 | specs: 9 | activemodel (3.2.13.rc1) 10 | activesupport (= 3.2.13.rc1) 11 | builder (~> 3.0.0) 12 | activesupport (3.2.13.rc1) 13 | i18n (= 0.6.1) 14 | multi_json (~> 1.0) 15 | appraisal (0.5.1) 16 | bundler 17 | rake 18 | bson (1.7.1) 19 | bson (1.7.1-java) 20 | builder (3.0.4) 21 | i18n (0.6.1) 22 | mongo (1.7.1) 23 | bson (~> 1.7.1) 24 | mongoid (2.4.10) 25 | activemodel (~> 3.1) 26 | mongo (~> 1.3) 27 | tzinfo (~> 0.3.22) 28 | multi_json (1.6.1) 29 | rake (10.0.3) 30 | simplecov (0.7.1) 31 | multi_json (~> 1.0) 32 | simplecov-html (~> 0.7.1) 33 | simplecov-html (0.7.1) 34 | tzinfo (0.3.35) 35 | 36 | PLATFORMS 37 | java 38 | ruby 39 | 40 | DEPENDENCIES 41 | activemodel (= 3.2.13.rc1) 42 | appraisal (~> 0.5.0) 43 | mongo (~> 1.7.0) 44 | mongoid (= 2.4.10) 45 | rake 46 | simplecov 47 | state_machine! 48 | -------------------------------------------------------------------------------- /lib/state_machine/integrations/active_model/versions.rb: -------------------------------------------------------------------------------- 1 | module StateMachine 2 | module Integrations #:nodoc: 3 | module ActiveModel 4 | version '2.x' do 5 | def self.active? 6 | !defined?(::ActiveModel::VERSION) || ::ActiveModel::VERSION::MAJOR == 2 7 | end 8 | 9 | def define_validation_hook 10 | define_helper :instance, <<-end_eval, __FILE__, __LINE__ + 1 11 | def valid?(*) 12 | self.class.state_machines.transitions(self, #{action.inspect}, :after => false).perform { super } 13 | end 14 | end_eval 15 | end 16 | end 17 | 18 | version '3.0.x' do 19 | def self.active? 20 | defined?(::ActiveModel::VERSION) && ::ActiveModel::VERSION::MAJOR == 3 && ::ActiveModel::VERSION::MINOR == 0 21 | end 22 | 23 | def define_validation_hook 24 | # +around+ callbacks don't have direct access to results until AS 3.1 25 | owner_class.set_callback(:validation, :after, 'value', :prepend => true) 26 | super 27 | end 28 | end 29 | end 30 | end 31 | end 32 | -------------------------------------------------------------------------------- /gemfiles/mongo_mapper_0.10.0.gemfile.lock: -------------------------------------------------------------------------------- 1 | PATH 2 | remote: /home/aaron/Projects/Personal/pluginaweek/state_machine 3 | specs: 4 | state_machine (1.2.0) 5 | 6 | GEM 7 | remote: http://www.rubygems.org/ 8 | specs: 9 | activemodel (3.2.13.rc1) 10 | activesupport (= 3.2.13.rc1) 11 | builder (~> 3.0.0) 12 | activesupport (3.2.13.rc1) 13 | i18n (= 0.6.1) 14 | multi_json (~> 1.0) 15 | appraisal (0.5.1) 16 | bundler 17 | rake 18 | bson (1.4.0) 19 | bson (1.4.0-java) 20 | builder (3.0.4) 21 | i18n (0.6.1) 22 | mongo (1.4.0) 23 | bson (= 1.4.0) 24 | mongo_mapper (0.10.0) 25 | activemodel (~> 3.0) 26 | activesupport (~> 3.0) 27 | plucky (~> 0.3.8) 28 | multi_json (1.0.4) 29 | plucky (0.3.8) 30 | mongo (~> 1.3) 31 | rake (0.9.2.2) 32 | simplecov (0.5.4) 33 | multi_json (~> 1.0.3) 34 | simplecov-html (~> 0.5.3) 35 | simplecov-html (0.5.3) 36 | 37 | PLATFORMS 38 | java 39 | ruby 40 | 41 | DEPENDENCIES 42 | activemodel (= 3.2.13.rc1) 43 | appraisal (~> 0.5.0) 44 | mongo_mapper (= 0.10.0) 45 | rake 46 | simplecov 47 | state_machine! 48 | -------------------------------------------------------------------------------- /gemfiles/mongo_mapper_0.11.2.gemfile.lock: -------------------------------------------------------------------------------- 1 | PATH 2 | remote: /home/aaron/Projects/Personal/pluginaweek/state_machine 3 | specs: 4 | state_machine (1.2.0) 5 | 6 | GEM 7 | remote: http://www.rubygems.org/ 8 | specs: 9 | activemodel (3.2.13.rc1) 10 | activesupport (= 3.2.13.rc1) 11 | builder (~> 3.0.0) 12 | activesupport (3.2.13.rc1) 13 | i18n (= 0.6.1) 14 | multi_json (~> 1.0) 15 | appraisal (0.5.1) 16 | bundler 17 | rake 18 | bson (1.7.1) 19 | bson (1.7.1-java) 20 | builder (3.0.4) 21 | i18n (0.6.1) 22 | mongo (1.7.1) 23 | bson (~> 1.7.1) 24 | mongo_mapper (0.11.2) 25 | activemodel (~> 3.0) 26 | activesupport (~> 3.0) 27 | plucky (~> 0.5.1) 28 | multi_json (1.6.1) 29 | plucky (0.5.2) 30 | mongo (~> 1.5) 31 | rake (10.0.3) 32 | simplecov (0.7.1) 33 | multi_json (~> 1.0) 34 | simplecov-html (~> 0.7.1) 35 | simplecov-html (0.7.1) 36 | 37 | PLATFORMS 38 | java 39 | ruby 40 | 41 | DEPENDENCIES 42 | activemodel (= 3.2.13.rc1) 43 | appraisal (~> 0.5.0) 44 | mongo (~> 1.7.0) 45 | mongo_mapper (= 0.11.2) 46 | rake 47 | simplecov 48 | state_machine! 49 | -------------------------------------------------------------------------------- /gemfiles/mongo_mapper_0.12.0.gemfile.lock: -------------------------------------------------------------------------------- 1 | PATH 2 | remote: /home/aaron/Projects/Personal/pluginaweek/state_machine 3 | specs: 4 | state_machine (1.2.0) 5 | 6 | GEM 7 | remote: http://www.rubygems.org/ 8 | specs: 9 | activemodel (3.2.13.rc1) 10 | activesupport (= 3.2.13.rc1) 11 | builder (~> 3.0.0) 12 | activesupport (3.2.13.rc1) 13 | i18n (= 0.6.1) 14 | multi_json (~> 1.0) 15 | appraisal (0.5.1) 16 | bundler 17 | rake 18 | bson (1.7.1) 19 | bson (1.7.1-java) 20 | builder (3.0.4) 21 | i18n (0.6.1) 22 | mongo (1.7.1) 23 | bson (~> 1.7.1) 24 | mongo_mapper (0.12.0) 25 | activemodel (~> 3.0) 26 | activesupport (~> 3.0) 27 | plucky (~> 0.5.2) 28 | multi_json (1.6.1) 29 | plucky (0.5.2) 30 | mongo (~> 1.5) 31 | rake (10.0.3) 32 | simplecov (0.7.1) 33 | multi_json (~> 1.0) 34 | simplecov-html (~> 0.7.1) 35 | simplecov-html (0.7.1) 36 | 37 | PLATFORMS 38 | java 39 | ruby 40 | 41 | DEPENDENCIES 42 | activemodel (= 3.2.13.rc1) 43 | appraisal (~> 0.5.0) 44 | mongo (~> 1.7.0) 45 | mongo_mapper (= 0.12.0) 46 | rake 47 | simplecov 48 | state_machine! 49 | -------------------------------------------------------------------------------- /lib/state_machine/yard/handlers/base.rb: -------------------------------------------------------------------------------- 1 | module StateMachine 2 | module YARD 3 | module Handlers 4 | # Handles and processes nodes 5 | class Base < ::YARD::Handlers::Ruby::Base 6 | private 7 | # Extracts the value from the node as either a string or symbol 8 | def extract_node_name(ast) 9 | case ast.type 10 | when :symbol_literal 11 | ast.jump(:ident).source.to_sym 12 | when :string_literal 13 | ast.jump(:tstring_content).source 14 | else 15 | nil 16 | end 17 | end 18 | 19 | # Extracts the values from the node as either strings or symbols. 20 | # If the node isn't an array, it'll be converted to an array. 21 | def extract_node_names(ast, convert_to_array = true) 22 | if [nil, :array].include?(ast.type) 23 | ast.children.map {|child| extract_node_name(child)} 24 | else 25 | node_name = extract_node_name(ast) 26 | convert_to_array ? [node_name] : node_name 27 | end 28 | end 29 | end 30 | end 31 | end 32 | end 33 | -------------------------------------------------------------------------------- /examples/merb-rest/controller.rb: -------------------------------------------------------------------------------- 1 | class Users < Application 2 | # GET /users 3 | def index 4 | @users = User.all 5 | display @users 6 | end 7 | 8 | # GET /users/1 9 | def show(id) 10 | @user = User.get(id) 11 | raise NotFound unless @user 12 | display @user 13 | end 14 | 15 | # GET /users/new 16 | def new 17 | only_provides :html 18 | @user = User.new 19 | display @user 20 | end 21 | 22 | # GET /users/1/edit 23 | def edit(id) 24 | only_provides :html 25 | @user = User.get(id) 26 | raise NotFound unless @user 27 | display @user 28 | end 29 | 30 | # POST /users 31 | def create(user) 32 | @user = User.new(user) 33 | if @user.save 34 | redirect resource(@user), :message => {:notice => "User was successfully created"} 35 | else 36 | message[:error] = "User failed to be created" 37 | render :new 38 | end 39 | end 40 | 41 | # PUT /users/1 42 | def update(id, user) 43 | @user = User.get(id) 44 | raise NotFound unless @user 45 | if @user.update_attributes(user) 46 | redirect resource(@user) 47 | else 48 | display @user, :edit 49 | end 50 | end 51 | end 52 | -------------------------------------------------------------------------------- /gemfiles/mongoid_2.0.0.gemfile.lock: -------------------------------------------------------------------------------- 1 | PATH 2 | remote: /home/aaron/Projects/Personal/pluginaweek/state_machine 3 | specs: 4 | state_machine (1.2.0) 5 | 6 | GEM 7 | remote: http://www.rubygems.org/ 8 | specs: 9 | activemodel (3.1.11) 10 | activesupport (= 3.1.11) 11 | builder (~> 3.0.0) 12 | i18n (~> 0.6) 13 | activesupport (3.1.11) 14 | multi_json (~> 1.0) 15 | appraisal (0.5.1) 16 | bundler 17 | rake 18 | bson (1.7.1) 19 | bson (1.7.1-java) 20 | builder (3.0.4) 21 | i18n (0.6.1) 22 | mongo (1.7.1) 23 | bson (~> 1.7.1) 24 | mongoid (2.0.0) 25 | activemodel (~> 3.0) 26 | mongo (~> 1.2) 27 | tzinfo (~> 0.3.22) 28 | will_paginate (~> 3.0.pre) 29 | multi_json (1.6.1) 30 | rake (10.0.3) 31 | simplecov (0.7.1) 32 | multi_json (~> 1.0) 33 | simplecov-html (~> 0.7.1) 34 | simplecov-html (0.7.1) 35 | tzinfo (0.3.35) 36 | will_paginate (3.0.4) 37 | 38 | PLATFORMS 39 | java 40 | ruby 41 | 42 | DEPENDENCIES 43 | activemodel (~> 3.1.0) 44 | appraisal (~> 0.5.0) 45 | mongo (~> 1.7.0) 46 | mongoid (= 2.0.0) 47 | rake 48 | simplecov 49 | state_machine! 50 | -------------------------------------------------------------------------------- /state_machine.gemspec: -------------------------------------------------------------------------------- 1 | $LOAD_PATH.unshift File.expand_path('../lib', __FILE__) 2 | require 'state_machine/version' 3 | 4 | Gem::Specification.new do |s| 5 | s.name = "state_machine" 6 | s.version = StateMachine::VERSION 7 | s.authors = ["Aaron Pfeifer"] 8 | s.email = "aaron@pluginaweek.org" 9 | s.homepage = "http://www.pluginaweek.org" 10 | s.description = "Adds support for creating state machines for attributes on any Ruby class" 11 | s.summary = "State machines for attributes" 12 | s.require_paths = ["lib"] 13 | ignores = File.read(".gitignore").split.map {|i| i.sub(/\/$/, "/*").sub(/^[^\/]/, "**/\\0")} 14 | s.files = (Dir[".*"] + Dir["**/*"]).select {|f| File.file?(f) && !ignores.any? {|i| File.fnmatch(i, "/#{f}")}} 15 | s.test_files = s.files.grep(/^test\//) 16 | s.rdoc_options = %w(--line-numbers --inline-source --title state_machine --main README.md) 17 | s.extra_rdoc_files = %w(README.md CHANGELOG.md LICENSE) 18 | 19 | s.add_development_dependency("rake") 20 | s.add_development_dependency("simplecov") 21 | s.add_development_dependency("appraisal", "~> 0.5.0") 22 | end 23 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | require 'rubygems' 2 | require 'bundler' 3 | Bundler.setup 4 | 5 | require 'rake' 6 | require 'rake/testtask' 7 | 8 | require 'appraisal' 9 | 10 | desc 'Default: run all tests.' 11 | task :default => :test 12 | 13 | desc "Test state_machine." 14 | Rake::TestTask.new(:test) do |t| 15 | integration = %w(active_model active_record data_mapper mongoid mongo_mapper sequel).detect do |name| 16 | Bundler.default_gemfile.to_s.include?(name) 17 | end 18 | 19 | t.libs << 'lib' 20 | t.test_files = integration ? Dir["test/unit/integrations/#{integration}_test.rb"] : Dir['test/{functional,unit}/*_test.rb'] + ['test/unit/integrations/base_test.rb'] 21 | t.verbose = true 22 | t.warning = true if ENV['WARNINGS'] 23 | end 24 | 25 | namespace :appraisal do 26 | desc "Run the given task for a particular integration's appraisals" 27 | task :integration do 28 | integration = ENV['INTEGRATION'] 29 | 30 | Appraisal::File.each do |appraisal| 31 | if appraisal.name.include?(integration) 32 | appraisal.install 33 | Appraisal::Command.from_args(appraisal.gemfile_path).run 34 | end 35 | end 36 | 37 | exit 38 | end 39 | end 40 | 41 | load File.dirname(__FILE__) + '/lib/tasks/state_machine.rake' 42 | -------------------------------------------------------------------------------- /lib/state_machine/integrations/active_model/observer.rb: -------------------------------------------------------------------------------- 1 | module StateMachine 2 | module Integrations #:nodoc: 3 | module ActiveModel 4 | # Adds support for invoking callbacks on ActiveModel observers with more 5 | # than one argument (e.g. the record *and* the state transition). By 6 | # default, ActiveModel only supports passing the record into the 7 | # callbacks. 8 | # 9 | # For example: 10 | # 11 | # class VehicleObserver < ActiveModel::Observer 12 | # # The default behavior: only pass in the record 13 | # def after_save(vehicle) 14 | # end 15 | # 16 | # # Custom behavior: allow the transition to be passed in as well 17 | # def after_transition(vehicle, transition) 18 | # Audit.log(vehicle, transition) 19 | # end 20 | # end 21 | module Observer 22 | def update_with_transition(observer_update) 23 | method = observer_update.method 24 | send(method, *observer_update.args) if respond_to?(method) 25 | end 26 | end 27 | end 28 | end 29 | end 30 | 31 | ActiveModel::Observer.class_eval do 32 | include StateMachine::Integrations::ActiveModel::Observer 33 | end if defined?(ActiveModel::Observer) 34 | -------------------------------------------------------------------------------- /gemfiles/active_record_3.0.5.gemfile.lock: -------------------------------------------------------------------------------- 1 | PATH 2 | remote: /home/aaron/Projects/Personal/pluginaweek/state_machine 3 | specs: 4 | state_machine (1.2.0) 5 | 6 | GEM 7 | remote: http://www.rubygems.org/ 8 | specs: 9 | activemodel (3.0.5) 10 | activesupport (= 3.0.5) 11 | builder (~> 2.1.2) 12 | i18n (~> 0.4) 13 | activerecord (3.0.5) 14 | activemodel (= 3.0.5) 15 | activesupport (= 3.0.5) 16 | arel (~> 2.0.2) 17 | tzinfo (~> 0.3.23) 18 | activerecord-jdbc-adapter (1.2.7) 19 | activerecord-jdbcsqlite3-adapter (1.2.7) 20 | activerecord-jdbc-adapter (~> 1.2.7) 21 | jdbc-sqlite3 (~> 3.7.2) 22 | activesupport (3.0.5) 23 | appraisal (0.5.1) 24 | bundler 25 | rake 26 | arel (2.0.10) 27 | builder (2.1.2) 28 | i18n (0.6.1) 29 | jdbc-sqlite3 (3.7.2.1) 30 | multi_json (1.6.1) 31 | rake (10.0.3) 32 | simplecov (0.7.1) 33 | multi_json (~> 1.0) 34 | simplecov-html (~> 0.7.1) 35 | simplecov-html (0.7.1) 36 | sqlite3-ruby (1.3.1) 37 | tzinfo (0.3.35) 38 | 39 | PLATFORMS 40 | java 41 | ruby 42 | 43 | DEPENDENCIES 44 | activerecord (= 3.0.5) 45 | activerecord-jdbcsqlite3-adapter (= 1.2.7) 46 | appraisal (~> 0.5.0) 47 | rake 48 | simplecov 49 | sqlite3-ruby (= 1.3.1) 50 | state_machine! 51 | -------------------------------------------------------------------------------- /gemfiles/active_record_3.1.1.gemfile.lock: -------------------------------------------------------------------------------- 1 | PATH 2 | remote: /home/aaron/Projects/Personal/pluginaweek/state_machine 3 | specs: 4 | state_machine (1.2.0) 5 | 6 | GEM 7 | remote: http://www.rubygems.org/ 8 | specs: 9 | activemodel (3.1.1) 10 | activesupport (= 3.1.1) 11 | builder (~> 3.0.0) 12 | i18n (~> 0.6) 13 | activerecord (3.1.1) 14 | activemodel (= 3.1.1) 15 | activesupport (= 3.1.1) 16 | arel (~> 2.2.1) 17 | tzinfo (~> 0.3.29) 18 | activerecord-jdbc-adapter (1.2.7) 19 | activerecord-jdbcsqlite3-adapter (1.2.7) 20 | activerecord-jdbc-adapter (~> 1.2.7) 21 | jdbc-sqlite3 (~> 3.7.2) 22 | activesupport (3.1.1) 23 | multi_json (~> 1.0) 24 | appraisal (0.5.1) 25 | bundler 26 | rake 27 | arel (2.2.3) 28 | builder (3.0.4) 29 | i18n (0.6.1) 30 | jdbc-sqlite3 (3.7.2.1) 31 | multi_json (1.6.1) 32 | rake (10.0.3) 33 | simplecov (0.7.1) 34 | multi_json (~> 1.0) 35 | simplecov-html (~> 0.7.1) 36 | simplecov-html (0.7.1) 37 | sqlite3 (1.3.6) 38 | tzinfo (0.3.35) 39 | 40 | PLATFORMS 41 | java 42 | ruby 43 | 44 | DEPENDENCIES 45 | activerecord (= 3.1.1) 46 | activerecord-jdbcsqlite3-adapter (= 1.2.7) 47 | appraisal (~> 0.5.0) 48 | rake 49 | simplecov 50 | sqlite3 (= 1.3.6) 51 | state_machine! 52 | -------------------------------------------------------------------------------- /gemfiles/active_record_3.2.12.gemfile.lock: -------------------------------------------------------------------------------- 1 | PATH 2 | remote: /home/aaron/Projects/Personal/pluginaweek/state_machine 3 | specs: 4 | state_machine (1.2.0) 5 | 6 | GEM 7 | remote: http://www.rubygems.org/ 8 | specs: 9 | activemodel (3.2.12) 10 | activesupport (= 3.2.12) 11 | builder (~> 3.0.0) 12 | activerecord (3.2.12) 13 | activemodel (= 3.2.12) 14 | activesupport (= 3.2.12) 15 | arel (~> 3.0.2) 16 | tzinfo (~> 0.3.29) 17 | activerecord-jdbc-adapter (1.2.7) 18 | activerecord-jdbcsqlite3-adapter (1.2.7) 19 | activerecord-jdbc-adapter (~> 1.2.7) 20 | jdbc-sqlite3 (~> 3.7.2) 21 | activesupport (3.2.12) 22 | i18n (~> 0.6) 23 | multi_json (~> 1.0) 24 | appraisal (0.5.1) 25 | bundler 26 | rake 27 | arel (3.0.2) 28 | builder (3.0.4) 29 | i18n (0.6.1) 30 | jdbc-sqlite3 (3.7.2.1) 31 | multi_json (1.6.1) 32 | rake (10.0.3) 33 | simplecov (0.7.1) 34 | multi_json (~> 1.0) 35 | simplecov-html (~> 0.7.1) 36 | simplecov-html (0.7.1) 37 | sqlite3 (1.3.6) 38 | tzinfo (0.3.35) 39 | 40 | PLATFORMS 41 | java 42 | ruby 43 | 44 | DEPENDENCIES 45 | activerecord (= 3.2.12) 46 | activerecord-jdbcsqlite3-adapter (= 1.2.7) 47 | appraisal (~> 0.5.0) 48 | rake 49 | simplecov 50 | sqlite3 (= 1.3.6) 51 | state_machine! 52 | -------------------------------------------------------------------------------- /gemfiles/active_record_3.0.0.gemfile.lock: -------------------------------------------------------------------------------- 1 | PATH 2 | remote: /home/aaron/Projects/Personal/pluginaweek/state_machine 3 | specs: 4 | state_machine (1.2.0) 5 | 6 | GEM 7 | remote: http://www.rubygems.org/ 8 | specs: 9 | activemodel (3.0.0) 10 | activesupport (= 3.0.0) 11 | builder (~> 2.1.2) 12 | i18n (~> 0.4.1) 13 | activerecord (3.0.0) 14 | activemodel (= 3.0.0) 15 | activesupport (= 3.0.0) 16 | arel (~> 1.0.0) 17 | tzinfo (~> 0.3.23) 18 | activerecord-jdbc-adapter (1.2.7) 19 | activerecord-jdbcsqlite3-adapter (1.2.7) 20 | activerecord-jdbc-adapter (~> 1.2.7) 21 | jdbc-sqlite3 (~> 3.7.2) 22 | activesupport (3.0.0) 23 | appraisal (0.5.1) 24 | bundler 25 | rake 26 | arel (1.0.1) 27 | activesupport (~> 3.0.0) 28 | builder (2.1.2) 29 | i18n (0.4.2) 30 | jdbc-sqlite3 (3.7.2.1) 31 | multi_json (1.6.1) 32 | rake (10.0.3) 33 | simplecov (0.7.1) 34 | multi_json (~> 1.0) 35 | simplecov-html (~> 0.7.1) 36 | simplecov-html (0.7.1) 37 | sqlite3-ruby (1.3.1) 38 | tzinfo (0.3.35) 39 | 40 | PLATFORMS 41 | java 42 | ruby 43 | 44 | DEPENDENCIES 45 | activerecord (= 3.0.0) 46 | activerecord-jdbcsqlite3-adapter (= 1.2.7) 47 | appraisal (~> 0.5.0) 48 | rake 49 | simplecov 50 | sqlite3-ruby (= 1.3.1) 51 | state_machine! 52 | -------------------------------------------------------------------------------- /lib/tasks/state_machine.rb: -------------------------------------------------------------------------------- 1 | namespace :state_machine do 2 | desc 'Draws state machines using GraphViz (options: CLASS=User,Vehicle; FILE=user.rb,vehicle.rb [not required in Rails / Merb]; FONT=Arial; FORMAT=png; ORIENTATION=portrait; HUMAN_NAMES=true' 3 | task :draw do 4 | # Build drawing options 5 | options = {} 6 | options[:file] = ENV['FILE'] if ENV['FILE'] 7 | options[:path] = ENV['TARGET'] if ENV['TARGET'] 8 | options[:format] = ENV['FORMAT'] if ENV['FORMAT'] 9 | options[:font] = ENV['FONT'] if ENV['FONT'] 10 | options[:orientation] = ENV['ORIENTATION'] if ENV['ORIENTATION'] 11 | options[:human_names] = ENV['HUMAN_NAMES'] == 'true' if ENV['HUMAN_NAMES'] 12 | 13 | if defined?(Rails) 14 | puts "Files are automatically loaded in Rails; ignoring FILE option" if options.delete(:file) 15 | Rake::Task['environment'].invoke 16 | elsif defined?(Merb) 17 | puts "Files are automatically loaded in Merb; ignoring FILE option" if options.delete(:file) 18 | Rake::Task['merb_env'].invoke 19 | 20 | # Fix ruby-graphviz being incompatible with Merb's process title 21 | $0 = 'rake' 22 | else 23 | # Load the library 24 | $:.unshift(File.dirname(__FILE__) + '/..') 25 | require 'state_machine' 26 | end 27 | 28 | StateMachine::Machine.draw(ENV['CLASS'], options) 29 | end 30 | end 31 | -------------------------------------------------------------------------------- /gemfiles/active_record_3.2.13.rc1.gemfile.lock: -------------------------------------------------------------------------------- 1 | PATH 2 | remote: /home/aaron/Projects/Personal/pluginaweek/state_machine 3 | specs: 4 | state_machine (1.2.0) 5 | 6 | GEM 7 | remote: http://www.rubygems.org/ 8 | specs: 9 | activemodel (3.2.13.rc1) 10 | activesupport (= 3.2.13.rc1) 11 | builder (~> 3.0.0) 12 | activerecord (3.2.13.rc1) 13 | activemodel (= 3.2.13.rc1) 14 | activesupport (= 3.2.13.rc1) 15 | arel (~> 3.0.2) 16 | tzinfo (~> 0.3.29) 17 | activerecord-jdbc-adapter (1.2.7) 18 | activerecord-jdbcsqlite3-adapter (1.2.7) 19 | activerecord-jdbc-adapter (~> 1.2.7) 20 | jdbc-sqlite3 (~> 3.7.2) 21 | activesupport (3.2.13.rc1) 22 | i18n (= 0.6.1) 23 | multi_json (~> 1.0) 24 | appraisal (0.5.1) 25 | bundler 26 | rake 27 | arel (3.0.2) 28 | builder (3.0.4) 29 | i18n (0.6.1) 30 | jdbc-sqlite3 (3.7.2.1) 31 | multi_json (1.6.1) 32 | rake (10.0.3) 33 | simplecov (0.7.1) 34 | multi_json (~> 1.0) 35 | simplecov-html (~> 0.7.1) 36 | simplecov-html (0.7.1) 37 | sqlite3 (1.3.6) 38 | tzinfo (0.3.35) 39 | 40 | PLATFORMS 41 | java 42 | ruby 43 | 44 | DEPENDENCIES 45 | activerecord (= 3.2.13.rc1) 46 | activerecord-jdbcsqlite3-adapter (= 1.2.7) 47 | appraisal (~> 0.5.0) 48 | rake 49 | simplecov 50 | sqlite3 (= 1.3.6) 51 | state_machine! 52 | -------------------------------------------------------------------------------- /gemfiles/data_mapper_0.10.2.gemfile.lock: -------------------------------------------------------------------------------- 1 | PATH 2 | remote: /home/aaron/Projects/Personal/pluginaweek/state_machine 3 | specs: 4 | state_machine (1.2.0) 5 | 6 | GEM 7 | remote: http://www.rubygems.org/ 8 | specs: 9 | addressable (2.3.2) 10 | appraisal (0.5.1) 11 | bundler 12 | rake 13 | data_objects (0.10.2) 14 | addressable (~> 2.1) 15 | dm-core (0.10.2) 16 | addressable (~> 2.1) 17 | extlib (~> 0.9.14) 18 | dm-migrations (0.10.2) 19 | dm-core (~> 0.10.2) 20 | dm-observer (0.10.2) 21 | dm-core (~> 0.10.2) 22 | dm-validations (0.10.2) 23 | dm-core (~> 0.10.2) 24 | do_jdbc (0.10.2-java) 25 | data_objects (= 0.10.2) 26 | do_sqlite3 (0.10.2) 27 | data_objects (= 0.10.2) 28 | do_sqlite3 (0.10.2-java) 29 | data_objects (= 0.10.2) 30 | do_jdbc (= 0.10.2) 31 | jdbc-sqlite3 (>= 3.5.8) 32 | extlib (0.9.16) 33 | jdbc-sqlite3 (3.7.2.1) 34 | multi_json (1.6.1) 35 | rake (10.0.3) 36 | simplecov (0.7.1) 37 | multi_json (~> 1.0) 38 | simplecov-html (~> 0.7.1) 39 | simplecov-html (0.7.1) 40 | 41 | PLATFORMS 42 | java 43 | ruby 44 | 45 | DEPENDENCIES 46 | appraisal (~> 0.5.0) 47 | data_objects (= 0.10.2) 48 | dm-core (= 0.10.2) 49 | dm-migrations (= 0.10.2) 50 | dm-observer (= 0.10.2) 51 | dm-validations (= 0.10.2) 52 | do_sqlite3 (= 0.10.2) 53 | extlib (= 0.9.16) 54 | rake 55 | simplecov 56 | state_machine! 57 | -------------------------------------------------------------------------------- /examples/doc/file_list.html: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 27 |
28 |

File List

29 | 38 | 39 | 40 | 44 |
45 | 46 | 47 | -------------------------------------------------------------------------------- /test/unit/error_test.rb: -------------------------------------------------------------------------------- 1 | require File.expand_path(File.dirname(__FILE__) + '/../test_helper') 2 | 3 | class ErrorByDefaultTest < Test::Unit::TestCase 4 | def setup 5 | @machine = StateMachine::Machine.new(Class.new) 6 | @collection = StateMachine::NodeCollection.new(@machine) 7 | end 8 | 9 | def test_should_not_have_any_nodes 10 | assert_equal 0, @collection.length 11 | end 12 | 13 | def test_should_have_a_machine 14 | assert_equal @machine, @collection.machine 15 | end 16 | 17 | def test_should_index_by_name 18 | @collection << object = Struct.new(:name).new(:parked) 19 | assert_equal object, @collection[:parked] 20 | end 21 | end 22 | 23 | class ErrorWithMessageTest < Test::Unit::TestCase 24 | def setup 25 | @machine = StateMachine::Machine.new(Class.new) 26 | @collection = StateMachine::NodeCollection.new(@machine) 27 | end 28 | 29 | def test_should_raise_exception_if_invalid_option_specified 30 | exception = assert_raise(ArgumentError) { StateMachine::NodeCollection.new(@machine, :invalid => true) } 31 | assert_equal 'Invalid key(s): invalid', exception.message 32 | end 33 | 34 | def test_should_raise_exception_on_lookup_if_invalid_index_specified 35 | exception = assert_raise(ArgumentError) { @collection[:something, :invalid] } 36 | assert_equal 'Invalid index: :invalid', exception.message 37 | end 38 | 39 | def test_should_raise_exception_on_fetch_if_invalid_index_specified 40 | exception = assert_raise(ArgumentError) { @collection.fetch(:something, :invalid) } 41 | assert_equal 'Invalid index: :invalid', exception.message 42 | end 43 | end 44 | -------------------------------------------------------------------------------- /lib/state_machine/yard/handlers/transition.rb: -------------------------------------------------------------------------------- 1 | module StateMachine 2 | module YARD 3 | module Handlers 4 | # Handles and processes #transition 5 | class Transition < Base 6 | handles method_call(:transition) 7 | 8 | def process 9 | if [StateMachine::Machine, StateMachine::Event, StateMachine::State].include?(owner.class) 10 | options = {} 11 | 12 | # Extract requirements 13 | ast = statement.parameters.first 14 | ast.children.each do |assoc| 15 | # Skip conditionals 16 | next if %w(if unless).include?(assoc[0].jump(:ident).source) 17 | 18 | options[extract_requirement(assoc[0])] = extract_requirement(assoc[1]) 19 | end 20 | 21 | owner.transition(options) 22 | end 23 | end 24 | 25 | private 26 | # Extracts the statement requirement from the given node 27 | def extract_requirement(ast) 28 | case ast.type 29 | when :symbol_literal, :string_literal, :array 30 | extract_node_names(ast, false) 31 | when :binary 32 | AllMatcher.instance - extract_node_names(ast.children.last) 33 | when :var_ref, :vcall 34 | case ast.source 35 | when 'nil' 36 | nil 37 | when 'same' 38 | LoopbackMatcher.instance 39 | else 40 | AllMatcher.instance 41 | end 42 | end 43 | end 44 | end 45 | end 46 | end 47 | end 48 | -------------------------------------------------------------------------------- /gemfiles/data_mapper_1.1.0.gemfile.lock: -------------------------------------------------------------------------------- 1 | PATH 2 | remote: /home/aaron/Projects/Personal/pluginaweek/state_machine 3 | specs: 4 | state_machine (1.2.0) 5 | 6 | GEM 7 | remote: http://www.rubygems.org/ 8 | specs: 9 | addressable (2.2.8) 10 | appraisal (0.5.1) 11 | bundler 12 | rake 13 | data_objects (0.10.12) 14 | addressable (~> 2.1) 15 | dm-core (1.1.0) 16 | addressable (~> 2.2.4) 17 | dm-do-adapter (1.1.0) 18 | data_objects (~> 0.10.2) 19 | dm-core (~> 1.1.0) 20 | dm-migrations (1.1.0) 21 | dm-core (~> 1.1.0) 22 | dm-observer (1.1.0) 23 | dm-core (~> 1.1.0) 24 | dm-sqlite-adapter (1.1.0) 25 | dm-do-adapter (~> 1.1.0) 26 | do_sqlite3 (~> 0.10.2) 27 | dm-transactions (1.1.0) 28 | dm-core (~> 1.1.0) 29 | dm-validations (1.1.0) 30 | dm-core (~> 1.1.0) 31 | do_jdbc (0.10.12-java) 32 | data_objects (= 0.10.12) 33 | do_sqlite3 (0.10.12) 34 | data_objects (= 0.10.12) 35 | do_sqlite3 (0.10.12-java) 36 | data_objects (= 0.10.12) 37 | do_jdbc (= 0.10.12) 38 | jdbc-sqlite3 (>= 3.5.8) 39 | jdbc-sqlite3 (3.7.2.1) 40 | multi_json (1.6.1) 41 | rake (10.0.3) 42 | simplecov (0.7.1) 43 | multi_json (~> 1.0) 44 | simplecov-html (~> 0.7.1) 45 | simplecov-html (0.7.1) 46 | 47 | PLATFORMS 48 | java 49 | ruby 50 | 51 | DEPENDENCIES 52 | appraisal (~> 0.5.0) 53 | dm-core (= 1.1.0) 54 | dm-migrations (= 1.1.0) 55 | dm-observer (= 1.1.0) 56 | dm-sqlite-adapter (= 1.1.0) 57 | dm-transactions (= 1.1.0) 58 | dm-validations (= 1.1.0) 59 | rake 60 | simplecov 61 | state_machine! 62 | -------------------------------------------------------------------------------- /gemfiles/data_mapper_1.2.0.gemfile.lock: -------------------------------------------------------------------------------- 1 | PATH 2 | remote: /home/aaron/Projects/Personal/pluginaweek/state_machine 3 | specs: 4 | state_machine (1.2.0) 5 | 6 | GEM 7 | remote: http://www.rubygems.org/ 8 | specs: 9 | addressable (2.2.8) 10 | appraisal (0.5.1) 11 | bundler 12 | rake 13 | data_objects (0.10.12) 14 | addressable (~> 2.1) 15 | dm-core (1.2.0) 16 | addressable (~> 2.2.6) 17 | dm-do-adapter (1.2.0) 18 | data_objects (~> 0.10.6) 19 | dm-core (~> 1.2.0) 20 | dm-migrations (1.2.0) 21 | dm-core (~> 1.2.0) 22 | dm-observer (1.2.0) 23 | dm-core (~> 1.2.0) 24 | dm-sqlite-adapter (1.2.0) 25 | dm-do-adapter (~> 1.2.0) 26 | do_sqlite3 (~> 0.10.6) 27 | dm-transactions (1.2.0) 28 | dm-core (~> 1.2.0) 29 | dm-validations (1.2.0) 30 | dm-core (~> 1.2.0) 31 | do_jdbc (0.10.12-java) 32 | data_objects (= 0.10.12) 33 | do_sqlite3 (0.10.12) 34 | data_objects (= 0.10.12) 35 | do_sqlite3 (0.10.12-java) 36 | data_objects (= 0.10.12) 37 | do_jdbc (= 0.10.12) 38 | jdbc-sqlite3 (>= 3.5.8) 39 | jdbc-sqlite3 (3.7.2.1) 40 | multi_json (1.6.1) 41 | rake (10.0.3) 42 | simplecov (0.7.1) 43 | multi_json (~> 1.0) 44 | simplecov-html (~> 0.7.1) 45 | simplecov-html (0.7.1) 46 | 47 | PLATFORMS 48 | java 49 | ruby 50 | 51 | DEPENDENCIES 52 | appraisal (~> 0.5.0) 53 | dm-core (= 1.2.0) 54 | dm-migrations (= 1.2.0) 55 | dm-observer (= 1.2.0) 56 | dm-sqlite-adapter (= 1.2.0) 57 | dm-transactions (= 1.2.0) 58 | dm-validations (= 1.2.0) 59 | rake 60 | simplecov 61 | state_machine! 62 | -------------------------------------------------------------------------------- /gemfiles/data_mapper_1.0.0.gemfile.lock: -------------------------------------------------------------------------------- 1 | PATH 2 | remote: /home/aaron/Projects/Personal/pluginaweek/state_machine 3 | specs: 4 | state_machine (1.2.0) 5 | 6 | GEM 7 | remote: http://www.rubygems.org/ 8 | specs: 9 | addressable (2.3.2) 10 | appraisal (0.5.1) 11 | bundler 12 | rake 13 | data_objects (0.10.12) 14 | addressable (~> 2.1) 15 | dm-core (1.0.0) 16 | addressable (~> 2.1) 17 | extlib (~> 0.9.15) 18 | dm-do-adapter (1.0.0) 19 | data_objects (~> 0.10.1) 20 | dm-core (~> 1.0.0) 21 | dm-migrations (1.0.0) 22 | dm-core (~> 1.0.0) 23 | dm-observer (1.0.0) 24 | dm-core (~> 1.0.0) 25 | dm-sqlite-adapter (1.0.0) 26 | dm-do-adapter (~> 1.0.0) 27 | do_sqlite3 (~> 0.10.2) 28 | dm-transactions (1.0.0) 29 | dm-core (~> 1.0.0) 30 | dm-validations (1.0.0) 31 | dm-core (~> 1.0.0) 32 | do_jdbc (0.10.12-java) 33 | data_objects (= 0.10.12) 34 | do_sqlite3 (0.10.12) 35 | data_objects (= 0.10.12) 36 | do_sqlite3 (0.10.12-java) 37 | data_objects (= 0.10.12) 38 | do_jdbc (= 0.10.12) 39 | jdbc-sqlite3 (>= 3.5.8) 40 | extlib (0.9.16) 41 | jdbc-sqlite3 (3.7.2.1) 42 | multi_json (1.6.1) 43 | rake (10.0.3) 44 | simplecov (0.7.1) 45 | multi_json (~> 1.0) 46 | simplecov-html (~> 0.7.1) 47 | simplecov-html (0.7.1) 48 | 49 | PLATFORMS 50 | java 51 | ruby 52 | 53 | DEPENDENCIES 54 | appraisal (~> 0.5.0) 55 | dm-core (= 1.0.0) 56 | dm-migrations (= 1.0.0) 57 | dm-observer (= 1.0.0) 58 | dm-sqlite-adapter (= 1.0.0) 59 | dm-transactions (= 1.0.0) 60 | dm-validations (= 1.0.0) 61 | rake 62 | simplecov 63 | state_machine! 64 | -------------------------------------------------------------------------------- /gemfiles/data_mapper_1.0.1.gemfile.lock: -------------------------------------------------------------------------------- 1 | PATH 2 | remote: /home/aaron/Projects/Personal/pluginaweek/state_machine 3 | specs: 4 | state_machine (1.2.0) 5 | 6 | GEM 7 | remote: http://www.rubygems.org/ 8 | specs: 9 | addressable (2.3.2) 10 | appraisal (0.5.1) 11 | bundler 12 | rake 13 | data_objects (0.10.12) 14 | addressable (~> 2.1) 15 | dm-core (1.0.1) 16 | addressable (~> 2.2) 17 | extlib (~> 0.9.15) 18 | dm-do-adapter (1.0.1) 19 | data_objects (~> 0.10.2) 20 | dm-core (~> 1.0.1) 21 | dm-migrations (1.0.1) 22 | dm-core (~> 1.0.1) 23 | dm-observer (1.0.1) 24 | dm-core (~> 1.0.1) 25 | dm-sqlite-adapter (1.0.1) 26 | dm-do-adapter (~> 1.0.1) 27 | do_sqlite3 (~> 0.10.2) 28 | dm-transactions (1.0.1) 29 | dm-core (~> 1.0.1) 30 | dm-validations (1.0.1) 31 | dm-core (~> 1.0.1) 32 | do_jdbc (0.10.12-java) 33 | data_objects (= 0.10.12) 34 | do_sqlite3 (0.10.12) 35 | data_objects (= 0.10.12) 36 | do_sqlite3 (0.10.12-java) 37 | data_objects (= 0.10.12) 38 | do_jdbc (= 0.10.12) 39 | jdbc-sqlite3 (>= 3.5.8) 40 | extlib (0.9.16) 41 | jdbc-sqlite3 (3.7.2.1) 42 | multi_json (1.6.1) 43 | rake (10.0.3) 44 | simplecov (0.7.1) 45 | multi_json (~> 1.0) 46 | simplecov-html (~> 0.7.1) 47 | simplecov-html (0.7.1) 48 | 49 | PLATFORMS 50 | java 51 | ruby 52 | 53 | DEPENDENCIES 54 | appraisal (~> 0.5.0) 55 | dm-core (= 1.0.1) 56 | dm-migrations (= 1.0.1) 57 | dm-observer (= 1.0.1) 58 | dm-sqlite-adapter (= 1.0.1) 59 | dm-transactions (= 1.0.1) 60 | dm-validations (= 1.0.1) 61 | rake 62 | simplecov 63 | state_machine! 64 | -------------------------------------------------------------------------------- /gemfiles/data_mapper_1.0.2.gemfile.lock: -------------------------------------------------------------------------------- 1 | PATH 2 | remote: /home/aaron/Projects/Personal/pluginaweek/state_machine 3 | specs: 4 | state_machine (1.2.0) 5 | 6 | GEM 7 | remote: http://www.rubygems.org/ 8 | specs: 9 | addressable (2.3.2) 10 | appraisal (0.5.1) 11 | bundler 12 | rake 13 | data_objects (0.10.12) 14 | addressable (~> 2.1) 15 | dm-core (1.0.2) 16 | addressable (~> 2.2) 17 | extlib (~> 0.9.15) 18 | dm-do-adapter (1.0.2) 19 | data_objects (~> 0.10.2) 20 | dm-core (~> 1.0.2) 21 | dm-migrations (1.0.2) 22 | dm-core (~> 1.0.2) 23 | dm-observer (1.0.2) 24 | dm-core (~> 1.0.2) 25 | dm-sqlite-adapter (1.0.2) 26 | dm-do-adapter (~> 1.0.2) 27 | do_sqlite3 (~> 0.10.2) 28 | dm-transactions (1.0.2) 29 | dm-core (~> 1.0.2) 30 | dm-validations (1.0.2) 31 | dm-core (~> 1.0.2) 32 | do_jdbc (0.10.12-java) 33 | data_objects (= 0.10.12) 34 | do_sqlite3 (0.10.12) 35 | data_objects (= 0.10.12) 36 | do_sqlite3 (0.10.12-java) 37 | data_objects (= 0.10.12) 38 | do_jdbc (= 0.10.12) 39 | jdbc-sqlite3 (>= 3.5.8) 40 | extlib (0.9.16) 41 | jdbc-sqlite3 (3.7.2.1) 42 | multi_json (1.6.1) 43 | rake (10.0.3) 44 | simplecov (0.7.1) 45 | multi_json (~> 1.0) 46 | simplecov-html (~> 0.7.1) 47 | simplecov-html (0.7.1) 48 | 49 | PLATFORMS 50 | java 51 | ruby 52 | 53 | DEPENDENCIES 54 | appraisal (~> 0.5.0) 55 | dm-core (= 1.0.2) 56 | dm-migrations (= 1.0.2) 57 | dm-observer (= 1.0.2) 58 | dm-sqlite-adapter (= 1.0.2) 59 | dm-transactions (= 1.0.2) 60 | dm-validations (= 1.0.2) 61 | rake 62 | simplecov 63 | state_machine! 64 | -------------------------------------------------------------------------------- /lib/state_machine/matcher_helpers.rb: -------------------------------------------------------------------------------- 1 | module StateMachine 2 | # Provides a set of helper methods for generating matchers 3 | module MatcherHelpers 4 | # Represents a state that matches all known states in a machine. 5 | # 6 | # == Examples 7 | # 8 | # class Vehicle 9 | # state_machine do 10 | # before_transition any => :parked, :do => lambda {...} 11 | # before_transition all - :parked => all - :idling, :do => lambda {} 12 | # 13 | # event :park 14 | # transition all => :parked 15 | # end 16 | # 17 | # event :crash 18 | # transition all - :parked => :stalled 19 | # end 20 | # end 21 | # end 22 | # 23 | # In the above example, +all+ will match the following states since they 24 | # are known: 25 | # * +parked+ 26 | # * +stalled+ 27 | # * +idling+ 28 | def all 29 | AllMatcher.instance 30 | end 31 | alias_method :any, :all 32 | 33 | # Represents a state that matches the original +from+ state. This is useful 34 | # for defining transitions which are loopbacks. 35 | # 36 | # == Examples 37 | # 38 | # class Vehicle 39 | # state_machine do 40 | # event :ignite 41 | # transition [:idling, :first_gear] => same 42 | # end 43 | # end 44 | # end 45 | # 46 | # In the above example, +same+ will match whichever the from state is. In 47 | # the case of the +ignite+ event, it is essential the same as the following: 48 | # 49 | # transition :parked => :parked, :first_gear => :first_gear 50 | def same 51 | LoopbackMatcher.instance 52 | end 53 | end 54 | end 55 | -------------------------------------------------------------------------------- /lib/state_machine/integrations/active_model/observer_update.rb: -------------------------------------------------------------------------------- 1 | module StateMachine 2 | module Integrations #:nodoc: 3 | module ActiveModel 4 | # Represents the encapsulation of all of the details to be included in an 5 | # update to state machine observers. This allows multiple arguments to 6 | # get passed to an observer method (instead of just a single +object+) 7 | # while still respecting the way in which ActiveModel checks for the 8 | # object's list of observers. 9 | class ObserverUpdate 10 | # The method to invoke on the observer 11 | attr_reader :method 12 | 13 | # The object being transitioned 14 | attr_reader :object 15 | 16 | # The transition being run 17 | attr_reader :transition 18 | 19 | def initialize(method, object, transition) #:nodoc: 20 | @method, @object, @transition = method, object, transition 21 | end 22 | 23 | # The arguments to pass into the method 24 | def args 25 | [object, transition] 26 | end 27 | 28 | # The class of the object being transitioned. Normally the object 29 | # getting passed into observer methods is the actual instance of the 30 | # ActiveModel class. ActiveModel uses that instance's class to check 31 | # for enabled / disabled observers. 32 | # 33 | # Since state_machine is passing an ObserverUpdate instance into observer 34 | # methods, +class+ needs to be overridden so that ActiveModel can still 35 | # get access to the enabled / disabled observers. 36 | def class 37 | object.class 38 | end 39 | end 40 | end 41 | end 42 | end 43 | -------------------------------------------------------------------------------- /gemfiles/data_mapper_0.9.7.gemfile.lock: -------------------------------------------------------------------------------- 1 | PATH 2 | remote: /home/aaron/Projects/Personal/pluginaweek/state_machine 3 | specs: 4 | state_machine (1.2.0) 5 | 6 | GEM 7 | remote: http://www.rubygems.org/ 8 | specs: 9 | addressable (2.3.2) 10 | appraisal (0.5.1) 11 | bundler 12 | rake 13 | data_objects (0.9.7) 14 | addressable (~> 2.0) 15 | extlib (~> 0.9.8) 16 | hoe (>= 1.8.2) 17 | diff-lcs (1.1.3) 18 | dm-core (0.9.7) 19 | addressable (~> 2.0) 20 | data_objects (~> 0.9.7) 21 | extlib (~> 0.9.8) 22 | rspec (>= 1.1.3) 23 | dm-migrations (0.9.7) 24 | dm-core (~> 0.9.7) 25 | hoe (>= 1.8.2) 26 | dm-observer (0.9.7) 27 | dm-core (= 0.9.7) 28 | hoe (>= 1.8.2) 29 | dm-validations (0.9.7) 30 | dm-core (= 0.9.7) 31 | hoe (>= 1.8.2) 32 | do_sqlite3 (0.9.7) 33 | data_objects (= 0.9.7) 34 | hoe (>= 1.8.2) 35 | extlib (0.9.8) 36 | hoe (3.5.0) 37 | rake (>= 0.8, < 11.0) 38 | multi_json (1.6.1) 39 | rake (10.0.3) 40 | rspec (2.12.0) 41 | rspec-core (~> 2.12.0) 42 | rspec-expectations (~> 2.12.0) 43 | rspec-mocks (~> 2.12.0) 44 | rspec-core (2.12.2) 45 | rspec-expectations (2.12.1) 46 | diff-lcs (~> 1.1.3) 47 | rspec-mocks (2.12.2) 48 | simplecov (0.7.1) 49 | multi_json (~> 1.0) 50 | simplecov-html (~> 0.7.1) 51 | simplecov-html (0.7.1) 52 | 53 | PLATFORMS 54 | ruby 55 | 56 | DEPENDENCIES 57 | appraisal (~> 0.5.0) 58 | data_objects (= 0.9.7) 59 | dm-core (= 0.9.7) 60 | dm-migrations (= 0.9.7) 61 | dm-observer (= 0.9.7) 62 | dm-validations (= 0.9.7) 63 | do_sqlite3 (= 0.9.7) 64 | extlib (= 0.9.8) 65 | rake 66 | simplecov 67 | state_machine! 68 | -------------------------------------------------------------------------------- /test/unit/assertions_test.rb: -------------------------------------------------------------------------------- 1 | require File.expand_path(File.dirname(__FILE__) + '/../test_helper') 2 | 3 | class AssertionsBaseTest < Test::Unit::TestCase 4 | include StateMachine::Assertions 5 | 6 | def default_test 7 | end 8 | end 9 | 10 | class AssertValidKeysTest < AssertionsBaseTest 11 | def test_should_not_raise_exception_if_key_is_valid 12 | assert_nothing_raised { assert_valid_keys({:name => 'foo', :value => 'bar'}, :name, :value, :force) } 13 | end 14 | 15 | def test_should_raise_exception_if_key_is_invalid 16 | exception = assert_raise(ArgumentError) { assert_valid_keys({:name => 'foo', :value => 'bar', :invalid => true}, :name, :value, :force) } 17 | assert_equal 'Invalid key(s): invalid', exception.message 18 | end 19 | end 20 | 21 | class AssertExclusiveKeysTest < AssertionsBaseTest 22 | def test_should_not_raise_exception_if_no_keys_found 23 | assert_nothing_raised { assert_exclusive_keys({:on => :park}, :only, :except) } 24 | end 25 | 26 | def test_should_not_raise_exception_if_one_key_found 27 | assert_nothing_raised { assert_exclusive_keys({:only => :parked}, :only, :except) } 28 | assert_nothing_raised { assert_exclusive_keys({:except => :parked}, :only, :except) } 29 | end 30 | 31 | def test_should_raise_exception_if_two_keys_found 32 | exception = assert_raise(ArgumentError) { assert_exclusive_keys({:only => :parked, :except => :parked}, :only, :except) } 33 | assert_equal 'Conflicting keys: only, except', exception.message 34 | end 35 | 36 | def test_should_raise_exception_if_multiple_keys_found 37 | exception = assert_raise(ArgumentError) { assert_exclusive_keys({:only => :parked, :except => :parked, :on => :park}, :only, :except, :with) } 38 | assert_equal 'Conflicting keys: only, except', exception.message 39 | end 40 | end 41 | -------------------------------------------------------------------------------- /gemfiles/data_mapper_0.9.4.gemfile.lock: -------------------------------------------------------------------------------- 1 | PATH 2 | remote: /home/aaron/Projects/Personal/pluginaweek/state_machine 3 | specs: 4 | state_machine (1.2.0) 5 | 6 | GEM 7 | remote: http://www.rubygems.org/ 8 | specs: 9 | addressable (2.3.2) 10 | appraisal (0.5.1) 11 | bundler 12 | rake 13 | data_objects (0.9.4) 14 | addressable (>= 1.0.3) 15 | extlib (= 0.9.4) 16 | hoe (>= 1.7.0) 17 | diff-lcs (1.1.3) 18 | dm-core (0.9.4) 19 | addressable (>= 1.0.4) 20 | data_objects (= 0.9.4) 21 | extlib (= 0.9.4) 22 | rspec (>= 1.1.3) 23 | dm-migrations (0.9.4) 24 | dm-core (= 0.9.4) 25 | hoe (>= 1.7.0) 26 | dm-observer (0.9.4) 27 | dm-core (= 0.9.4) 28 | hoe (>= 1.7.0) 29 | dm-validations (0.9.4) 30 | dm-core (= 0.9.4) 31 | hoe (>= 1.7.0) 32 | do_sqlite3 (0.9.4) 33 | data_objects (= 0.9.4) 34 | hoe (>= 1.7.0) 35 | english (0.6.3) 36 | language 37 | extlib (0.9.4) 38 | english (>= 0.2.0) 39 | hoe (3.5.0) 40 | rake (>= 0.8, < 11.0) 41 | language (0.6.0) 42 | multi_json (1.6.1) 43 | rake (10.0.3) 44 | rspec (2.12.0) 45 | rspec-core (~> 2.12.0) 46 | rspec-expectations (~> 2.12.0) 47 | rspec-mocks (~> 2.12.0) 48 | rspec-core (2.12.2) 49 | rspec-expectations (2.12.1) 50 | diff-lcs (~> 1.1.3) 51 | rspec-mocks (2.12.2) 52 | simplecov (0.7.1) 53 | multi_json (~> 1.0) 54 | simplecov-html (~> 0.7.1) 55 | simplecov-html (0.7.1) 56 | 57 | PLATFORMS 58 | ruby 59 | 60 | DEPENDENCIES 61 | appraisal (~> 0.5.0) 62 | data_objects (= 0.9.4) 63 | dm-core (= 0.9.4) 64 | dm-migrations (= 0.9.4) 65 | dm-observer (= 0.9.4) 66 | dm-validations (= 0.9.4) 67 | do_sqlite3 (= 0.9.4) 68 | rake 69 | simplecov 70 | state_machine! 71 | -------------------------------------------------------------------------------- /lib/state_machine/assertions.rb: -------------------------------------------------------------------------------- 1 | module StateMachine 2 | # Provides a set of helper methods for making assertions about the content 3 | # of various objects 4 | module Assertions 5 | # Validates that the given hash *only* includes the specified valid keys. 6 | # If any invalid keys are found, an ArgumentError will be raised. 7 | # 8 | # == Examples 9 | # 10 | # options = {:name => 'John Smith', :age => 30} 11 | # 12 | # assert_valid_keys(options, :name) # => ArgumentError: Invalid key(s): age 13 | # assert_valid_keys(options, 'name', 'age') # => ArgumentError: Invalid key(s): age, name 14 | # assert_valid_keys(options, :name, :age) # => nil 15 | def assert_valid_keys(hash, *valid_keys) 16 | invalid_keys = hash.keys - valid_keys 17 | raise ArgumentError, "Invalid key(s): #{invalid_keys.join(', ')}" unless invalid_keys.empty? 18 | end 19 | 20 | # Validates that the given hash only includes at *most* one of a set of 21 | # exclusive keys. If more than one key is found, an ArgumentError will be 22 | # raised. 23 | # 24 | # == Examples 25 | # 26 | # options = {:only => :on, :except => :off} 27 | # assert_exclusive_keys(options, :only) # => nil 28 | # assert_exclusive_keys(options, :except) # => nil 29 | # assert_exclusive_keys(options, :only, :except) # => ArgumentError: Conflicting keys: only, except 30 | # assert_exclusive_keys(options, :only, :except, :with) # => ArgumentError: Conflicting keys: only, except 31 | def assert_exclusive_keys(hash, *exclusive_keys) 32 | conflicting_keys = exclusive_keys & hash.keys 33 | raise ArgumentError, "Conflicting keys: #{conflicting_keys.join(', ')}" unless conflicting_keys.length <= 1 34 | end 35 | end 36 | end 37 | -------------------------------------------------------------------------------- /gemfiles/data_mapper_0.9.11.gemfile.lock: -------------------------------------------------------------------------------- 1 | PATH 2 | remote: /home/aaron/Projects/Personal/pluginaweek/state_machine 3 | specs: 4 | state_machine (1.2.0) 5 | 6 | GEM 7 | remote: http://www.rubygems.org/ 8 | specs: 9 | addressable (2.0.2) 10 | launchy (>= 0.3.2) 11 | rake (>= 0.7.3) 12 | rspec (>= 1.0.8) 13 | appraisal (0.5.1) 14 | bundler 15 | rake 16 | data_objects (0.9.11) 17 | addressable (~> 2.0) 18 | extlib (~> 0.9.9) 19 | hoe (>= 1.8.2) 20 | diff-lcs (1.1.3) 21 | dm-core (0.9.11) 22 | addressable (~> 2.0.2) 23 | data_objects (~> 0.9.11) 24 | extlib (~> 0.9.11) 25 | dm-migrations (0.9.11) 26 | dm-core (= 0.9.11) 27 | dm-observer (0.9.11) 28 | dm-core (= 0.9.11) 29 | dm-validations (0.9.11) 30 | dm-core (= 0.9.11) 31 | do_sqlite3 (0.9.11) 32 | data_objects (= 0.9.11) 33 | hoe (>= 1.8.2) 34 | extlib (0.9.11) 35 | hoe (3.5.0) 36 | rake (>= 0.8, < 11.0) 37 | launchy (2.0.3) 38 | launchy (2.0.3-java) 39 | spoon (~> 0.0.1) 40 | multi_json (1.6.1) 41 | rake (10.0.3) 42 | rspec (2.12.0) 43 | rspec-core (~> 2.12.0) 44 | rspec-expectations (~> 2.12.0) 45 | rspec-mocks (~> 2.12.0) 46 | rspec-core (2.12.2) 47 | rspec-expectations (2.12.1) 48 | diff-lcs (~> 1.1.3) 49 | rspec-mocks (2.12.2) 50 | simplecov (0.7.1) 51 | multi_json (~> 1.0) 52 | simplecov-html (~> 0.7.1) 53 | simplecov-html (0.7.1) 54 | spoon (0.0.1) 55 | 56 | PLATFORMS 57 | java 58 | ruby 59 | 60 | DEPENDENCIES 61 | appraisal (~> 0.5.0) 62 | data_objects (= 0.9.11) 63 | dm-core (= 0.9.11) 64 | dm-migrations (= 0.9.11) 65 | dm-observer (= 0.9.11) 66 | dm-validations (= 0.9.11) 67 | do_sqlite3 (= 0.9.11) 68 | extlib (= 0.9.11) 69 | rake 70 | simplecov 71 | state_machine! 72 | -------------------------------------------------------------------------------- /gemfiles/active_model_4.0.0.gemfile.lock: -------------------------------------------------------------------------------- 1 | GIT 2 | remote: git://github.com/rails/rails.git 3 | revision: 4e286bf1c62e24017867fdd04bda1129a645bec6 4 | ref: 4e286bf 5 | specs: 6 | actionpack (4.0.0.beta) 7 | activesupport (= 4.0.0.beta) 8 | builder (~> 3.1.0) 9 | erubis (~> 2.7.0) 10 | rack (~> 1.5.2) 11 | rack-test (~> 0.6.2) 12 | activemodel (4.0.0.beta) 13 | activesupport (= 4.0.0.beta) 14 | builder (~> 3.1.0) 15 | activesupport (4.0.0.beta) 16 | i18n (~> 0.6) 17 | minitest (~> 4.2) 18 | multi_json (~> 1.3) 19 | thread_safe (~> 0.1) 20 | tzinfo (~> 0.3.33) 21 | railties (4.0.0.beta) 22 | actionpack (= 4.0.0.beta) 23 | activesupport (= 4.0.0.beta) 24 | rake (>= 0.8.7) 25 | rdoc (~> 3.4) 26 | thor (>= 0.17.0, < 2.0) 27 | 28 | PATH 29 | remote: /home/aaron/Projects/Personal/pluginaweek/state_machine 30 | specs: 31 | state_machine (1.2.0) 32 | 33 | GEM 34 | remote: http://www.rubygems.org/ 35 | specs: 36 | appraisal (0.5.1) 37 | bundler 38 | rake 39 | atomic (1.0.1) 40 | atomic (1.0.1-java) 41 | builder (3.1.4) 42 | erubis (2.7.0) 43 | i18n (0.6.1) 44 | json (1.7.7) 45 | json (1.7.7-java) 46 | minitest (4.6.1) 47 | multi_json (1.6.1) 48 | protected_attributes (1.0.0) 49 | activemodel (>= 4.0.0.beta, < 5.0) 50 | rack (1.5.2) 51 | rack-test (0.6.2) 52 | rack (>= 1.0) 53 | rails-observers (0.1.1) 54 | railties (~> 4.0.0.beta) 55 | rake (10.0.3) 56 | rdoc (3.12.2) 57 | json (~> 1.4) 58 | simplecov (0.7.1) 59 | multi_json (~> 1.0) 60 | simplecov-html (~> 0.7.1) 61 | simplecov-html (0.7.1) 62 | thor (0.17.0) 63 | thread_safe (0.1.0) 64 | atomic 65 | tzinfo (0.3.35) 66 | 67 | PLATFORMS 68 | java 69 | ruby 70 | 71 | DEPENDENCIES 72 | activemodel (= 4.0.0.beta)! 73 | appraisal (~> 0.5.0) 74 | protected_attributes (= 1.0.0) 75 | rails-observers (= 0.1.1) 76 | rake 77 | simplecov 78 | state_machine! 79 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: ruby 2 | script: "bundle exec rake appraisal:integration test" 3 | rvm: 4 | - 1.8.7 5 | - 1.9.2 6 | - 1.9.3 7 | - jruby-18mode 8 | - jruby-19mode 9 | - rbx-18mode 10 | - rbx-19mode 11 | env: 12 | - INTEGRATION=default 13 | - INTEGRATION=active_model 14 | - INTEGRATION=active_record 15 | - INTEGRATION=data_mapper 16 | - INTEGRATION=mongoid 17 | - INTEGRATION=mongo_mapper 18 | - INTEGRATION=sequel 19 | services: 20 | - mongodb 21 | notifications: 22 | disabled: true 23 | matrix: 24 | exclude: 25 | - rvm: jruby-18mode 26 | env: INTEGRATION=active_model 27 | - rvm: jruby-18mode 28 | env: INTEGRATION=active_record 29 | - rvm: jruby-18mode 30 | env: INTEGRATION=data_mapper 31 | - rvm: jruby-18mode 32 | env: INTEGRATION=mongoid 33 | - rvm: jruby-18mode 34 | env: INTEGRATION=mongo_mapper 35 | - rvm: jruby-18mode 36 | env: INTEGRATION=sequel 37 | - rvm: jruby-19mode 38 | env: INTEGRATION=active_model 39 | - rvm: jruby-19mode 40 | env: INTEGRATION=active_record 41 | - rvm: jruby-19mode 42 | env: INTEGRATION=data_mapper 43 | - rvm: jruby-19mode 44 | env: INTEGRATION=mongoid 45 | - rvm: jruby-19mode 46 | env: INTEGRATION=mongo_mapper 47 | - rvm: jruby-19mode 48 | env: INTEGRATION=sequel 49 | - rvm: rbx-18mode 50 | env: INTEGRATION=active_model 51 | - rvm: rbx-18mode 52 | env: INTEGRATION=active_record 53 | - rvm: rbx-18mode 54 | env: INTEGRATION=data_mapper 55 | - rvm: rbx-18mode 56 | env: INTEGRATION=mongoid 57 | - rvm: rbx-18mode 58 | env: INTEGRATION=mongo_mapper 59 | - rvm: rbx-18mode 60 | env: INTEGRATION=sequel 61 | - rvm: rbx-19mode 62 | env: INTEGRATION=active_model 63 | - rvm: rbx-19mode 64 | env: INTEGRATION=active_record 65 | - rvm: rbx-19mode 66 | env: INTEGRATION=data_mapper 67 | - rvm: rbx-19mode 68 | env: INTEGRATION=mongoid 69 | - rvm: rbx-19mode 70 | env: INTEGRATION=mongo_mapper 71 | - rvm: rbx-19mode 72 | env: INTEGRATION=sequel 73 | -------------------------------------------------------------------------------- /gemfiles/active_record_4.0.0.gemfile.lock: -------------------------------------------------------------------------------- 1 | GIT 2 | remote: git://github.com/rails/rails.git 3 | revision: 92d6dacc348a4e42d314c813a650ac578976d4c4 4 | ref: 92d6dac 5 | specs: 6 | actionpack (4.0.0.beta1) 7 | activesupport (= 4.0.0.beta1) 8 | builder (~> 3.1.0) 9 | erubis (~> 2.7.0) 10 | rack (~> 1.5.2) 11 | rack-test (~> 0.6.2) 12 | activemodel (4.0.0.beta1) 13 | activesupport (= 4.0.0.beta1) 14 | builder (~> 3.1.0) 15 | activerecord (4.0.0.beta1) 16 | activemodel (= 4.0.0.beta1) 17 | activerecord-deprecated_finders (~> 0.0.3) 18 | activesupport (= 4.0.0.beta1) 19 | arel (~> 4.0.0.beta2) 20 | activesupport (4.0.0.beta1) 21 | i18n (~> 0.6, >= 0.6.4) 22 | minitest (~> 4.2) 23 | multi_json (~> 1.3) 24 | thread_safe (~> 0.1) 25 | tzinfo (~> 0.3.37) 26 | railties (4.0.0.beta1) 27 | actionpack (= 4.0.0.beta1) 28 | activesupport (= 4.0.0.beta1) 29 | rake (>= 0.8.7) 30 | thor (>= 0.17.0, < 2.0) 31 | 32 | PATH 33 | remote: /home/aaron/Projects/Personal/pluginaweek/state_machine 34 | specs: 35 | state_machine (1.2.0) 36 | 37 | GEM 38 | remote: http://www.rubygems.org/ 39 | specs: 40 | activerecord-deprecated_finders (0.0.3) 41 | appraisal (0.5.1) 42 | bundler 43 | rake 44 | arel (4.0.0.beta2) 45 | atomic (1.0.2) 46 | atomic (1.0.2-java) 47 | builder (3.1.4) 48 | erubis (2.7.0) 49 | i18n (0.6.4) 50 | minitest (4.7.0) 51 | multi_json (1.6.1) 52 | protected_attributes (1.0.0) 53 | activemodel (>= 4.0.0.beta, < 5.0) 54 | rack (1.5.2) 55 | rack-test (0.6.2) 56 | rack (>= 1.0) 57 | rails-observers (0.1.1) 58 | railties (~> 4.0.0.beta) 59 | rake (10.0.3) 60 | simplecov (0.7.1) 61 | multi_json (~> 1.0) 62 | simplecov-html (~> 0.7.1) 63 | simplecov-html (0.7.1) 64 | sqlite3 (1.3.6) 65 | thor (0.18.0) 66 | thread_safe (0.1.0) 67 | atomic 68 | tzinfo (0.3.37) 69 | 70 | PLATFORMS 71 | java 72 | ruby 73 | 74 | DEPENDENCIES 75 | activerecord (= 4.0.0.beta1)! 76 | activerecord-deprecated_finders (= 0.0.3) 77 | appraisal (~> 0.5.0) 78 | protected_attributes (= 1.0.0) 79 | rails-observers (= 0.1.1) 80 | rake 81 | simplecov 82 | sqlite3 (= 1.3.6) 83 | state_machine! 84 | -------------------------------------------------------------------------------- /examples/doc/class_list.html: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 27 |
28 |

Class List

29 | 38 | 39 | 40 | 45 |
46 | 47 | 48 | -------------------------------------------------------------------------------- /lib/state_machine/integrations/data_mapper/versions.rb: -------------------------------------------------------------------------------- 1 | module StateMachine 2 | module Integrations #:nodoc: 3 | module DataMapper 4 | version '0.9.x - 0.10.x' do 5 | def self.active? 6 | ::DataMapper::VERSION =~ /^0\.\d\./ || ::DataMapper::VERSION =~ /^0\.10\./ 7 | end 8 | 9 | def pluralize(word) 10 | ::Extlib::Inflection.pluralize(word.to_s) 11 | end 12 | end 13 | 14 | version '0.9.x' do 15 | def self.active? 16 | ::DataMapper::VERSION =~ /^0\.9\./ 17 | end 18 | 19 | def define_action_helpers 20 | if action_hook == :save 21 | define_helper :instance, <<-end_eval, __FILE__, __LINE__ + 1 22 | def save(*) 23 | self.class.state_machines.transitions(self, :save).perform { super } 24 | end 25 | end_eval 26 | 27 | define_validation_hook 28 | else 29 | super 30 | end 31 | end 32 | end 33 | 34 | version '0.9.4 - 0.9.6' do 35 | def self.active? 36 | ::DataMapper::VERSION =~ /^0\.9\.[4-6]/ 37 | end 38 | 39 | # 0.9.4 - 0.9.6 fails to run after callbacks when validations are 40 | # enabled because of the way dm-validations integrates 41 | def define_action_helpers? 42 | super if action != :save || !supports_validations? 43 | end 44 | end 45 | 46 | version '0.10.x' do 47 | def self.active? 48 | ::DataMapper::VERSION =~ /^0\.10\./ 49 | end 50 | 51 | def define_action_helpers 52 | if action_hook == :save 53 | define_helper :instance, <<-end_eval, __FILE__, __LINE__ + 1 54 | def save(*) 55 | self.class.state_machines.transitions(self, :save).perform { super } 56 | end 57 | 58 | def save!(*) 59 | self.class.state_machines.transitions(self, :save).perform { super } 60 | end 61 | 62 | def save_self(*) 63 | self.class.state_machines.transitions(self, :save).perform { super } 64 | end 65 | end_eval 66 | 67 | define_validation_hook 68 | else 69 | super 70 | end 71 | end 72 | end 73 | 74 | version '1.0.0' do 75 | def self.active? 76 | ::DataMapper::VERSION == '1.0.0' 77 | end 78 | 79 | def pluralize(word) 80 | (defined?(::ActiveSupport::Inflector) ? ::ActiveSupport::Inflector : ::Extlib::Inflection).pluralize(word.to_s) 81 | end 82 | end 83 | end 84 | end 85 | end 86 | -------------------------------------------------------------------------------- /lib/state_machine/integrations/mongoid/versions.rb: -------------------------------------------------------------------------------- 1 | module StateMachine 2 | module Integrations #:nodoc: 3 | module Mongoid 4 | version '2.x' do 5 | def self.active? 6 | ::Mongoid::VERSION =~ /^2\./ 7 | end 8 | 9 | def define_state_initializer 10 | define_helper :instance, <<-end_eval, __FILE__, __LINE__ + 1 11 | def initialize(*) 12 | @attributes ||= {} 13 | self.class.state_machines.initialize_states(self, :static => :force, :dynamic => false) 14 | 15 | super do |*args| 16 | self.class.state_machines.initialize_states(self, :static => false) 17 | yield(*args) if block_given? 18 | end 19 | end 20 | end_eval 21 | end 22 | 23 | def owner_class_attribute_default 24 | attribute_field && attribute_field.default 25 | end 26 | 27 | def define_action_hook 28 | if action_hook == :save 29 | define_helper :instance, <<-end_eval, __FILE__, __LINE__ + 1 30 | def insert(*) 31 | self.class.state_machine(#{name.inspect}).send(:around_save, self) { super.persisted? } 32 | self 33 | end 34 | 35 | def update(*) 36 | self.class.state_machine(#{name.inspect}).send(:around_save, self) { super } 37 | end 38 | end_eval 39 | else 40 | super 41 | end 42 | end 43 | end 44 | 45 | version '2.0.x - 2.3.x' do 46 | def self.active? 47 | ::Mongoid::VERSION =~ /^2\.[0-3]\./ 48 | end 49 | 50 | def attribute_field 51 | owner_class.fields[attribute.to_s] 52 | end 53 | end 54 | 55 | version '2.0.x - 2.2.x' do 56 | def self.active? 57 | ::Mongoid::VERSION =~ /^2\.[0-2]\./ 58 | end 59 | 60 | def define_state_initializer 61 | define_helper :instance, <<-end_eval, __FILE__, __LINE__ + 1 62 | # Initializes dynamic states 63 | def initialize(*) 64 | super do |*args| 65 | self.class.state_machines.initialize_states(self, :static => false) 66 | yield(*args) if block_given? 67 | end 68 | end 69 | 70 | # Initializes static states 71 | def apply_default_attributes(*) 72 | result = super 73 | self.class.state_machines.initialize_states(self, :static => :force, :dynamic => false, :to => result) if new_record? 74 | result 75 | end 76 | end_eval 77 | end 78 | end 79 | end 80 | end 81 | end 82 | -------------------------------------------------------------------------------- /examples/doc/top-level-namespace.html: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 7 | Top Level Namespace 8 | 9 | — Documentation by YARD 0.7.5 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 32 | 33 | 56 | 57 | 58 | 59 |

Top Level Namespace 60 | 61 | 62 | 63 |

64 | 65 |
66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 |
75 |
76 | 77 |

Defined Under Namespace

78 |

79 | 80 | 81 | 82 | 83 | Classes: AutoShop, Car, TrafficLight, Vehicle 84 | 85 | 86 |

87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 |
97 | 98 | 103 | 104 | 105 | -------------------------------------------------------------------------------- /test/unit/integrations/base_test.rb: -------------------------------------------------------------------------------- 1 | require File.expand_path(File.dirname(__FILE__) + '/../../test_helper') 2 | 3 | # Load library 4 | require 'rubygems' 5 | 6 | module BaseTest 7 | class IntegrationTest < Test::Unit::TestCase 8 | def test_should_have_an_integration_name 9 | assert_equal :base, StateMachine::Integrations::Base.integration_name 10 | end 11 | 12 | def test_should_not_be_available 13 | assert !StateMachine::Integrations::Base.available? 14 | end 15 | 16 | def test_should_not_have_any_matching_ancestors 17 | assert_equal [], StateMachine::Integrations::Base.matching_ancestors 18 | end 19 | 20 | def test_should_not_match_any_classes 21 | assert !StateMachine::Integrations::Base.matches?(Class.new) 22 | end 23 | 24 | def test_should_not_have_a_locale_path 25 | assert_nil StateMachine::Integrations::Base.locale_path 26 | end 27 | end 28 | 29 | class IncludedTest < Test::Unit::TestCase 30 | def setup 31 | @integration = Module.new 32 | StateMachine::Integrations.const_set('Custom', @integration) 33 | 34 | @integration.class_eval do 35 | include StateMachine::Integrations::Base 36 | end 37 | end 38 | 39 | def test_should_not_have_any_defaults 40 | assert_nil @integration.defaults 41 | end 42 | 43 | def test_should_not_have_any_versions 44 | assert_equal [], @integration.versions 45 | end 46 | 47 | def test_should_track_version 48 | version1 = @integration.version '1.0' do 49 | def self.active? 50 | true 51 | end 52 | end 53 | 54 | version2 = @integration.version '2.0' do 55 | def self.active? 56 | false 57 | end 58 | end 59 | 60 | assert_equal [version1, version2], @integration.versions 61 | end 62 | 63 | def test_should_allow_active_versions_to_override_default_behavior 64 | @integration.class_eval do 65 | def version1_included? 66 | false 67 | end 68 | 69 | def version2_included? 70 | false 71 | end 72 | end 73 | 74 | @integration.version '1.0' do 75 | def self.active? 76 | true 77 | end 78 | 79 | def version1_included? 80 | true 81 | end 82 | end 83 | 84 | @integration.version '2.0' do 85 | def self.active? 86 | false 87 | end 88 | 89 | def version2_included? 90 | true 91 | end 92 | end 93 | 94 | @machine = StateMachine::Machine.new(Class.new, :integration => :custom) 95 | assert @machine.version1_included? 96 | assert !@machine.version2_included? 97 | end 98 | 99 | def teardown 100 | StateMachine::Integrations.send(:remove_const, 'Custom') 101 | super 102 | end 103 | end 104 | end 105 | -------------------------------------------------------------------------------- /test/unit/graph_test.rb: -------------------------------------------------------------------------------- 1 | require File.expand_path(File.dirname(__FILE__) + '/../test_helper') 2 | 3 | begin 4 | # Load library 5 | require 'graphviz' 6 | 7 | class GraphDefaultTest < Test::Unit::TestCase 8 | def setup 9 | @graph = StateMachine::Graph.new('test') 10 | end 11 | 12 | def test_should_have_a_default_font 13 | assert_equal 'Arial', @graph.font 14 | end 15 | 16 | def test_should_use_current_directory_for_filepath 17 | assert_equal './test.png', @graph.file_path 18 | end 19 | 20 | def test_should_have_a_default_file_format 21 | assert_equal 'png', @graph.file_format 22 | end 23 | 24 | def test_should_have_a_default_orientation 25 | assert_equal 'TB', @graph[:rankdir].source 26 | end 27 | end 28 | 29 | class GraphNodesTest < Test::Unit::TestCase 30 | def setup 31 | @graph = StateMachine::Graph.new('test') 32 | @node = @graph.add_nodes('parked', :shape => 'ellipse') 33 | end 34 | 35 | def test_should_return_generated_node 36 | assert_not_nil @node 37 | end 38 | 39 | def test_should_use_specified_name 40 | assert_equal @node, @graph.get_node('parked') 41 | end 42 | 43 | def test_should_use_specified_options 44 | assert_equal 'ellipse', @node['shape'].to_s.gsub('"', '') 45 | end 46 | 47 | def test_should_set_default_font 48 | assert_equal 'Arial', @node['fontname'].to_s.gsub('"', '') 49 | end 50 | end 51 | 52 | class GraphEdgesTest < Test::Unit::TestCase 53 | def setup 54 | @graph = StateMachine::Graph.new('test') 55 | @graph.add_nodes('parked', :shape => 'ellipse') 56 | @graph.add_nodes('idling', :shape => 'ellipse') 57 | @edge = @graph.add_edges('parked', 'idling', :label => 'ignite') 58 | end 59 | 60 | def test_should_return_generated_edge 61 | assert_not_nil @edge 62 | end 63 | 64 | def test_should_use_specified_nodes 65 | assert_equal 'parked', @edge.node_one(false) 66 | assert_equal 'idling', @edge.node_two(false) 67 | end 68 | 69 | def test_should_use_specified_options 70 | assert_equal 'ignite', @edge['label'].to_s.gsub('"', '') 71 | end 72 | 73 | def test_should_set_default_font 74 | assert_equal 'Arial', @edge['fontname'].to_s.gsub('"', '') 75 | end 76 | end 77 | 78 | class GraphOutputTest < Test::Unit::TestCase 79 | def setup 80 | @graph_name = "test_#{rand(1000000)}" 81 | @graph = StateMachine::Graph.new(@graph_name) 82 | @graph.add_nodes('parked', :shape => 'ellipse') 83 | @graph.add_nodes('idling', :shape => 'ellipse') 84 | @graph.add_edges('parked', 'idling', :label => 'ignite') 85 | @graph.output 86 | end 87 | 88 | def test_should_save_file 89 | assert File.exist?("./#{@graph_name}.png") 90 | end 91 | 92 | def teardown 93 | FileUtils.rm Dir["./#{@graph_name}.png"] 94 | end 95 | end 96 | rescue LoadError 97 | $stderr.puts 'Skipping GraphViz StateMachine::Graph tests. `gem install ruby-graphviz` >= v0.9.17 and try again.' 98 | end unless ENV['TRAVIS'] 99 | -------------------------------------------------------------------------------- /lib/state_machine/integrations/mongo_mapper/versions.rb: -------------------------------------------------------------------------------- 1 | module StateMachine 2 | module Integrations #:nodoc: 3 | module MongoMapper 4 | version '0.5.x - 0.6.x' do 5 | def self.active? 6 | !defined?(::MongoMapper::Plugins) 7 | end 8 | 9 | def filter_attributes(object, attributes) 10 | attributes 11 | end 12 | 13 | def define_state_initializer 14 | define_helper :instance, <<-end_eval, __FILE__, __LINE__ + 1 15 | def initialize(*args) 16 | attrs, * = args 17 | attrs && attrs.stringify_keys.key?('_id') ? super : self.class.state_machines.initialize_states(self, :static => :force) { super } 18 | end 19 | end_eval 20 | end 21 | end 22 | 23 | version '0.5.x - 0.7.x' do 24 | def self.active? 25 | !defined?(::MongoMapper::Version) || ::MongoMapper::Version =~ /^0\.[5-7]\./ 26 | end 27 | 28 | def define_scope(name, scope) 29 | lambda {|model, values| model.all(scope.call(values))} 30 | end 31 | end 32 | 33 | version '0.5.x - 0.8.x' do 34 | def self.active? 35 | !defined?(::MongoMapper::Version) || ::MongoMapper::Version =~ /^0\.[5-8]\./ 36 | end 37 | 38 | def invalidate(object, attribute, message, values = []) 39 | object.errors.add(self.attribute(attribute), generate_message(message, values)) 40 | end 41 | 42 | def define_state_accessor 43 | owner_class.key(attribute, String) unless owner_class.keys.include?(attribute) 44 | 45 | name = self.name 46 | owner_class.validates_each(attribute, :logic => lambda {|*| 47 | machine = self.class.state_machine(name) 48 | machine.invalidate(self, :state, :invalid) unless machine.states.match(self) 49 | }) 50 | end 51 | 52 | def load_locale 53 | end 54 | 55 | def supports_observers? 56 | false 57 | end 58 | 59 | def supports_validations? 60 | true 61 | end 62 | 63 | def callback_terminator 64 | end 65 | 66 | def translate(klass, key, value) 67 | value.to_s.humanize.downcase 68 | end 69 | end 70 | 71 | version '0.7.x - 0.8.3' do 72 | def self.active? 73 | # Only 0.8.x and up has a Version string available, so Plugins is used 74 | # to detect when 0.7.x is active 75 | defined?(::MongoMapper::Plugins) && (!defined?(::MongoMapper::Version) || ::MongoMapper::Version =~ /^0\.(7|8\.[0-3])\./) 76 | end 77 | 78 | def define_state_initializer 79 | define_helper :instance, <<-end_eval, __FILE__, __LINE__ + 1 80 | def initialize(*args) 81 | from_db = args[1] 82 | from_db ? super : self.class.state_machines.initialize_states(self, :static => :force) { super } 83 | end 84 | end_eval 85 | end 86 | end 87 | end 88 | end 89 | end 90 | -------------------------------------------------------------------------------- /test/unit/integrations_test.rb: -------------------------------------------------------------------------------- 1 | require File.expand_path(File.dirname(__FILE__) + '/../test_helper') 2 | 3 | class IntegrationMatcherTest < Test::Unit::TestCase 4 | def setup 5 | superclass = Class.new 6 | self.class.const_set('Vehicle', superclass) 7 | 8 | @klass = Class.new(superclass) 9 | end 10 | 11 | def test_should_return_nil_if_no_match_found 12 | assert_nil StateMachine::Integrations.match(@klass) 13 | end 14 | 15 | def test_should_return_integration_class_if_match_found 16 | integration = Module.new do 17 | include StateMachine::Integrations::Base 18 | 19 | def self.matching_ancestors 20 | ['IntegrationMatcherTest::Vehicle'] 21 | end 22 | end 23 | StateMachine::Integrations.const_set('Custom', integration) 24 | 25 | assert_equal integration, StateMachine::Integrations.match(@klass) 26 | ensure 27 | StateMachine::Integrations.send(:remove_const, 'Custom') 28 | end 29 | 30 | def test_should_return_nil_if_no_match_found_with_ancestors 31 | assert_nil StateMachine::Integrations.match_ancestors(['IntegrationMatcherTest::Fake']) 32 | end 33 | 34 | def test_should_return_integration_class_if_match_found_with_ancestors 35 | integration = Module.new do 36 | include StateMachine::Integrations::Base 37 | 38 | def self.matching_ancestors 39 | ['IntegrationMatcherTest::Vehicle'] 40 | end 41 | end 42 | StateMachine::Integrations.const_set('Custom', integration) 43 | 44 | assert_equal integration, StateMachine::Integrations.match_ancestors(['IntegrationMatcherTest::Fake', 'IntegrationMatcherTest::Vehicle']) 45 | ensure 46 | StateMachine::Integrations.send(:remove_const, 'Custom') 47 | end 48 | 49 | def teardown 50 | self.class.send(:remove_const, 'Vehicle') 51 | end 52 | end 53 | 54 | class IntegrationFinderTest < Test::Unit::TestCase 55 | def test_should_find_base 56 | assert_equal StateMachine::Integrations::Base, StateMachine::Integrations.find_by_name(:base) 57 | end 58 | 59 | def test_should_find_active_model 60 | assert_equal StateMachine::Integrations::ActiveModel, StateMachine::Integrations.find_by_name(:active_model) 61 | end 62 | 63 | def test_should_find_active_record 64 | assert_equal StateMachine::Integrations::ActiveRecord, StateMachine::Integrations.find_by_name(:active_record) 65 | end 66 | 67 | def test_should_find_data_mapper 68 | assert_equal StateMachine::Integrations::DataMapper, StateMachine::Integrations.find_by_name(:data_mapper) 69 | end 70 | 71 | def test_should_find_mongo_mapper 72 | assert_equal StateMachine::Integrations::MongoMapper, StateMachine::Integrations.find_by_name(:mongo_mapper) 73 | end 74 | 75 | def test_should_find_sequel 76 | assert_equal StateMachine::Integrations::Sequel, StateMachine::Integrations.find_by_name(:sequel) 77 | end 78 | 79 | def test_should_raise_an_exception_if_invalid 80 | exception = assert_raise(StateMachine::IntegrationNotFound) { StateMachine::Integrations.find_by_name(:invalid) } 81 | assert_equal ':invalid is an invalid integration', exception.message 82 | end 83 | end 84 | -------------------------------------------------------------------------------- /lib/state_machine/path_collection.rb: -------------------------------------------------------------------------------- 1 | require 'state_machine/path' 2 | 3 | module StateMachine 4 | # Represents a collection of paths that are generated based on a set of 5 | # requirements regarding what states to start and end on 6 | class PathCollection < Array 7 | include Assertions 8 | 9 | # The object whose state machine is being walked 10 | attr_reader :object 11 | 12 | # The state machine these path are walking 13 | attr_reader :machine 14 | 15 | # The initial state to start each path from 16 | attr_reader :from_name 17 | 18 | # The target state for each path 19 | attr_reader :to_name 20 | 21 | # Creates a new collection of paths with the given requirements. 22 | # 23 | # Configuration options: 24 | # * :from - The initial state to start from 25 | # * :to - The target end state 26 | # * :deep - Whether to enable deep searches for the target state. 27 | # * :guard - Whether to guard transitions with the if/unless 28 | # conditionals defined for each one 29 | def initialize(object, machine, options = {}) 30 | options = {:deep => false, :from => machine.states.match!(object).name}.merge(options) 31 | assert_valid_keys(options, :from, :to, :deep, :guard) 32 | 33 | @object = object 34 | @machine = machine 35 | @from_name = machine.states.fetch(options[:from]).name 36 | @to_name = options[:to] && machine.states.fetch(options[:to]).name 37 | @guard = options[:guard] 38 | @deep = options[:deep] 39 | 40 | initial_paths.each {|path| walk(path)} 41 | end 42 | 43 | # Lists all of the states that can be transitioned from through the paths in 44 | # this collection. 45 | # 46 | # For example, 47 | # 48 | # paths.from_states # => [:parked, :idling, :first_gear, ...] 49 | def from_states 50 | map {|path| path.from_states}.flatten.uniq 51 | end 52 | 53 | # Lists all of the states that can be transitioned to through the paths in 54 | # this collection. 55 | # 56 | # For example, 57 | # 58 | # paths.to_states # => [:idling, :first_gear, :second_gear, ...] 59 | def to_states 60 | map {|path| path.to_states}.flatten.uniq 61 | end 62 | 63 | # Lists all of the events that can be fired through the paths in this 64 | # collection. 65 | # 66 | # For example, 67 | # 68 | # paths.events # => [:park, :ignite, :shift_up, ...] 69 | def events 70 | map {|path| path.events}.flatten.uniq 71 | end 72 | 73 | private 74 | # Gets the initial set of paths to walk 75 | def initial_paths 76 | machine.events.transitions_for(object, :from => from_name, :guard => @guard).map do |transition| 77 | path = Path.new(object, machine, :target => to_name, :guard => @guard) 78 | path << transition 79 | path 80 | end 81 | end 82 | 83 | # Walks down the given path. Each new path that matches the configured 84 | # requirements will be added to this collection. 85 | def walk(path) 86 | self << path if path.complete? 87 | path.walk {|next_path| walk(next_path)} unless to_name && path.complete? && !@deep 88 | end 89 | end 90 | end 91 | -------------------------------------------------------------------------------- /lib/state_machine/integrations/sequel/versions.rb: -------------------------------------------------------------------------------- 1 | module StateMachine 2 | module Integrations #:nodoc: 3 | module Sequel 4 | version '2.8.x - 3.23.x' do 5 | def self.active? 6 | !defined?(::Sequel::MAJOR) || ::Sequel::MAJOR == 2 || ::Sequel::MAJOR == 3 && ::Sequel::MINOR <= 23 7 | end 8 | 9 | def define_state_initializer 10 | define_helper :instance, <<-end_eval, __FILE__, __LINE__ + 1 11 | def initialize(*) 12 | super do |*args| 13 | self.class.state_machines.initialize_states(self, :static => false) 14 | changed_columns.clear 15 | yield(*args) if block_given? 16 | end 17 | end 18 | 19 | def set(*) 20 | self.class.state_machines.initialize_states(self, :static => :force, :dynamic => false) if values.empty? 21 | super 22 | end 23 | end_eval 24 | end 25 | 26 | def define_validation_hook 27 | define_helper :instance, <<-end_eval, __FILE__, __LINE__ + 1 28 | def valid?(*args) 29 | opts = args.first.is_a?(Hash) ? args.first : {} 30 | yielded = false 31 | result = self.class.state_machines.transitions(self, :save, :after => false).perform do 32 | yielded = true 33 | super 34 | end 35 | 36 | if yielded || result 37 | result 38 | else 39 | #{handle_validation_failure} 40 | end 41 | end 42 | end_eval 43 | end 44 | end 45 | 46 | version '2.8.x - 3.13.x' do 47 | def self.active? 48 | !defined?(::Sequel::MAJOR) || ::Sequel::MAJOR == 2 || ::Sequel::MAJOR == 3 && ::Sequel::MINOR <= 13 49 | end 50 | 51 | def handle_validation_failure 52 | 'raise_on_save_failure ? save_failure(:validation) : result' 53 | end 54 | 55 | def handle_save_failure 56 | 'save_failure(:save) if raise_on_save_failure' 57 | end 58 | end 59 | 60 | version '2.8.x - 2.11.x' do 61 | def self.active? 62 | !defined?(::Sequel::MAJOR) || ::Sequel::MAJOR == 2 && ::Sequel::MINOR <= 11 63 | end 64 | 65 | def load_plugins 66 | end 67 | 68 | def load_inflector 69 | end 70 | 71 | def model_from_dataset(dataset) 72 | dataset.model_classes[nil] 73 | end 74 | 75 | def define_state_accessor 76 | name = self.name 77 | owner_class.validates_each(attribute) do |record, attr, value| 78 | machine = record.class.state_machine(name) 79 | machine.invalidate(record, :state, :invalid) unless machine.states.match(record) 80 | end 81 | end 82 | end 83 | 84 | version '3.14.x - 3.23.x' do 85 | def self.active? 86 | defined?(::Sequel::MAJOR) && ::Sequel::MAJOR == 3 && ::Sequel::MINOR >= 14 && ::Sequel::MINOR <= 23 87 | end 88 | 89 | def handle_validation_failure 90 | 'raise_on_failure?(opts) ? raise_hook_failure(:validation) : result' 91 | end 92 | end 93 | end 94 | end 95 | end 96 | -------------------------------------------------------------------------------- /lib/state_machine/graph.rb: -------------------------------------------------------------------------------- 1 | begin 2 | require 'rubygems' 3 | gem 'ruby-graphviz', '>=0.9.17' 4 | require 'graphviz' 5 | rescue LoadError => ex 6 | $stderr.puts "Cannot draw the machine (#{ex.message}). `gem install ruby-graphviz` >= v0.9.17 and try again." 7 | raise 8 | end 9 | 10 | require 'state_machine/assertions' 11 | 12 | module StateMachine 13 | # Provides a set of higher-order features on top of the raw GraphViz graphs 14 | class Graph < GraphViz 15 | include Assertions 16 | 17 | # The name of the font to draw state names in 18 | attr_reader :font 19 | 20 | # The graph's full filename 21 | attr_reader :file_path 22 | 23 | # The image format to generate the graph in 24 | attr_reader :file_format 25 | 26 | # Creates a new graph with the given name. 27 | # 28 | # Configuration options: 29 | # * :path - The path to write the graph file to. Default is the 30 | # current directory ("."). 31 | # * :format - The image format to generate the graph in. 32 | # Default is "png'. 33 | # * :font - The name of the font to draw state names in. 34 | # Default is "Arial". 35 | # * :orientation - The direction of the graph ("portrait" or 36 | # "landscape"). Default is "portrait". 37 | def initialize(name, options = {}) 38 | options = {:path => '.', :format => 'png', :font => 'Arial', :orientation => 'portrait'}.merge(options) 39 | assert_valid_keys(options, :path, :format, :font, :orientation) 40 | 41 | @font = options[:font] 42 | @file_path = File.join(options[:path], "#{name}.#{options[:format]}") 43 | @file_format = options[:format] 44 | 45 | super('G', :rankdir => options[:orientation] == 'landscape' ? 'LR' : 'TB') 46 | end 47 | 48 | # Generates the actual image file based on the nodes / edges added to the 49 | # graph. The path to the file is based on the configuration options for 50 | # this graph. 51 | def output 52 | super(@file_format => @file_path) 53 | end 54 | 55 | # Adds a new node to the graph. The font for the node will be automatically 56 | # set based on the graph configuration. The generated node will be returned. 57 | # 58 | # For example, 59 | # 60 | # graph = StateMachine::Graph.new('test') 61 | # graph.add_nodes('parked', :label => 'Parked', :width => '1', :height => '1', :shape => 'ellipse') 62 | def add_nodes(*args) 63 | node = v0_api? ? add_node(*args) : super 64 | node.fontname = @font 65 | node 66 | end 67 | 68 | # Adds a new edge to the graph. The font for the edge will be automatically 69 | # set based on the graph configuration. The generated edge will be returned. 70 | # 71 | # For example, 72 | # 73 | # graph = StateMachine::Graph.new('test') 74 | # graph.add_edges('parked', 'idling', :label => 'ignite') 75 | def add_edges(*args) 76 | edge = v0_api? ? add_edge(*args) : super 77 | edge.fontname = @font 78 | edge 79 | end 80 | 81 | private 82 | # Determines whether the old v0 api is in use 83 | def v0_api? 84 | version[0] == '0' || version[0] == '1' && version[1] == '0' && version[2] <= '2' 85 | end 86 | 87 | # The ruby-graphviz version data 88 | def version 89 | Constants::RGV_VERSION.split('.') 90 | end 91 | end 92 | end 93 | -------------------------------------------------------------------------------- /lib/state_machine/machine_collection.rb: -------------------------------------------------------------------------------- 1 | require 'state_machine/assertions' 2 | 3 | module StateMachine 4 | # Represents a collection of state machines for a class 5 | class MachineCollection < Hash 6 | include Assertions 7 | 8 | # Initializes the state of each machine in the given object. This can allow 9 | # states to be initialized in two groups: static and dynamic. For example: 10 | # 11 | # machines.initialize_states(object) do 12 | # # After static state initialization, before dynamic state initialization 13 | # end 14 | # 15 | # If no block is provided, then all states will still be initialized. 16 | # 17 | # Valid configuration options: 18 | # * :static - Whether to initialize static states. If set to 19 | # :force, the state will be initialized regardless of its current value. 20 | # Default is :force. 21 | # * :dynamic - Whether to initialize dynamic states. If set to 22 | # :force, the state will be initialized regardless of its current value. 23 | # Default is true. 24 | # * :to - A hash to write the initialized state to instead of 25 | # writing to the object. Default is to write directly to the object. 26 | def initialize_states(object, options = {}) 27 | assert_valid_keys(options, :static, :dynamic, :to) 28 | options = {:static => true, :dynamic => true}.merge(options) 29 | 30 | each_value do |machine| 31 | machine.initialize_state(object, :force => options[:static] == :force, :to => options[:to]) unless machine.dynamic_initial_state? 32 | end if options[:static] 33 | 34 | result = yield if block_given? 35 | 36 | each_value do |machine| 37 | machine.initialize_state(object, :force => options[:dynamic] == :force, :to => options[:to]) if machine.dynamic_initial_state? 38 | end if options[:dynamic] 39 | 40 | result 41 | end 42 | 43 | # Runs one or more events in parallel on the given object. See 44 | # StateMachine::InstanceMethods#fire_events for more information. 45 | def fire_events(object, *events) 46 | run_action = [true, false].include?(events.last) ? events.pop : true 47 | 48 | # Generate the transitions to run for each event 49 | transitions = events.collect do |event_name| 50 | # Find the actual event being run 51 | event = nil 52 | detect {|name, machine| event = machine.events[event_name, :qualified_name]} 53 | 54 | raise(InvalidEvent.new(object, event_name)) unless event 55 | 56 | # Get the transition that will be performed for the event 57 | unless transition = event.transition_for(object) 58 | event.on_failure(object) 59 | end 60 | 61 | transition 62 | end.compact 63 | 64 | # Run the events in parallel only if valid transitions were found for 65 | # all of them 66 | if events.length == transitions.length 67 | TransitionCollection.new(transitions, :actions => run_action).perform 68 | else 69 | false 70 | end 71 | end 72 | 73 | # Builds the collection of transitions for all event attributes defined on 74 | # the given object. This will only include events whose machine actions 75 | # match the one specified. 76 | # 77 | # These should only be fired as a result of the action being run. 78 | def transitions(object, action, options = {}) 79 | transitions = map do |name, machine| 80 | machine.events.attribute_transition_for(object, true) if machine.action == action 81 | end 82 | 83 | AttributeTransitionCollection.new(transitions.compact, options) 84 | end 85 | end 86 | end 87 | -------------------------------------------------------------------------------- /lib/state_machine/eval_helpers.rb: -------------------------------------------------------------------------------- 1 | module StateMachine 2 | # Provides a set of helper methods for evaluating methods within the context 3 | # of an object. 4 | module EvalHelpers 5 | # Evaluates one of several different types of methods within the context 6 | # of the given object. Methods can be one of the following types: 7 | # * Symbol 8 | # * Method / Proc 9 | # * String 10 | # 11 | # == Examples 12 | # 13 | # Below are examples of the various ways that a method can be evaluated 14 | # on an object: 15 | # 16 | # class Person 17 | # def initialize(name) 18 | # @name = name 19 | # end 20 | # 21 | # def name 22 | # @name 23 | # end 24 | # end 25 | # 26 | # class PersonCallback 27 | # def self.run(person) 28 | # person.name 29 | # end 30 | # end 31 | # 32 | # person = Person.new('John Smith') 33 | # 34 | # evaluate_method(person, :name) # => "John Smith" 35 | # evaluate_method(person, PersonCallback.method(:run)) # => "John Smith" 36 | # evaluate_method(person, Proc.new {|person| person.name}) # => "John Smith" 37 | # evaluate_method(person, lambda {|person| person.name}) # => "John Smith" 38 | # evaluate_method(person, '@name') # => "John Smith" 39 | # 40 | # == Additional arguments 41 | # 42 | # Additional arguments can be passed to the methods being evaluated. If 43 | # the method defines additional arguments other than the object context, 44 | # then all arguments are required. 45 | # 46 | # For example, 47 | # 48 | # person = Person.new('John Smith') 49 | # 50 | # evaluate_method(person, lambda {|person| person.name}, 21) # => "John Smith" 51 | # evaluate_method(person, lambda {|person, age| "#{person.name} is #{age}"}, 21) # => "John Smith is 21" 52 | # evaluate_method(person, lambda {|person, age| "#{person.name} is #{age}"}, 21, 'male') # => ArgumentError: wrong number of arguments (3 for 2) 53 | def evaluate_method(object, method, *args, &block) 54 | case method 55 | when Symbol 56 | klass = (class << object; self; end) 57 | args = [] if (klass.method_defined?(method) || klass.private_method_defined?(method)) && object.method(method).arity == 0 58 | object.send(method, *args, &block) 59 | when Proc, Method 60 | args.unshift(object) 61 | arity = method.arity 62 | 63 | # Procs don't support blocks in < Ruby 1.9, so it's tacked on as an 64 | # argument for consistency across versions of Ruby 65 | if block_given? && Proc === method && arity != 0 66 | if [1, 2].include?(arity) 67 | # Force the block to be either the only argument or the 2nd one 68 | # after the object (may mean additional arguments get discarded) 69 | args = args[0, arity - 1] + [block] 70 | else 71 | # Tack the block to the end of the args 72 | args << block 73 | end 74 | else 75 | # These method types are only called with 0, 1, or n arguments 76 | args = args[0, arity] if [0, 1].include?(arity) 77 | end 78 | 79 | method.is_a?(Proc) ? method.call(*args) : method.call(*args, &block) 80 | when String 81 | eval(method, object.instance_eval {binding}, &block) 82 | else 83 | raise ArgumentError, 'Methods must be a symbol denoting the method to call, a block to be invoked, or a string to be evaluated' 84 | end 85 | end 86 | end 87 | end 88 | -------------------------------------------------------------------------------- /lib/state_machine/integrations/base.rb: -------------------------------------------------------------------------------- 1 | module StateMachine 2 | module Integrations 3 | # Provides a set of base helpers for managing individual integrations 4 | module Base 5 | module ClassMethods 6 | # The default options to use for state machines using this integration 7 | attr_reader :defaults 8 | 9 | # The name of the integration 10 | def integration_name 11 | @integration_name ||= begin 12 | name = self.name.split('::').last 13 | name.gsub!(/([A-Z]+)([A-Z][a-z])/,'\1_\2') 14 | name.gsub!(/([a-z\d])([A-Z])/,'\1_\2') 15 | name.downcase! 16 | name.to_sym 17 | end 18 | end 19 | 20 | # Whether this integration is available for the current library. This 21 | # is only true if the ORM that the integration is for is currently 22 | # defined. 23 | def available? 24 | matching_ancestors.any? && Object.const_defined?(matching_ancestors[0].split('::')[0]) 25 | end 26 | 27 | # The list of ancestor names that cause this integration to matched. 28 | def matching_ancestors 29 | [] 30 | end 31 | 32 | # Whether the integration should be used for the given class. 33 | def matches?(klass) 34 | matches_ancestors?(klass.ancestors.map {|ancestor| ancestor.name}) 35 | end 36 | 37 | # Whether the integration should be used for the given list of ancestors. 38 | def matches_ancestors?(ancestors) 39 | (ancestors & matching_ancestors).any? 40 | end 41 | 42 | # Tracks the various version overrides for an integration 43 | def versions 44 | @versions ||= [] 45 | end 46 | 47 | # Creates a new version override for an integration. When this 48 | # integration is activated, each version that is marked as active will 49 | # also extend the integration. 50 | # 51 | # == Example 52 | # 53 | # module StateMachine 54 | # module Integrations 55 | # module ORMLibrary 56 | # version '0.2.x - 0.3.x' do 57 | # def self.active? 58 | # ::ORMLibrary::VERSION >= '0.2.0' && ::ORMLibrary::VERSION < '0.4.0' 59 | # end 60 | # 61 | # def invalidate(object, attribute, message, values = []) 62 | # # Override here... 63 | # end 64 | # end 65 | # end 66 | # end 67 | # end 68 | # 69 | # In the above example, a version override is defined for the ORMLibrary 70 | # integration when the version is between 0.2.x and 0.3.x. 71 | def version(name, &block) 72 | versions << mod = Module.new(&block) 73 | mod 74 | end 75 | 76 | # The path to the locale file containing translations for this 77 | # integration. This file will only exist for integrations that actually 78 | # support i18n. 79 | def locale_path 80 | path = "#{File.dirname(__FILE__)}/#{integration_name}/locale.rb" 81 | path if File.exists?(path) 82 | end 83 | 84 | # Extends the given object with any version overrides that are currently 85 | # active 86 | def extended(base) 87 | versions.each do |version| 88 | base.extend(version) if version.active? 89 | end 90 | end 91 | end 92 | 93 | extend ClassMethods 94 | 95 | def self.included(base) #:nodoc: 96 | base.class_eval { extend ClassMethods } 97 | end 98 | end 99 | end 100 | end 101 | -------------------------------------------------------------------------------- /test/unit/invalid_transition_test.rb: -------------------------------------------------------------------------------- 1 | require File.expand_path(File.dirname(__FILE__) + '/../test_helper') 2 | 3 | class InvalidTransitionTest < Test::Unit::TestCase 4 | def setup 5 | @klass = Class.new 6 | @machine = StateMachine::Machine.new(@klass) 7 | @state = @machine.state :parked 8 | @machine.event :ignite 9 | 10 | @object = @klass.new 11 | @object.state = 'parked' 12 | 13 | @invalid_transition = StateMachine::InvalidTransition.new(@object, @machine, :ignite) 14 | end 15 | 16 | def test_should_have_an_object 17 | assert_equal @object, @invalid_transition.object 18 | end 19 | 20 | def test_should_have_a_machine 21 | assert_equal @machine, @invalid_transition.machine 22 | end 23 | 24 | def test_should_have_an_event 25 | assert_equal :ignite, @invalid_transition.event 26 | end 27 | 28 | def test_should_have_a_qualified_event 29 | assert_equal :ignite, @invalid_transition.qualified_event 30 | end 31 | 32 | def test_should_have_a_from_value 33 | assert_equal 'parked', @invalid_transition.from 34 | end 35 | 36 | def test_should_have_a_from_name 37 | assert_equal :parked, @invalid_transition.from_name 38 | end 39 | 40 | def test_should_have_a_qualified_from_name 41 | assert_equal :parked, @invalid_transition.qualified_from_name 42 | end 43 | 44 | def test_should_generate_a_message 45 | assert_equal 'Cannot transition state via :ignite from :parked', @invalid_transition.message 46 | end 47 | end 48 | 49 | class InvalidTransitionWithNamespaceTest < Test::Unit::TestCase 50 | def setup 51 | @klass = Class.new 52 | @machine = StateMachine::Machine.new(@klass, :namespace => 'alarm') 53 | @state = @machine.state :active 54 | @machine.event :disable 55 | 56 | @object = @klass.new 57 | @object.state = 'active' 58 | 59 | @invalid_transition = StateMachine::InvalidTransition.new(@object, @machine, :disable) 60 | end 61 | 62 | def test_should_have_an_event 63 | assert_equal :disable, @invalid_transition.event 64 | end 65 | 66 | def test_should_have_a_qualified_event 67 | assert_equal :disable_alarm, @invalid_transition.qualified_event 68 | end 69 | 70 | def test_should_have_a_from_name 71 | assert_equal :active, @invalid_transition.from_name 72 | end 73 | 74 | def test_should_have_a_qualified_from_name 75 | assert_equal :alarm_active, @invalid_transition.qualified_from_name 76 | end 77 | end 78 | 79 | class InvalidTransitionWithIntegrationTest < Test::Unit::TestCase 80 | def setup 81 | StateMachine::Integrations.const_set('Custom', Module.new do 82 | include StateMachine::Integrations::Base 83 | 84 | def errors_for(object) 85 | object.errors 86 | end 87 | end) 88 | 89 | @klass = Class.new do 90 | attr_accessor :errors 91 | end 92 | @machine = StateMachine::Machine.new(@klass, :integration => :custom) 93 | @machine.state :parked 94 | @machine.event :ignite 95 | 96 | @object = @klass.new 97 | @object.state = 'parked' 98 | end 99 | 100 | def test_should_generate_a_message_without_reasons_if_empty 101 | @object.errors = '' 102 | invalid_transition = StateMachine::InvalidTransition.new(@object, @machine, :ignite) 103 | assert_equal 'Cannot transition state via :ignite from :parked', invalid_transition.message 104 | end 105 | 106 | def test_should_generate_a_message_with_error_reasons_if_errors_found 107 | @object.errors = 'Id is invalid, Name is invalid' 108 | invalid_transition = StateMachine::InvalidTransition.new(@object, @machine, :ignite) 109 | assert_equal 'Cannot transition state via :ignite from :parked (Reason(s): Id is invalid, Name is invalid)', invalid_transition.message 110 | end 111 | 112 | def teardown 113 | StateMachine::Integrations.send(:remove_const, 'Custom') 114 | end 115 | end 116 | --------------------------------------------------------------------------------