From 00819ce27b2d7fdce1becc10a44c2c20fe6384ed Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Mon, 16 May 2011 15:42:47 +0800 Subject: [PATCH 1/5] migrating to aasm - code part --- app/controllers/todos_controller.rb | 3 - app/models/project.rb | 22 +- app/models/recurring_todo.rb | 14 +- app/models/todo.rb | 47 +- app/views/projects/_project_listing.rhtml | 2 +- app/views/projects/project_mobile.rhtml | 2 +- app/views/projects/update_status.js.rjs | 8 +- test/functional/projects_controller_test.rb | 4 +- test/unit/project_test.rb | 22 +- test/unit/recurring_todo_test.rb | 6 +- test/unit/todo_test.rb | 22 +- vendor/gems/aasm-2.2.0/.document | 5 + vendor/gems/aasm-2.2.0/.gitignore | 7 + vendor/gems/aasm-2.2.0/README.rdoc | 137 ++++++ vendor/gems/aasm-2.2.0/Rakefile | 108 ++++ vendor/gems/aasm-2.2.0/VERSION | 1 + vendor/gems/aasm-2.2.0/aasm.gemspec | 94 ++++ vendor/gems/aasm-2.2.0/lib/aasm.rb | 9 + vendor/gems/aasm-2.2.0/lib/aasm/aasm.rb | 196 ++++++++ vendor/gems/aasm-2.2.0/lib/aasm/event.rb | 109 +++++ .../gems/aasm-2.2.0/lib/aasm/persistence.rb | 14 + .../persistence/active_record_persistence.rb | 259 ++++++++++ vendor/gems/aasm-2.2.0/lib/aasm/state.rb | 53 ++ .../gems/aasm-2.2.0/lib/aasm/state_machine.rb | 32 ++ .../aasm-2.2.0/lib/aasm/state_transition.rb | 46 ++ .../aasm-2.2.0/lib/aasm/supporting_classes.rb | 6 + .../spec/functional/conversation.rb | 49 ++ .../spec/functional/conversation_spec.rb | 8 + vendor/gems/aasm-2.2.0/spec/spec_helper.rb | 11 + vendor/gems/aasm-2.2.0/spec/unit/aasm_spec.rb | 462 ++++++++++++++++++ .../unit/active_record_persistence_spec.rb | 255 ++++++++++ .../spec/unit/before_after_callbacks_spec.rb | 79 +++ .../gems/aasm-2.2.0/spec/unit/event_spec.rb | 126 +++++ .../gems/aasm-2.2.0/spec/unit/state_spec.rb | 85 ++++ .../spec/unit/state_transition_spec.rb | 84 ++++ .../test/functional/auth_machine_test.rb | 120 +++++ vendor/gems/aasm-2.2.0/test/test_helper.rb | 33 ++ .../gems/aasm-2.2.0/test/unit/event_test.rb | 54 ++ .../gems/aasm-2.2.0/test/unit/state_test.rb | 69 +++ .../test/unit/state_transition_test.rb | 75 +++ .../plugins/acts_as_state_machine/CHANGELOG | 13 - .../plugins/acts_as_state_machine/MIT-LICENSE | 20 - vendor/plugins/acts_as_state_machine/README | 33 -- vendor/plugins/acts_as_state_machine/Rakefile | 28 -- vendor/plugins/acts_as_state_machine/TODO | 11 - vendor/plugins/acts_as_state_machine/init.rb | 5 - .../lib/acts_as_state_machine.rb | 276 ----------- .../test/acts_as_state_machine_test.rb | 224 --------- .../acts_as_state_machine/test/database.yml | 18 - .../test/fixtures/conversation.rb | 67 --- .../test/fixtures/conversations.yml | 11 - .../test/fixtures/person.rb | 2 - .../acts_as_state_machine/test/schema.rb | 11 - .../acts_as_state_machine/test/test_helper.rb | 38 -- 54 files changed, 2656 insertions(+), 839 deletions(-) create mode 100644 vendor/gems/aasm-2.2.0/.document create mode 100644 vendor/gems/aasm-2.2.0/.gitignore create mode 100644 vendor/gems/aasm-2.2.0/README.rdoc create mode 100644 vendor/gems/aasm-2.2.0/Rakefile create mode 100644 vendor/gems/aasm-2.2.0/VERSION create mode 100644 vendor/gems/aasm-2.2.0/aasm.gemspec create mode 100644 vendor/gems/aasm-2.2.0/lib/aasm.rb create mode 100644 vendor/gems/aasm-2.2.0/lib/aasm/aasm.rb create mode 100644 vendor/gems/aasm-2.2.0/lib/aasm/event.rb create mode 100644 vendor/gems/aasm-2.2.0/lib/aasm/persistence.rb create mode 100644 vendor/gems/aasm-2.2.0/lib/aasm/persistence/active_record_persistence.rb create mode 100644 vendor/gems/aasm-2.2.0/lib/aasm/state.rb create mode 100644 vendor/gems/aasm-2.2.0/lib/aasm/state_machine.rb create mode 100644 vendor/gems/aasm-2.2.0/lib/aasm/state_transition.rb create mode 100644 vendor/gems/aasm-2.2.0/lib/aasm/supporting_classes.rb create mode 100644 vendor/gems/aasm-2.2.0/spec/functional/conversation.rb create mode 100644 vendor/gems/aasm-2.2.0/spec/functional/conversation_spec.rb create mode 100644 vendor/gems/aasm-2.2.0/spec/spec_helper.rb create mode 100644 vendor/gems/aasm-2.2.0/spec/unit/aasm_spec.rb create mode 100644 vendor/gems/aasm-2.2.0/spec/unit/active_record_persistence_spec.rb create mode 100644 vendor/gems/aasm-2.2.0/spec/unit/before_after_callbacks_spec.rb create mode 100644 vendor/gems/aasm-2.2.0/spec/unit/event_spec.rb create mode 100644 vendor/gems/aasm-2.2.0/spec/unit/state_spec.rb create mode 100644 vendor/gems/aasm-2.2.0/spec/unit/state_transition_spec.rb create mode 100644 vendor/gems/aasm-2.2.0/test/functional/auth_machine_test.rb create mode 100644 vendor/gems/aasm-2.2.0/test/test_helper.rb create mode 100644 vendor/gems/aasm-2.2.0/test/unit/event_test.rb create mode 100644 vendor/gems/aasm-2.2.0/test/unit/state_test.rb create mode 100644 vendor/gems/aasm-2.2.0/test/unit/state_transition_test.rb delete mode 100644 vendor/plugins/acts_as_state_machine/CHANGELOG delete mode 100644 vendor/plugins/acts_as_state_machine/MIT-LICENSE delete mode 100644 vendor/plugins/acts_as_state_machine/README delete mode 100644 vendor/plugins/acts_as_state_machine/Rakefile delete mode 100644 vendor/plugins/acts_as_state_machine/TODO delete mode 100644 vendor/plugins/acts_as_state_machine/init.rb delete mode 100644 vendor/plugins/acts_as_state_machine/lib/acts_as_state_machine.rb delete mode 100644 vendor/plugins/acts_as_state_machine/test/acts_as_state_machine_test.rb delete mode 100644 vendor/plugins/acts_as_state_machine/test/database.yml delete mode 100644 vendor/plugins/acts_as_state_machine/test/fixtures/conversation.rb delete mode 100644 vendor/plugins/acts_as_state_machine/test/fixtures/conversations.yml delete mode 100644 vendor/plugins/acts_as_state_machine/test/fixtures/person.rb delete mode 100644 vendor/plugins/acts_as_state_machine/test/schema.rb delete mode 100644 vendor/plugins/acts_as_state_machine/test/test_helper.rb diff --git a/app/controllers/todos_controller.rb b/app/controllers/todos_controller.rb index 843e43de..7bb6d0ed 100644 --- a/app/controllers/todos_controller.rb +++ b/app/controllers/todos_controller.rb @@ -89,9 +89,6 @@ class TodosController < ApplicationController specified_state = @todo.state @saved = @todo.save - # Fix for #977 because AASM overrides @state on creation - @todo.update_attribute('state', specified_state) unless specified_state == "immediate" || specified_state.nil? || !@saved - @saved = @todo.save @todo.update_state_from_project if @saved unless (@saved == false) || tag_list.blank? diff --git a/app/models/project.rb b/app/models/project.rb index 1eb3e04c..9c29c01c 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -40,23 +40,27 @@ class Project < ActiveRecord::Base validates_does_not_contain :name, :string => ',' acts_as_list :scope => 'user_id = #{user_id} AND state = \'#{state}\'' - acts_as_state_machine :initial => :active, :column => 'state' + + include AASM + aasm_column :state + aasm_initial_state :active + extend NamePartFinder #include Tracks::TodoList - state :active - state :hidden, :enter => :hide_todos, :exit => :unhide_todos - state :completed, :enter => Proc.new { |p| p.completed_at = Time.zone.now }, :exit => Proc.new { |p| p.completed_at = nil } + aasm_state :active + aasm_state :hidden, :enter => :hide_todos, :exit => :unhide_todos + aasm_state :completed, :enter => Proc.new { |p| p.completed_at = Time.zone.now }, :exit => Proc.new { |p| p.completed_at = nil } - event :activate do - transitions :to => :active, :from => [:hidden, :completed] + aasm_event :activate do + transitions :to => :active, :from => [:active, :hidden, :completed] end - event :hide do + aasm_event :hide do transitions :to => :hidden, :from => [:active, :completed] end - event :complete do + aasm_event :complete do transitions :to => :completed, :from => [:active, :hidden] end @@ -106,7 +110,7 @@ class Project < ActiveRecord::Base # as a result of acts_as_state_machine calling state=() to update the attribute def transition_to(candidate_state) case candidate_state.to_sym - when current_state + when aasm_current_state return when :hidden hide! diff --git a/app/models/recurring_todo.rb b/app/models/recurring_todo.rb index 48c9ede3..04066ffd 100644 --- a/app/models/recurring_todo.rb +++ b/app/models/recurring_todo.rb @@ -10,20 +10,22 @@ class RecurringTodo < ActiveRecord::Base named_scope :completed, :conditions => { :state => 'completed'} attr_protected :user - - acts_as_state_machine :initial => :active, :column => 'state' - state :active, :enter => Proc.new { |t| + include AASM + aasm_column :state + aasm_initial_state :active + + aasm_state :active, :enter => Proc.new { |t| t[:show_from], t.completed_at = nil, nil t.occurences_count = 0 } - state :completed, :enter => Proc.new { |t| t.completed_at = Time.zone.now }, :exit => Proc.new { |t| t.completed_at = nil } + aasm_state :completed, :enter => Proc.new { |t| t.completed_at = Time.zone.now }, :exit => Proc.new { |t| t.completed_at = nil } - event :complete do + aasm_event :complete do transitions :to => :completed, :from => [:active] end - event :activate do + aasm_event :activate do transitions :to => :active, :from => [:completed] end diff --git a/app/models/todo.rb b/app/models/todo.rb index 6ddbd5b0..601f666f 100644 --- a/app/models/todo.rb +++ b/app/models/todo.rb @@ -45,40 +45,42 @@ class Todo < ActiveRecord::Base RE_PARTS = /'(#{RE_TODO})'\s<'(#{RE_CONTEXT})';\s'(#{RE_PROJECT})'>/ # results in array RE_SPEC = /'#{RE_TODO}'\s<'#{RE_CONTEXT}';\s'#{RE_PROJECT}'>/ # results in string - acts_as_state_machine :initial => :active, :column => 'state' + include AASM + aasm_column :state + aasm_initial_state Proc.new { |todo| (todo.show_from && (todo.show_from > todo.user.date)) ? :deferred : :active} # when entering active state, also remove completed_at date. Looks like :exit # of state completed is not run, see #679 - state :active, :enter => Proc.new { |t| t[:show_from], t.completed_at = nil, nil } - state :project_hidden - state :completed, :enter => Proc.new { |t| t.completed_at = Time.zone.now }, :exit => Proc.new { |t| t.completed_at = nil } - state :deferred - state :pending + aasm_state :active, :enter => Proc.new { |t| t[:show_from], t.completed_at = nil, nil } + aasm_state :project_hidden, :enter => Proc.new { |t| t.completed_at = Time.zone.now }, :exit => Proc.new { |t| t.completed_at = nil } + aasm_state :completed + aasm_state :deferred + aasm_state :pending - event :defer do + aasm_event :defer do transitions :to => :deferred, :from => [:active] end - event :complete do + aasm_event :complete do transitions :to => :completed, :from => [:active, :project_hidden, :deferred] end - event :activate do + aasm_event :activate do transitions :to => :active, :from => [:project_hidden, :completed, :deferred] transitions :to => :active, :from => [:pending], :guard => :no_uncompleted_predecessors_or_deferral? transitions :to => :deferred, :from => [:pending], :guard => :no_uncompleted_predecessors? end - event :hide do + aasm_event :hide do transitions :to => :project_hidden, :from => [:active, :deferred] end - event :unhide do + aasm_event :unhide do transitions :to => :deferred, :from => [:project_hidden], :guard => Proc.new{|t| !t.show_from.blank? } transitions :to => :active, :from => [:project_hidden] end - event :block do + aasm_event :block do transitions :to => :pending, :from => [:active, :deferred] end @@ -216,6 +218,7 @@ class Todo < ActiveRecord::Base date = user.at_midnight(date) if (date.is_a? Date) activate! if deferred? && date.blank? defer! if active? && !date.blank? && date > user.date + self[:show_from] = date end @@ -224,27 +227,7 @@ class Todo < ActiveRecord::Base def project original_project.nil? ? Project.null_object : original_project end - - alias_method :original_set_initial_state, :set_initial_state - def set_initial_state - if show_from && (show_from > user.date) - write_attribute self.class.state_column, 'deferred' - else - original_set_initial_state - end - end - - alias_method :original_run_initial_state_actions, :run_initial_state_actions - - def run_initial_state_actions - # only run the initial state actions if the standard initial state hasn't - # been changed - if self.class.initial_state.to_sym == current_state - original_run_initial_state_actions - end - end - def self.feed_options(user) { :title => 'Tracks Actions', diff --git a/app/views/projects/_project_listing.rhtml b/app/views/projects/_project_listing.rhtml index 7f84add5..b07bf0c3 100644 --- a/app/views/projects/_project_listing.rhtml +++ b/app/views/projects/_project_listing.rhtml @@ -17,7 +17,7 @@ suppress_edit_button ||= false
- <%= project.current_state.to_s.upcase %> + <%= project.aasm_current_state.to_s.upcase %> <%= link_to_delete_project(project, image_tag( "blank.png", :title => t('projects.delete_project_title'), :class=>"delete_item")) %> <%= suppress_edit_button ? "" : link_to_edit_project(project, image_tag( "blank.png", :title => t('projects.edit_project_title'), :class=>"edit_item")) %>
diff --git a/app/views/projects/project_mobile.rhtml b/app/views/projects/project_mobile.rhtml index 3b35c8e2..d79cad08 100644 --- a/app/views/projects/project_mobile.rhtml +++ b/app/views/projects/project_mobile.rhtml @@ -24,4 +24,4 @@ <% else -%><%= render :partial => "notes/mobile_notes_summary", :collection => @project.notes %> <% end -%>

<%= t('projects.settings') %>

-<%= t('projects.state', :state => project.current_state.to_s) %>. <%= @project_default_context %> \ No newline at end of file +<%= t('projects.state', :state => project.aasm_current_state.to_s) %>. <%= @project_default_context %> \ No newline at end of file diff --git a/app/views/projects/update_status.js.rjs b/app/views/projects/update_status.js.rjs index f2570dd4..c15a4acb 100644 --- a/app/views/projects/update_status.js.rjs +++ b/app/views/projects/update_status.js.rjs @@ -1,11 +1,11 @@ # TODO: is this dead code? page.select('#project_status .active span').each do |element| - element.className = @project.current_state == :active ? 'active_state' : 'inactive_state' + element.className = @project.aasm_current_state == :active ? 'active_state' : 'inactive_state' end page.select('#project_status .hidden span').each do |element| - element.className = @project.current_state == :hidden ? 'active_state' : 'inactive_state' + element.className = @project.aasm_current_state == :hidden ? 'active_state' : 'inactive_state' end page.select('#project_status .completed span').each do |element| - element.className = @project.current_state == :completed ? 'active_state' : 'inactive_state' + element.className = @project.aasm_current_state == :completed ? 'active_state' : 'inactive_state' end -page.notify :notice, "Set project status to #{@project.current_state}", 5.0 +page.notify :notice, "Set project status to #{@project.aasm_current_state}", 5.0 diff --git a/test/functional/projects_controller_test.rb b/test/functional/projects_controller_test.rb index 297ae2e2..ba419ecf 100644 --- a/test/functional/projects_controller_test.rb +++ b/test/functional/projects_controller_test.rb @@ -58,7 +58,7 @@ class ProjectsControllerTest < TodoContainerControllerTestBase login_as(:admin_user) xhr :post, :update, :id => 1, "project"=>{"name"=>p.name, "description"=>p.description, "state"=>"hidden"} todos.each do |t| - assert_equal :project_hidden, t.reload().current_state + assert_equal :project_hidden, t.reload().aasm_current_state end assert p.reload().hidden? end @@ -70,7 +70,7 @@ class ProjectsControllerTest < TodoContainerControllerTestBase xhr :post, :update, :id => 1, "project"=>{"name"=>p.name, "description"=>p.description, "state"=>"hidden"} xhr :post, :update, :id => 1, "project"=>{"name"=>p.name, "description"=>p.description, "state"=>"active"} todos.each do |t| - assert_equal :active, t.reload().current_state + assert_equal :active, t.reload().aasm_current_state end assert p.reload().active? end diff --git a/test/unit/project_test.rb b/test/unit/project_test.rb index 180f0876..a9a95679 100644 --- a/test/unit/project_test.rb +++ b/test/unit/project_test.rb @@ -53,26 +53,26 @@ class ProjectTest < ActiveSupport::TestCase end def test_project_initial_state_is_active - assert_equal :active, @timemachine.current_state + assert_equal :active, @timemachine.aasm_current_state assert @timemachine.active? end def test_hide_project @timemachine.hide! - assert_equal :hidden, @timemachine.current_state + assert_equal :hidden, @timemachine.aasm_current_state assert @timemachine.hidden? end def test_activate_project @timemachine.activate! - assert_equal :active, @timemachine.current_state + assert_equal :active, @timemachine.aasm_current_state assert @timemachine.active? end def test_complete_project assert_nil @timemachine.completed_at @timemachine.complete! - assert_equal :completed, @timemachine.current_state + assert_equal :completed, @timemachine.aasm_current_state assert @timemachine.completed? assert_not_nil @timemachine.completed_at, "completed_at not expected to be nil" assert_in_delta Time.now, @timemachine.completed_at, 1 @@ -141,25 +141,27 @@ class ProjectTest < ActiveSupport::TestCase end def test_transition_to_another_state - assert_equal :active, @timemachine.current_state + assert_equal :active, @timemachine.aasm_current_state @timemachine.transition_to(:hidden) - assert_equal :hidden, @timemachine.current_state + assert_equal :hidden, @timemachine.aasm_current_state @timemachine.transition_to(:completed) - assert_equal :completed, @timemachine.current_state + assert_equal :completed, @timemachine.aasm_current_state @timemachine.transition_to(:active) - assert_equal :active, @timemachine.current_state + assert_equal :active, @timemachine.aasm_current_state end def test_transition_to_same_state - assert_equal :active, @timemachine.current_state + assert_equal :active, @timemachine.aasm_current_state @timemachine.transition_to(:active) - assert_equal :active, @timemachine.current_state + assert_equal :active, @timemachine.aasm_current_state end def test_deferred_todo_count assert_equal 1, @timemachine.deferred_todos.count assert_equal 0, @moremoney.deferred_todos.count @moremoney.todos[0].show_from = next_week + @moremoney.todos[0].save + assert_equal :deferred, @moremoney.todos[0].aasm_current_state assert_equal 1, @moremoney.deferred_todos.count end diff --git a/test/unit/recurring_todo_test.rb b/test/unit/recurring_todo_test.rb index 980525be..60b96915 100644 --- a/test/unit/recurring_todo_test.rb +++ b/test/unit/recurring_todo_test.rb @@ -276,11 +276,11 @@ class RecurringTodoTest < ActiveSupport::TestCase def test_toggle_completion t = @yearly - assert_equal :active, t.current_state + assert_equal :active, t.aasm_current_state t.toggle_completion! - assert_equal :completed, t.current_state + assert_equal :completed, t.aasm_current_state t.toggle_completion! - assert_equal :active, t.current_state + assert_equal :active, t.aasm_current_state end def test_starred diff --git a/test/unit/todo_test.rb b/test/unit/todo_test.rb index 45b77af7..00460139 100644 --- a/test/unit/todo_test.rb +++ b/test/unit/todo_test.rb @@ -77,10 +77,10 @@ class TodoTest < ActiveSupport::TestCase def test_defer_an_existing_todo @not_completed2 - assert_equal :active, @not_completed2.current_state + assert_equal :active, @not_completed2.aasm_current_state @not_completed2.show_from = next_week assert @not_completed2.save, "should have saved successfully" + @not_completed2.errors.to_xml - assert_equal :deferred, @not_completed2.current_state + assert_equal :deferred, @not_completed2.aasm_current_state end def test_create_a_new_deferred_todo @@ -88,16 +88,16 @@ class TodoTest < ActiveSupport::TestCase todo = user.todos.build todo.show_from = next_week todo.context_id = 1 - todo.description = 'foo' + todo.description = 'foo' assert todo.save, "should have saved successfully" + todo.errors.to_xml - assert_equal :deferred, todo.current_state + assert_equal :deferred, todo.aasm_current_state end def test_create_a_new_deferred_todo_by_passing_attributes user = users(:other_user) - todo = user.todos.build(:show_from => next_week, :context_id => 1, :description => 'foo') + todo = user.todos.build(:show_from => next_week, :context_id => 1, :description => 'foo') assert todo.save, "should have saved successfully" + todo.errors.to_xml - assert_equal :deferred, todo.current_state + assert_equal :deferred, todo.aasm_current_state end def test_feed_options @@ -108,11 +108,11 @@ class TodoTest < ActiveSupport::TestCase def test_toggle_completion t = @not_completed1 - assert_equal :active, t.current_state + assert_equal :active, t.aasm_current_state t.toggle_completion! - assert_equal :completed, t.current_state + assert_equal :completed, t.aasm_current_state t.toggle_completion! - assert_equal :active, t.current_state + assert_equal :active, t.aasm_current_state end def test_activate_also_saves @@ -154,7 +154,7 @@ class TodoTest < ActiveSupport::TestCase t.context_id = 1 t.save! t.reload - assert_equal :active, t.current_state + assert_equal :active, t.aasm_current_state end def test_initial_state_is_deferred_when_show_from_in_future @@ -165,7 +165,7 @@ class TodoTest < ActiveSupport::TestCase t.show_from = 1.week.from_now.to_date t.save! t.reload - assert_equal :deferred, t.current_state + assert_equal :deferred, t.aasm_current_state end def test_todo_is_not_starred diff --git a/vendor/gems/aasm-2.2.0/.document b/vendor/gems/aasm-2.2.0/.document new file mode 100644 index 00000000..ecf36731 --- /dev/null +++ b/vendor/gems/aasm-2.2.0/.document @@ -0,0 +1,5 @@ +README.rdoc +lib/**/*.rb +bin/* +features/**/*.feature +LICENSE diff --git a/vendor/gems/aasm-2.2.0/.gitignore b/vendor/gems/aasm-2.2.0/.gitignore new file mode 100644 index 00000000..4e80aa16 --- /dev/null +++ b/vendor/gems/aasm-2.2.0/.gitignore @@ -0,0 +1,7 @@ +*.sw? +*~ +.DS_Store +.idea +coverage +pkg +rdoc diff --git a/vendor/gems/aasm-2.2.0/README.rdoc b/vendor/gems/aasm-2.2.0/README.rdoc new file mode 100644 index 00000000..9504eaee --- /dev/null +++ b/vendor/gems/aasm-2.2.0/README.rdoc @@ -0,0 +1,137 @@ += Alternatives + +If you are looking for an alternative to AASM, I would highly suggest transitions: http://github.com/qoobaa/transitions + += AASM - Ruby state machines + +This package contains AASM, a library for adding finite state machines to Ruby classes. + +AASM started as the acts_as_state_machine plugin but has evolved into a more generic library that no longer targets only ActiveRecord models. + +AASM has the following features: + +* States +* Machines +* Events +* Transitions + +== New Callbacks + +The callback chain & order on a successful event looks like: + + oldstate:exit* + event:before + __find transition, if possible__ + transition:on_transition* + oldstate:before_exit + newstate:before_enter + newstate:enter* + __update state__ + event:success* + oldstate:after_exit + newstate:after_enter + event:after + obj:aasm_event_fired* + + (*) marks old callbacks + + +== Download + +The latest AASM can currently be pulled from the git repository on github. + +* http://github.com/rubyist/aasm/tree/master + + +== Installation + +=== From gemcutter + + % sudo gem install gemcutter + % sudo gem tumble + % sudo gem install aasm + +=== From GitHub hosted gems (only older releases are available) + + % sudo gem sources -a http://gems.github.com # (you only need to do this once) + % sudo gem install rubyist-aasm + +=== Building your own gems + + % rake gemspec + % rake build + % sudo gem install pkg/aasm-2.1.gem + + +== Simple Example + +Here's a quick example highlighting some of the features. + + class Conversation + include AASM + + aasm_column :current_state # defaults to aasm_state + + aasm_initial_state :unread + + aasm_state :unread + aasm_state :read + aasm_state :closed + + + aasm_event :view do + transitions :to => :read, :from => [:unread] + end + + aasm_event :close do + transitions :to => :closed, :from => [:read, :unread] + end + end + +== A Slightly More Complex Example + +This example uses a few of the more complex features available. + + class Relationship + include AASM + + aasm_column :status + + aasm_initial_state Proc.new { |relationship| relationship.strictly_for_fun? ? :intimate : :dating } + + aasm_state :dating, :enter => :make_happy, :exit => :make_depressed + aasm_state :intimate, :enter => :make_very_happy, :exit => :never_speak_again + aasm_state :married, :enter => :give_up_intimacy, :exit => :buy_exotic_car_and_wear_a_combover + + aasm_event :get_intimate do + transitions :to => :intimate, :from => [:dating], :guard => :drunk? + end + + aasm_event :get_married do + transitions :to => :married, :from => [:dating, :intimate], :guard => :willing_to_give_up_manhood? + end + + def strictly_for_fun?; end + def drunk?; end + def willing_to_give_up_manhood?; end + def make_happy; end + def make_depressed; end + def make_very_happy; end + def never_speak_again; end + def give_up_intimacy; end + def buy_exotic_car_and_wear_a_combover; end + end + += Other Stuff + +Author:: Scott Barron +License:: Original code Copyright 2006, 2007, 2008 by Scott Barron. + Released under an MIT-style license. See the LICENSE file + included in the distribution. + +== Warranty + +This software is provided "as is" and without any express or +implied warranties, including, without limitation, the implied +warranties of merchantibility and fitness for a particular +purpose. diff --git a/vendor/gems/aasm-2.2.0/Rakefile b/vendor/gems/aasm-2.2.0/Rakefile new file mode 100644 index 00000000..e6f8d173 --- /dev/null +++ b/vendor/gems/aasm-2.2.0/Rakefile @@ -0,0 +1,108 @@ +require 'rubygems' +require 'rake' + +begin + require 'jeweler' + Jeweler::Tasks.new do |gem| + gem.name = "aasm" + gem.summary = %Q{State machine mixin for Ruby objects} + gem.description = %Q{AASM is a continuation of the acts as state machine rails plugin, built for plain Ruby objects.} + gem.homepage = "http://rubyist.github.com/aasm/" + gem.authors = ["Scott Barron", "Scott Petersen", "Travis Tilley"] + gem.email = "scott@elitists.net, ttilley@gmail.com" + gem.add_development_dependency "rspec" + gem.add_development_dependency "shoulda" + gem.add_development_dependency 'sdoc' + # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings + end + Jeweler::GemcutterTasks.new +rescue LoadError + puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler" +end + +require 'spec/rake/spectask' +require 'rake/testtask' + +Rake::TestTask.new(:test) do |test| + test.libs << 'lib' << 'test' + test.pattern = 'test/**/*_test.rb' + test.verbose = true +end + +begin + require 'rcov/rcovtask' + Rcov::RcovTask.new(:rcov_shoulda) do |test| + test.libs << 'test' + test.pattern = 'test/**/*_test.rb' + test.verbose = true + end +rescue LoadError + task :rcov do + abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov" + end +end + +Spec::Rake::SpecTask.new(:spec) do |spec| + spec.libs << 'lib' << 'spec' + spec.spec_files = FileList['spec/**/*_spec.rb'] + spec.spec_opts = ['-cfs'] +end + +Spec::Rake::SpecTask.new(:rcov_rspec) do |spec| + spec.libs << 'lib' << 'spec' + spec.pattern = 'spec/**/*_spec.rb' + spec.rcov = true +end + +task :test => :check_dependencies +task :spec => :check_dependencies + +begin + require 'reek/rake_task' + Reek::RakeTask.new do |t| + t.fail_on_error = true + t.verbose = false + t.source_files = 'lib/**/*.rb' + end +rescue LoadError + task :reek do + abort "Reek is not available. In order to run reek, you must: sudo gem install reek" + end +end + +begin + require 'roodi' + require 'roodi_task' + RoodiTask.new do |t| + t.verbose = false + end +rescue LoadError + task :roodi do + abort "Roodi is not available. In order to run roodi, you must: sudo gem install roodi" + end +end + +task :default => :test + +begin + require 'rake/rdoctask' + require 'sdoc' + Rake::RDocTask.new do |rdoc| + if File.exist?('VERSION') + version = File.read('VERSION') + else + version = "" + end + + rdoc.rdoc_dir = 'rdoc' + rdoc.title = "aasm #{version}" + rdoc.rdoc_files.include('README*') + rdoc.rdoc_files.include('lib/**/*.rb') + + rdoc.options << '--fmt' << 'shtml' + rdoc.template = 'direct' + end +rescue LoadError + puts "aasm makes use of the sdoc gem. Install it with: sudo gem install sdoc" +end + diff --git a/vendor/gems/aasm-2.2.0/VERSION b/vendor/gems/aasm-2.2.0/VERSION new file mode 100644 index 00000000..ccbccc3d --- /dev/null +++ b/vendor/gems/aasm-2.2.0/VERSION @@ -0,0 +1 @@ +2.2.0 diff --git a/vendor/gems/aasm-2.2.0/aasm.gemspec b/vendor/gems/aasm-2.2.0/aasm.gemspec new file mode 100644 index 00000000..10947796 --- /dev/null +++ b/vendor/gems/aasm-2.2.0/aasm.gemspec @@ -0,0 +1,94 @@ +# Generated by jeweler +# DO NOT EDIT THIS FILE DIRECTLY +# Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command +# -*- encoding: utf-8 -*- + +Gem::Specification.new do |s| + s.name = %q{aasm} + s.version = "2.2.0" + + s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version= + s.authors = ["Scott Barron", "Scott Petersen", "Travis Tilley"] + s.date = %q{2010-09-13} + s.description = %q{AASM is a continuation of the acts as state machine rails plugin, built for plain Ruby objects.} + s.email = %q{scott@elitists.net, ttilley@gmail.com} + s.extra_rdoc_files = [ + "LICENSE", + "README.rdoc" + ] + s.files = [ + ".document", + ".gitignore", + "LICENSE", + "README.rdoc", + "Rakefile", + "VERSION", + "aasm.gemspec", + "lib/aasm.rb", + "lib/aasm/aasm.rb", + "lib/aasm/event.rb", + "lib/aasm/persistence.rb", + "lib/aasm/persistence/active_record_persistence.rb", + "lib/aasm/state.rb", + "lib/aasm/state_machine.rb", + "lib/aasm/state_transition.rb", + "lib/aasm/supporting_classes.rb", + "spec/functional/conversation.rb", + "spec/functional/conversation_spec.rb", + "spec/spec_helper.rb", + "spec/unit/aasm_spec.rb", + "spec/unit/active_record_persistence_spec.rb", + "spec/unit/before_after_callbacks_spec.rb", + "spec/unit/event_spec.rb", + "spec/unit/state_spec.rb", + "spec/unit/state_transition_spec.rb", + "test/functional/auth_machine_test.rb", + "test/test_helper.rb", + "test/unit/aasm_test.rb", + "test/unit/event_test.rb", + "test/unit/state_test.rb", + "test/unit/state_transition_test.rb" + ] + s.homepage = %q{http://rubyist.github.com/aasm/} + s.rdoc_options = ["--charset=UTF-8"] + s.require_paths = ["lib"] + s.rubygems_version = %q{1.3.7} + s.summary = %q{State machine mixin for Ruby objects} + s.test_files = [ + "spec/functional/conversation.rb", + "spec/functional/conversation_spec.rb", + "spec/spec_helper.rb", + "spec/unit/aasm_spec.rb", + "spec/unit/active_record_persistence_spec.rb", + "spec/unit/before_after_callbacks_spec.rb", + "spec/unit/event_spec.rb", + "spec/unit/state_spec.rb", + "spec/unit/state_transition_spec.rb", + "test/functional/auth_machine_test.rb", + "test/test_helper.rb", + "test/unit/aasm_test.rb", + "test/unit/event_test.rb", + "test/unit/state_test.rb", + "test/unit/state_transition_test.rb" + ] + + if s.respond_to? :specification_version then + current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION + s.specification_version = 3 + + if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then + s.add_development_dependency(%q, [">= 0"]) + s.add_development_dependency(%q, [">= 0"]) + s.add_development_dependency(%q, [">= 0"]) + else + s.add_dependency(%q, [">= 0"]) + s.add_dependency(%q, [">= 0"]) + s.add_dependency(%q, [">= 0"]) + end + else + s.add_dependency(%q, [">= 0"]) + s.add_dependency(%q, [">= 0"]) + s.add_dependency(%q, [">= 0"]) + end +end + diff --git a/vendor/gems/aasm-2.2.0/lib/aasm.rb b/vendor/gems/aasm-2.2.0/lib/aasm.rb new file mode 100644 index 00000000..659d1d1d --- /dev/null +++ b/vendor/gems/aasm-2.2.0/lib/aasm.rb @@ -0,0 +1,9 @@ +module AASM +end + +require 'ostruct' + +require File.join(File.dirname(__FILE__), 'aasm', 'supporting_classes') +require File.join(File.dirname(__FILE__), 'aasm', 'state_machine') +require File.join(File.dirname(__FILE__), 'aasm', 'persistence') +require File.join(File.dirname(__FILE__), 'aasm', 'aasm') diff --git a/vendor/gems/aasm-2.2.0/lib/aasm/aasm.rb b/vendor/gems/aasm-2.2.0/lib/aasm/aasm.rb new file mode 100644 index 00000000..b08c5223 --- /dev/null +++ b/vendor/gems/aasm-2.2.0/lib/aasm/aasm.rb @@ -0,0 +1,196 @@ +module AASM + class InvalidTransition < RuntimeError + end + + class UndefinedState < RuntimeError + end + + def self.included(base) #:nodoc: + base.extend AASM::ClassMethods + AASM::Persistence.set_persistence(base) + unless AASM::StateMachine[base] + AASM::StateMachine[base] = AASM::StateMachine.new('') + end + super + end + + module ClassMethods + def inherited(klass) + AASM::StateMachine[klass] = AASM::StateMachine[self].clone + super + end + + def aasm_initial_state(set_state=nil) + if set_state + AASM::StateMachine[self].initial_state = set_state + else + AASM::StateMachine[self].initial_state + end + end + + def aasm_initial_state=(state) + AASM::StateMachine[self].initial_state = state + end + + def aasm_state(name, options={}) + sm = AASM::StateMachine[self] + sm.create_state(name, options) + sm.initial_state = name unless sm.initial_state + + define_method("#{name.to_s}?") do + aasm_current_state == name + end + end + + def aasm_event(name, options = {}, &block) + sm = AASM::StateMachine[self] + + unless sm.events.has_key?(name) + sm.events[name] = AASM::SupportingClasses::Event.new(name, options, &block) + end + + define_method("#{name.to_s}!") do |*args| + aasm_fire_event(name, true, *args) + end + + define_method("#{name.to_s}") do |*args| + aasm_fire_event(name, false, *args) + end + end + + def aasm_states + AASM::StateMachine[self].states + end + + def aasm_events + AASM::StateMachine[self].events + end + + def aasm_states_for_select + AASM::StateMachine[self].states.map { |state| state.for_select } + end + + end + + # Instance methods + def aasm_current_state + return @aasm_current_state if @aasm_current_state + + if self.respond_to?(:aasm_read_state) || self.private_methods.include?('aasm_read_state') + @aasm_current_state = aasm_read_state + end + return @aasm_current_state if @aasm_current_state + + aasm_enter_initial_state + end + + def aasm_enter_initial_state + state_name = aasm_determine_state_name(self.class.aasm_initial_state) + state = aasm_state_object_for_state(state_name) + + state.call_action(:before_enter, self) + state.call_action(:enter, self) + self.aasm_current_state = state_name + state.call_action(:after_enter, self) + + state_name + end + + def aasm_events_for_current_state + aasm_events_for_state(aasm_current_state) + end + + def aasm_events_for_state(state) + events = self.class.aasm_events.values.select {|event| event.transitions_from_state?(state) } + events.map {|event| event.name} + end + + private + + def set_aasm_current_state_with_persistence(state) + save_success = true + if self.respond_to?(:aasm_write_state) || self.private_methods.include?('aasm_write_state') + save_success = aasm_write_state(state) + end + self.aasm_current_state = state if save_success + + save_success + end + + def aasm_current_state=(state) + if self.respond_to?(:aasm_write_state_without_persistence) || self.private_methods.include?('aasm_write_state_without_persistence') + aasm_write_state_without_persistence(state) + end + @aasm_current_state = state + end + + def aasm_determine_state_name(state) + case state + when Symbol, String + state + when Proc + state.call(self) + else + raise NotImplementedError, "Unrecognized state-type given. Expected Symbol, String, or Proc." + end + end + + def aasm_state_object_for_state(name) + obj = self.class.aasm_states.find {|s| s == name} + raise AASM::UndefinedState, "State :#{name} doesn't exist" if obj.nil? + obj + end + + def aasm_fire_event(name, persist, *args) + event = self.class.aasm_events[name] + begin + old_state = aasm_state_object_for_state(aasm_current_state) + + + old_state.call_action(:exit, self) + + # new event before callback + event.call_action(:before, self) + + new_state_name = event.fire(self, *args) + + unless new_state_name.nil? + new_state = aasm_state_object_for_state(new_state_name) + + # new before_ callbacks + old_state.call_action(:before_exit, self) + new_state.call_action(:before_enter, self) + + new_state.call_action(:enter, self) + + persist_successful = true + if persist + persist_successful = set_aasm_current_state_with_persistence(new_state_name) + event.execute_success_callback(self) if persist_successful + else + self.aasm_current_state = new_state_name + end + + if persist_successful + old_state.call_action(:after_exit, self) + new_state.call_action(:after_enter, self) + event.call_action(:after, self) + + self.aasm_event_fired(name, old_state.name, self.aasm_current_state) if self.respond_to?(:aasm_event_fired) + else + self.aasm_event_failed(name, old_state.name) if self.respond_to?(:aasm_event_failed) + end + + persist_successful + else + if self.respond_to?(:aasm_event_failed) + self.aasm_event_failed(name, old_state.name) + end + + false + end + rescue StandardError => e + event.execute_error_callback(self, e) + end + end +end diff --git a/vendor/gems/aasm-2.2.0/lib/aasm/event.rb b/vendor/gems/aasm-2.2.0/lib/aasm/event.rb new file mode 100644 index 00000000..22133ae3 --- /dev/null +++ b/vendor/gems/aasm-2.2.0/lib/aasm/event.rb @@ -0,0 +1,109 @@ +class AASM::SupportingClasses::Event + attr_reader :name, :success, :options + + def initialize(name, options = {}, &block) + @name = name + @transitions = [] + update(options, &block) + end + + def fire(obj, to_state=nil, *args) + transitions = @transitions.select { |t| t.from == obj.aasm_current_state } + raise AASM::InvalidTransition, "Event '#{name}' cannot transition from '#{obj.aasm_current_state}'" if transitions.size == 0 + + next_state = nil + transitions.each do |transition| + next if to_state and !Array(transition.to).include?(to_state) + if transition.perform(obj) + next_state = to_state || Array(transition.to).first + transition.execute(obj, *args) + break + end + end + next_state + end + + def transitions_from_state?(state) + @transitions.any? { |t| t.from == state } + end + + def transitions_from_state(state) + @transitions.select { |t| t.from == state } + end + + def all_transitions + @transitions + end + + def call_action(action, record) + action = @options[action] + action.is_a?(Array) ? + action.each {|a| _call_action(a, record)} : + _call_action(action, record) + end + + def ==(event) + if event.is_a? Symbol + name == event + else + name == event.name + end + end + + def update(options = {}, &block) + if options.key?(:success) then + @success = options[:success] + end + if options.key?(:error) then + @error = options[:error] + end + if block then + instance_eval(&block) + end + @options = options + self + end + + def execute_success_callback(obj, success = nil) + callback = success || @success + case(callback) + when String, Symbol + obj.send(callback) + when Proc + callback.call(obj) + when Array + callback.each{|meth|self.execute_success_callback(obj, meth)} + end + end + + def execute_error_callback(obj, error, error_callback=nil) + callback = error_callback || @error + raise error unless callback + case(callback) + when String, Symbol + raise NoMethodError unless obj.respond_to?(callback.to_sym) + obj.send(callback, error) + when Proc + callback.call(obj, error) + when Array + callback.each{|meth|self.execute_error_callback(obj, error, meth)} + end + end + + private + + def _call_action(action, record) + case action + when Symbol, String + record.send(action) + when Proc + action.call(record) + end + end + + def transitions(trans_opts) + Array(trans_opts[:from]).each do |s| + @transitions << AASM::SupportingClasses::StateTransition.new(trans_opts.merge({:from => s.to_sym})) + end + end +end diff --git a/vendor/gems/aasm-2.2.0/lib/aasm/persistence.rb b/vendor/gems/aasm-2.2.0/lib/aasm/persistence.rb new file mode 100644 index 00000000..5704d802 --- /dev/null +++ b/vendor/gems/aasm-2.2.0/lib/aasm/persistence.rb @@ -0,0 +1,14 @@ +module AASM::Persistence + + # Checks to see this class or any of it's superclasses inherit from + # ActiveRecord::Base and if so includes ActiveRecordPersistence + def self.set_persistence(base) + # Use a fancier auto-loading thingy, perhaps. When there are more persistence engines. + hierarchy = base.ancestors.map {|klass| klass.to_s} + + if hierarchy.include?("ActiveRecord::Base") + require File.join(File.dirname(__FILE__), 'persistence', 'active_record_persistence') + base.send(:include, AASM::Persistence::ActiveRecordPersistence) + end + end +end diff --git a/vendor/gems/aasm-2.2.0/lib/aasm/persistence/active_record_persistence.rb b/vendor/gems/aasm-2.2.0/lib/aasm/persistence/active_record_persistence.rb new file mode 100644 index 00000000..528b404f --- /dev/null +++ b/vendor/gems/aasm-2.2.0/lib/aasm/persistence/active_record_persistence.rb @@ -0,0 +1,259 @@ +module AASM + module Persistence + module ActiveRecordPersistence + # This method: + # + # * extends the model with ClassMethods + # * includes InstanceMethods + # + # Unless the corresponding methods are already defined, it includes + # * ReadState + # * WriteState + # * WriteStateWithoutPersistence + # + # Adds + # + # before_validation :aasm_ensure_initial_state, :on => :create + # + # As a result, it doesn't matter when you define your methods - the following 2 are equivalent + # + # class Foo < ActiveRecord::Base + # def aasm_write_state(state) + # "bar" + # end + # include AASM + # end + # + # class Foo < ActiveRecord::Base + # include AASM + # def aasm_write_state(state) + # "bar" + # end + # end + # + def self.included(base) + base.extend AASM::Persistence::ActiveRecordPersistence::ClassMethods + base.send(:include, AASM::Persistence::ActiveRecordPersistence::InstanceMethods) + base.send(:include, AASM::Persistence::ActiveRecordPersistence::ReadState) unless base.method_defined?(:aasm_read_state) + base.send(:include, AASM::Persistence::ActiveRecordPersistence::WriteState) unless base.method_defined?(:aasm_write_state) + base.send(:include, AASM::Persistence::ActiveRecordPersistence::WriteStateWithoutPersistence) unless base.method_defined?(:aasm_write_state_without_persistence) + + if base.respond_to?(:named_scope) || base.respond_to?(:scope) + base.extend(AASM::Persistence::ActiveRecordPersistence::NamedScopeMethods) + + base.class_eval do + class << self + unless method_defined?(:aasm_state_without_scope) + alias_method :aasm_state_without_scope, :aasm_state + alias_method :aasm_state, :aasm_state_with_scope + end + end + end + end + + if ActiveRecord::VERSION::MAJOR >= 3 + base.before_validation(:aasm_ensure_initial_state, :on => :create) + else + base.before_validation_on_create(:aasm_ensure_initial_state) + end + end + + module ClassMethods + # Maps to the aasm_column in the database. Defaults to "aasm_state". You can write: + # + # create_table :foos do |t| + # t.string :name + # t.string :aasm_state + # end + # + # class Foo < ActiveRecord::Base + # include AASM + # end + # + # OR: + # + # create_table :foos do |t| + # t.string :name + # t.string :status + # end + # + # class Foo < ActiveRecord::Base + # include AASM + # aasm_column :status + # end + # + # This method is both a getter and a setter + def aasm_column(column_name=nil) + if column_name + AASM::StateMachine[self].config.column = column_name.to_sym + # @aasm_column = column_name.to_sym + else + AASM::StateMachine[self].config.column ||= :aasm_state + # @aasm_column ||= :aasm_state + end + # @aasm_column + AASM::StateMachine[self].config.column + end + + def find_in_state(number, state, *args) + with_state_scope state do + find(number, *args) + end + end + + def count_in_state(state, *args) + with_state_scope state do + count(*args) + end + end + + def calculate_in_state(state, *args) + with_state_scope state do + calculate(*args) + end + end + + protected + def with_state_scope(state) + with_scope :find => {:conditions => ["#{table_name}.#{aasm_column} = ?", state.to_s]} do + yield if block_given? + end + end + end + + module InstanceMethods + + # Returns the current aasm_state of the object. Respects reload and + # any changes made to the aasm_state field directly + # + # Internally just calls aasm_read_state + # + # foo = Foo.find(1) + # foo.aasm_current_state # => :pending + # foo.aasm_state = "opened" + # foo.aasm_current_state # => :opened + # foo.close # => calls aasm_write_state_without_persistence + # foo.aasm_current_state # => :closed + # foo.reload + # foo.aasm_current_state # => :pending + # + def aasm_current_state + @current_state = aasm_read_state + end + + private + + # Ensures that if the aasm_state column is nil and the record is new + # that the initial state gets populated before validation on create + # + # foo = Foo.new + # foo.aasm_state # => nil + # foo.valid? + # foo.aasm_state # => "open" (where :open is the initial state) + # + # + # foo = Foo.find(:first) + # foo.aasm_state # => 1 + # foo.aasm_state = nil + # foo.valid? + # foo.aasm_state # => nil + # + def aasm_ensure_initial_state + send("#{self.class.aasm_column}=", self.aasm_enter_initial_state.to_s) if send(self.class.aasm_column).blank? + end + + end + + module WriteStateWithoutPersistence + # Writes state to the state column, but does not persist it to the database + # + # foo = Foo.find(1) + # foo.aasm_current_state # => :opened + # foo.close + # foo.aasm_current_state # => :closed + # Foo.find(1).aasm_current_state # => :opened + # foo.save + # foo.aasm_current_state # => :closed + # Foo.find(1).aasm_current_state # => :closed + # + # NOTE: intended to be called from an event + def aasm_write_state_without_persistence(state) + write_attribute(self.class.aasm_column, state.to_s) + end + end + + module WriteState + # Writes state to the state column and persists it to the database + # + # foo = Foo.find(1) + # foo.aasm_current_state # => :opened + # foo.close! + # foo.aasm_current_state # => :closed + # Foo.find(1).aasm_current_state # => :closed + # + # NOTE: intended to be called from an event + def aasm_write_state(state) + old_value = read_attribute(self.class.aasm_column) + write_attribute(self.class.aasm_column, state.to_s) + + # see https://github.com/rubyist/aasm/issues/2 + unless self.save + write_attribute(self.class.aasm_column, old_value) + # return false + return true + end + + true + end + end + + module ReadState + + # Returns the value of the aasm_column - called from aasm_current_state + # + # If it's a new record, and the aasm state column is blank it returns the initial state: + # + # class Foo < ActiveRecord::Base + # include AASM + # aasm_column :status + # aasm_state :opened + # aasm_state :closed + # end + # + # foo = Foo.new + # foo.current_state # => :opened + # foo.close + # foo.current_state # => :closed + # + # foo = Foo.find(1) + # foo.current_state # => :opened + # foo.aasm_state = nil + # foo.current_state # => nil + # + # NOTE: intended to be called from an event + # + # This allows for nil aasm states - be sure to add validation to your model + def aasm_read_state + if new_record? + send(self.class.aasm_column).blank? ? aasm_determine_state_name(self.class.aasm_initial_state) : send(self.class.aasm_column).to_sym + else + send(self.class.aasm_column).nil? ? nil : send(self.class.aasm_column).to_sym + end + end + end + + module NamedScopeMethods + def aasm_state_with_scope name, options = {} + aasm_state_without_scope name, options + + unless self.respond_to?(name) + scope_options = {:conditions => { "#{table_name}.#{self.aasm_column}" => name.to_s}} + scope_method = ActiveRecord::VERSION::MAJOR >= 3 ? :scope : :named_scope + self.send(scope_method, name, scope_options) + end + + end + end + end + end +end diff --git a/vendor/gems/aasm-2.2.0/lib/aasm/state.rb b/vendor/gems/aasm-2.2.0/lib/aasm/state.rb new file mode 100644 index 00000000..df3840f7 --- /dev/null +++ b/vendor/gems/aasm-2.2.0/lib/aasm/state.rb @@ -0,0 +1,53 @@ +class AASM::SupportingClasses::State + attr_reader :name, :options + + def initialize(name, options={}) + @name = name + update(options) + end + + def ==(state) + if state.is_a? Symbol + name == state + else + name == state.name + end + end + + def call_action(action, record) + action = @options[action] + catch :halt_aasm_chain do + action.is_a?(Array) ? + action.each {|a| _call_action(a, record)} : + _call_action(action, record) + end + end + + def display_name + @display_name ||= name.to_s.gsub(/_/, ' ').capitalize + end + + def for_select + [display_name, name.to_s] + end + + def update(options = {}) + if options.key?(:display) then + @display_name = options.delete(:display) + end + @options = options + self + end + + private + + def _call_action(action, record) + case action + when Symbol, String + record.send(action) + when Proc + action.call(record) + end + end + +end diff --git a/vendor/gems/aasm-2.2.0/lib/aasm/state_machine.rb b/vendor/gems/aasm-2.2.0/lib/aasm/state_machine.rb new file mode 100644 index 00000000..92313cf4 --- /dev/null +++ b/vendor/gems/aasm-2.2.0/lib/aasm/state_machine.rb @@ -0,0 +1,32 @@ +class AASM::StateMachine + def self.[](*args) + (@machines ||= {})[args] + end + + def self.[]=(*args) + val = args.pop + (@machines ||= {})[args] = val + end + + attr_accessor :states, :events, :initial_state, :config + attr_reader :name + + def initialize(name) + @name = name + @initial_state = nil + @states = [] + @events = {} + @config = OpenStruct.new + end + + def clone + klone = super + klone.states = states.clone + klone.events = events.clone + klone + end + + def create_state(name, options) + @states << AASM::SupportingClasses::State.new(name, options) unless @states.include?(name) + end +end diff --git a/vendor/gems/aasm-2.2.0/lib/aasm/state_transition.rb b/vendor/gems/aasm-2.2.0/lib/aasm/state_transition.rb new file mode 100644 index 00000000..c5dce1df --- /dev/null +++ b/vendor/gems/aasm-2.2.0/lib/aasm/state_transition.rb @@ -0,0 +1,46 @@ +class AASM::SupportingClasses::StateTransition + attr_reader :from, :to, :opts + alias_method :options, :opts + + def initialize(opts) + @from, @to, @guard, @on_transition = opts[:from], opts[:to], opts[:guard], opts[:on_transition] + @opts = opts + end + + def perform(obj) + case @guard + when Symbol, String + obj.send(@guard) + when Proc + @guard.call(obj) + else + true + end + end + + def execute(obj, *args) + @on_transition.is_a?(Array) ? + @on_transition.each {|ot| _execute(obj, ot, *args)} : + _execute(obj, @on_transition, *args) + end + + def ==(obj) + @from == obj.from && @to == obj.to + end + + def from?(value) + @from == value + end + + private + + def _execute(obj, on_transition, *args) + case on_transition + when Symbol, String + obj.send(on_transition, *args) + when Proc + on_transition.call(obj, *args) + end + end + +end diff --git a/vendor/gems/aasm-2.2.0/lib/aasm/supporting_classes.rb b/vendor/gems/aasm-2.2.0/lib/aasm/supporting_classes.rb new file mode 100644 index 00000000..145eba5a --- /dev/null +++ b/vendor/gems/aasm-2.2.0/lib/aasm/supporting_classes.rb @@ -0,0 +1,6 @@ +module AASM::SupportingClasses +end + +require File.join(File.dirname(__FILE__), 'state_transition') +require File.join(File.dirname(__FILE__), 'event') +require File.join(File.dirname(__FILE__), 'state') diff --git a/vendor/gems/aasm-2.2.0/spec/functional/conversation.rb b/vendor/gems/aasm-2.2.0/spec/functional/conversation.rb new file mode 100644 index 00000000..da6e2bba --- /dev/null +++ b/vendor/gems/aasm-2.2.0/spec/functional/conversation.rb @@ -0,0 +1,49 @@ +require File.join(File.dirname(__FILE__), '..', '..', 'lib', 'aasm') + +class Conversation + include AASM + + aasm_initial_state :needs_attention + + aasm_state :needs_attention + aasm_state :read + aasm_state :closed + aasm_state :awaiting_response + aasm_state :junk + + aasm_event :new_message do + end + + aasm_event :view do + transitions :to => :read, :from => [:needs_attention] + end + + aasm_event :reply do + end + + aasm_event :close do + transitions :to => :closed, :from => [:read, :awaiting_response] + end + + aasm_event :junk do + transitions :to => :junk, :from => [:read] + end + + aasm_event :unjunk do + end + + def initialize(persister) + @persister = persister + end + + + private + def aasm_read_state + @persister.read_state + end + + def aasm_write_state(state) + @persister.write_state(state) + end + +end diff --git a/vendor/gems/aasm-2.2.0/spec/functional/conversation_spec.rb b/vendor/gems/aasm-2.2.0/spec/functional/conversation_spec.rb new file mode 100644 index 00000000..8cfc97c9 --- /dev/null +++ b/vendor/gems/aasm-2.2.0/spec/functional/conversation_spec.rb @@ -0,0 +1,8 @@ +require File.expand_path(File.join(File.dirname(__FILE__), '..', 'spec_helper')) +require File.expand_path(File.join(File.dirname(__FILE__), 'conversation')) + +describe Conversation, 'description' do + it '.aasm_states should contain all of the states' do + Conversation.aasm_states.should == [:needs_attention, :read, :closed, :awaiting_response, :junk] + end +end diff --git a/vendor/gems/aasm-2.2.0/spec/spec_helper.rb b/vendor/gems/aasm-2.2.0/spec/spec_helper.rb new file mode 100644 index 00000000..9b9df8e5 --- /dev/null +++ b/vendor/gems/aasm-2.2.0/spec/spec_helper.rb @@ -0,0 +1,11 @@ +$LOAD_PATH.unshift(File.expand_path(File.dirname(__FILE__))) +$LOAD_PATH.unshift(File.expand_path(File.join(File.dirname(__FILE__), '..', 'lib'))) + +require 'aasm' + +require 'spec' +require 'spec/autorun' + +Spec::Runner.configure do |config| + +end diff --git a/vendor/gems/aasm-2.2.0/spec/unit/aasm_spec.rb b/vendor/gems/aasm-2.2.0/spec/unit/aasm_spec.rb new file mode 100644 index 00000000..7d7e0613 --- /dev/null +++ b/vendor/gems/aasm-2.2.0/spec/unit/aasm_spec.rb @@ -0,0 +1,462 @@ +require File.expand_path(File.join(File.dirname(__FILE__), '..', 'spec_helper')) + +class Foo + include AASM + aasm_initial_state :open + aasm_state :open, :exit => :exit + aasm_state :closed, :enter => :enter + + aasm_event :close, :success => :success_callback do + transitions :to => :closed, :from => [:open] + end + + aasm_event :null do + transitions :to => :closed, :from => [:open], :guard => :always_false + end + + def always_false + false + end + + def success_callback + end + + def enter + end + def exit + end +end + +class FooTwo < Foo + include AASM + aasm_state :foo +end + +class Bar + include AASM + + aasm_state :read + aasm_state :ended + + aasm_event :foo do + transitions :to => :ended, :from => [:read] + end +end + +class Baz < Bar +end + +class Banker + include AASM + aasm_initial_state Proc.new { |banker| banker.rich? ? :retired : :selling_bad_mortgages } + aasm_state :retired + aasm_state :selling_bad_mortgages + RICH = 1_000_000 + attr_accessor :balance + def initialize(balance = 0); self.balance = balance; end + def rich?; self.balance >= RICH; end +end + + +describe AASM, '- class level definitions' do + it 'should define a class level aasm_initial_state() method on its including class' do + Foo.should respond_to(:aasm_initial_state) + end + + it 'should define a class level aasm_state() method on its including class' do + Foo.should respond_to(:aasm_state) + end + + it 'should define a class level aasm_event() method on its including class' do + Foo.should respond_to(:aasm_event) + end + + it 'should define a class level aasm_states() method on its including class' do + Foo.should respond_to(:aasm_states) + end + + it 'should define a class level aasm_states_for_select() method on its including class' do + Foo.should respond_to(:aasm_states_for_select) + end + + it 'should define a class level aasm_events() method on its including class' do + Foo.should respond_to(:aasm_events) + end + +end + + +describe AASM, '- subclassing' do + it 'should have the parent states' do + Foo.aasm_states.each do |state| + FooTwo.aasm_states.should include(state) + end + end + + it 'should not add the child states to the parent machine' do + Foo.aasm_states.should_not include(:foo) + end +end + + +describe AASM, '- aasm_states_for_select' do + it "should return a select friendly array of states in the form of [['Friendly name', 'state_name']]" do + Foo.aasm_states_for_select.should == [['Open', 'open'], ['Closed', 'closed']] + end +end + +describe AASM, '- instance level definitions' do + before(:each) do + @foo = Foo.new + end + + it 'should define a state querying instance method on including class' do + @foo.should respond_to(:open?) + end + + it 'should define an event! inance method' do + @foo.should respond_to(:close!) + end +end + +describe AASM, '- initial states' do + before(:each) do + @foo = Foo.new + @bar = Bar.new + end + + it 'should set the initial state' do + @foo.aasm_current_state.should == :open + end + + it '#open? should be initially true' do + @foo.open?.should be_true + end + + it '#closed? should be initially false' do + @foo.closed?.should be_false + end + + it 'should use the first state defined if no initial state is given' do + @bar.aasm_current_state.should == :read + end + + it 'should determine initial state from the Proc results' do + Banker.new(Banker::RICH - 1).aasm_current_state.should == :selling_bad_mortgages + Banker.new(Banker::RICH + 1).aasm_current_state.should == :retired + end +end + +describe AASM, '- event firing with persistence' do + it 'should fire the Event' do + foo = Foo.new + + Foo.aasm_events[:close].should_receive(:fire).with(foo) + foo.close! + end + + it 'should update the current state' do + foo = Foo.new + foo.close! + + foo.aasm_current_state.should == :closed + end + + it 'should call the success callback if one was provided' do + foo = Foo.new + + foo.should_receive(:success_callback) + + foo.close! + end + + it 'should attempt to persist if aasm_write_state is defined' do + foo = Foo.new + + def foo.aasm_write_state + end + + foo.should_receive(:aasm_write_state) + + foo.close! + end + + it 'should return true if aasm_write_state is defined and returns true' do + foo = Foo.new + + def foo.aasm_write_state(state) + true + end + + foo.close!.should be_true + end + + it 'should return false if aasm_write_state is defined and returns false' do + foo = Foo.new + + def foo.aasm_write_state(state) + false + end + + foo.close!.should be_false + end + + it "should not update the aasm_current_state if the write fails" do + foo = Foo.new + + def foo.aasm_write_state + false + end + + foo.should_receive(:aasm_write_state) + + foo.close! + foo.aasm_current_state.should == :open + end +end + +describe AASM, '- event firing without persistence' do + it 'should fire the Event' do + foo = Foo.new + + Foo.aasm_events[:close].should_receive(:fire).with(foo) + foo.close + end + + it 'should update the current state' do + foo = Foo.new + foo.close + + foo.aasm_current_state.should == :closed + end + + it 'should attempt to persist if aasm_write_state is defined' do + foo = Foo.new + + def foo.aasm_write_state + end + + foo.should_receive(:aasm_write_state_without_persistence).twice + + foo.close + end +end + +describe AASM, '- persistence' do + it 'should read the state if it has not been set and aasm_read_state is defined' do + foo = Foo.new + def foo.aasm_read_state + end + + foo.should_receive(:aasm_read_state) + + foo.aasm_current_state + end +end + +describe AASM, '- getting events for a state' do + it '#aasm_events_for_current_state should use current state' do + foo = Foo.new + foo.should_receive(:aasm_current_state) + foo.aasm_events_for_current_state + end + + it '#aasm_events_for_current_state should use aasm_events_for_state' do + foo = Foo.new + foo.stub!(:aasm_current_state).and_return(:foo) + foo.should_receive(:aasm_events_for_state).with(:foo) + foo.aasm_events_for_current_state + end +end + +describe AASM, '- event callbacks' do + describe "with an error callback defined" do + before do + class Foo + aasm_event :safe_close, :success => :success_callback, :error => :error_callback do + transitions :to => :closed, :from => [:open] + end + end + + @foo = Foo.new + end + + it "should run error_callback if an exception is raised and error_callback defined" do + def @foo.error_callback(e) + end + @foo.stub!(:enter).and_raise(e=StandardError.new) + @foo.should_receive(:error_callback).with(e) + @foo.safe_close! + end + + it "should raise NoMethodError if exceptionis raised and error_callback is declared but not defined" do + @foo.stub!(:enter).and_raise(StandardError) + lambda{@foo.safe_close!}.should raise_error(NoMethodError) + end + + it "should propagate an error if no error callback is declared" do + @foo.stub!(:enter).and_raise("Cannot enter safe") + lambda{@foo.close!}.should raise_error(StandardError, "Cannot enter safe") + end + end + + describe "with aasm_event_fired defined" do + before do + @foo = Foo.new + def @foo.aasm_event_fired(event, from, to) + end + end + + it 'should call it for successful bang fire' do + @foo.should_receive(:aasm_event_fired).with(:close, :open, :closed) + @foo.close! + end + + it 'should call it for successful non-bang fire' do + @foo.should_receive(:aasm_event_fired) + @foo.close + end + + it 'should not call it for failing bang fire' do + @foo.stub!(:set_aasm_current_state_with_persistence).and_return(false) + @foo.should_not_receive(:aasm_event_fired) + @foo.close! + end + end + + describe "with aasm_event_failed defined" do + before do + @foo = Foo.new + def @foo.aasm_event_failed(event, from) + end + end + + it 'should call it when transition failed for bang fire' do + @foo.should_receive(:aasm_event_failed).with(:null, :open) + @foo.null! + end + + it 'should call it when transition failed for non-bang fire' do + @foo.should_receive(:aasm_event_failed).with(:null, :open) + @foo.null + end + + it 'should not call it if persist fails for bang fire' do + @foo.stub!(:set_aasm_current_state_with_persistence).and_return(false) + @foo.should_receive(:aasm_event_failed) + @foo.close! + end + end +end + +describe AASM, '- state actions' do + it "should call enter when entering state" do + foo = Foo.new + foo.should_receive(:enter) + + foo.close + end + + it "should call exit when exiting state" do + foo = Foo.new + foo.should_receive(:exit) + + foo.close + end +end + + +describe Baz do + it "should have the same states as it's parent" do + Baz.aasm_states.should == Bar.aasm_states + end + + it "should have the same events as it's parent" do + Baz.aasm_events.should == Bar.aasm_events + end +end + + +class ChetanPatil + include AASM + aasm_initial_state :sleeping + aasm_state :sleeping + aasm_state :showering + aasm_state :working + aasm_state :dating + aasm_state :prettying_up + + aasm_event :wakeup do + transitions :from => :sleeping, :to => [:showering, :working] + end + + aasm_event :dress do + transitions :from => :sleeping, :to => :working, :on_transition => :wear_clothes + transitions :from => :showering, :to => [:working, :dating], :on_transition => Proc.new { |obj, *args| obj.wear_clothes(*args) } + transitions :from => :showering, :to => :prettying_up, :on_transition => [:condition_hair, :fix_hair] + end + + def wear_clothes(shirt_color, trouser_type) + end + + def condition_hair + end + + def fix_hair + end +end + + +describe ChetanPatil do + it 'should transition to specified next state (sleeping to showering)' do + cp = ChetanPatil.new + cp.wakeup! :showering + + cp.aasm_current_state.should == :showering + end + + it 'should transition to specified next state (sleeping to working)' do + cp = ChetanPatil.new + cp.wakeup! :working + + cp.aasm_current_state.should == :working + end + + it 'should transition to default (first or showering) state' do + cp = ChetanPatil.new + cp.wakeup! + + cp.aasm_current_state.should == :showering + end + + it 'should transition to default state when on_transition invoked' do + cp = ChetanPatil.new + cp.dress!(nil, 'purple', 'dressy') + + cp.aasm_current_state.should == :working + end + + it 'should call on_transition method with args' do + cp = ChetanPatil.new + cp.wakeup! :showering + + cp.should_receive(:wear_clothes).with('blue', 'jeans') + cp.dress! :working, 'blue', 'jeans' + end + + it 'should call on_transition proc' do + cp = ChetanPatil.new + cp.wakeup! :showering + + cp.should_receive(:wear_clothes).with('purple', 'slacks') + cp.dress!(:dating, 'purple', 'slacks') + end + + it 'should call on_transition with an array of methods' do + cp = ChetanPatil.new + cp.wakeup! :showering + cp.should_receive(:condition_hair) + cp.should_receive(:fix_hair) + cp.dress!(:prettying_up) + end +end diff --git a/vendor/gems/aasm-2.2.0/spec/unit/active_record_persistence_spec.rb b/vendor/gems/aasm-2.2.0/spec/unit/active_record_persistence_spec.rb new file mode 100644 index 00000000..75b87c7f --- /dev/null +++ b/vendor/gems/aasm-2.2.0/spec/unit/active_record_persistence_spec.rb @@ -0,0 +1,255 @@ +begin + require 'rubygems' + require 'active_record' + require 'logger' + + ActiveRecord::Base.logger = Logger.new(STDERR) + + # A dummy class for mocking the activerecord connection class + class Connection + end + + class FooBar < ActiveRecord::Base + include AASM + + # Fake this column for testing purposes + attr_accessor :aasm_state + + aasm_state :open + aasm_state :closed + + aasm_event :view do + transitions :to => :read, :from => [:needs_attention] + end + end + + class Fi < ActiveRecord::Base + def aasm_read_state + "fi" + end + include AASM + end + + class Fo < ActiveRecord::Base + def aasm_write_state(state) + "fo" + end + include AASM + end + + class Fum < ActiveRecord::Base + def aasm_write_state_without_persistence(state) + "fum" + end + include AASM + end + + class June < ActiveRecord::Base + include AASM + aasm_column :status + end + + class Beaver < June + end + + class Thief < ActiveRecord::Base + include AASM + aasm_initial_state Proc.new { |thief| thief.skilled ? :rich : :jailed } + aasm_state :rich + aasm_state :jailed + attr_accessor :skilled, :aasm_state + end + + describe "aasm model", :shared => true do + it "should include AASM::Persistence::ActiveRecordPersistence" do + @klass.included_modules.should be_include(AASM::Persistence::ActiveRecordPersistence) + end + it "should include AASM::Persistence::ActiveRecordPersistence::InstanceMethods" do + @klass.included_modules.should be_include(AASM::Persistence::ActiveRecordPersistence::InstanceMethods) + end + end + + describe FooBar, "class methods" do + before(:each) do + @klass = FooBar + end + it_should_behave_like "aasm model" + it "should include AASM::Persistence::ActiveRecordPersistence::ReadState" do + @klass.included_modules.should be_include(AASM::Persistence::ActiveRecordPersistence::ReadState) + end + it "should include AASM::Persistence::ActiveRecordPersistence::WriteState" do + @klass.included_modules.should be_include(AASM::Persistence::ActiveRecordPersistence::WriteState) + end + it "should include AASM::Persistence::ActiveRecordPersistence::WriteStateWithoutPersistence" do + @klass.included_modules.should be_include(AASM::Persistence::ActiveRecordPersistence::WriteStateWithoutPersistence) + end + end + + describe Fi, "class methods" do + before(:each) do + @klass = Fi + end + it_should_behave_like "aasm model" + it "should not include AASM::Persistence::ActiveRecordPersistence::ReadState" do + @klass.included_modules.should_not be_include(AASM::Persistence::ActiveRecordPersistence::ReadState) + end + it "should include AASM::Persistence::ActiveRecordPersistence::WriteState" do + @klass.included_modules.should be_include(AASM::Persistence::ActiveRecordPersistence::WriteState) + end + it "should include AASM::Persistence::ActiveRecordPersistence::WriteStateWithoutPersistence" do + @klass.included_modules.should be_include(AASM::Persistence::ActiveRecordPersistence::WriteStateWithoutPersistence) + end + end + + describe Fo, "class methods" do + before(:each) do + @klass = Fo + end + it_should_behave_like "aasm model" + it "should include AASM::Persistence::ActiveRecordPersistence::ReadState" do + @klass.included_modules.should be_include(AASM::Persistence::ActiveRecordPersistence::ReadState) + end + it "should not include AASM::Persistence::ActiveRecordPersistence::WriteState" do + @klass.included_modules.should_not be_include(AASM::Persistence::ActiveRecordPersistence::WriteState) + end + it "should include AASM::Persistence::ActiveRecordPersistence::WriteStateWithoutPersistence" do + @klass.included_modules.should be_include(AASM::Persistence::ActiveRecordPersistence::WriteStateWithoutPersistence) + end + end + + describe Fum, "class methods" do + before(:each) do + @klass = Fum + end + it_should_behave_like "aasm model" + it "should include AASM::Persistence::ActiveRecordPersistence::ReadState" do + @klass.included_modules.should be_include(AASM::Persistence::ActiveRecordPersistence::ReadState) + end + it "should include AASM::Persistence::ActiveRecordPersistence::WriteState" do + @klass.included_modules.should be_include(AASM::Persistence::ActiveRecordPersistence::WriteState) + end + it "should not include AASM::Persistence::ActiveRecordPersistence::WriteStateWithoutPersistence" do + @klass.included_modules.should_not be_include(AASM::Persistence::ActiveRecordPersistence::WriteStateWithoutPersistence) + end + end + + describe FooBar, "instance methods" do + before(:each) do + connection = mock(Connection, :columns => []) + FooBar.stub!(:connection).and_return(connection) + end + + it "should respond to aasm read state when not previously defined" do + FooBar.new.should respond_to(:aasm_read_state) + end + + it "should respond to aasm write state when not previously defined" do + FooBar.new.should respond_to(:aasm_write_state) + end + + it "should respond to aasm write state without persistence when not previously defined" do + FooBar.new.should respond_to(:aasm_write_state_without_persistence) + end + + it "should return the initial state when new and the aasm field is nil" do + FooBar.new.aasm_current_state.should == :open + end + + it "should return the aasm column when new and the aasm field is not nil" do + foo = FooBar.new + foo.aasm_state = "closed" + foo.aasm_current_state.should == :closed + end + + it "should return the aasm column when not new and the aasm_column is not nil" do + foo = FooBar.new + foo.stub!(:new_record?).and_return(false) + foo.aasm_state = "state" + foo.aasm_current_state.should == :state + end + + it "should allow a nil state" do + foo = FooBar.new + foo.stub!(:new_record?).and_return(false) + foo.aasm_state = nil + foo.aasm_current_state.should be_nil + end + + it "should have aasm_ensure_initial_state" do + foo = FooBar.new + foo.send :aasm_ensure_initial_state + end + + it "should call aasm_ensure_initial_state on validation before create" do + foo = FooBar.new + foo.should_receive(:aasm_ensure_initial_state).and_return(true) + foo.valid? + end + + it "should call aasm_ensure_initial_state on validation before create" do + foo = FooBar.new + foo.stub!(:new_record?).and_return(false) + foo.should_not_receive(:aasm_ensure_initial_state) + foo.valid? + end + + end + + describe 'Beavers' do + it "should have the same states as it's parent" do + Beaver.aasm_states.should == June.aasm_states + end + + it "should have the same events as it's parent" do + Beaver.aasm_events.should == June.aasm_events + end + + it "should have the same column as it's parent" do + Beaver.aasm_column.should == :status + end + end + + describe AASM::Persistence::ActiveRecordPersistence::NamedScopeMethods do + class NamedScopeExample < ActiveRecord::Base + include AASM + end + + context "Does not already respond_to? the scope name" do + it "should add a scope" do + NamedScopeExample.aasm_state :unknown_scope + NamedScopeExample.scopes.keys.should include(:unknown_scope) + end + end + + context "Already respond_to? the scope name" do + it "should not add a scope" do + NamedScopeExample.aasm_state :new + NamedScopeExample.scopes.keys.should_not include(:new) + end + end + end + + describe 'Thieves' do + before(:each) do + connection = mock(Connection, :columns => []) + Thief.stub!(:connection).and_return(connection) + end + + it 'should be rich if they\'re skilled' do + Thief.new(:skilled => true).aasm_current_state.should == :rich + end + + it 'should be jailed if they\'re unskilled' do + Thief.new(:skilled => false).aasm_current_state.should == :jailed + end + end + + # TODO: figure out how to test ActiveRecord reload! without a database + +rescue LoadError => e + if e.message == "no such file to load -- active_record" + puts "You must install active record to run this spec. Install with sudo gem install activerecord" + else + raise + end +end diff --git a/vendor/gems/aasm-2.2.0/spec/unit/before_after_callbacks_spec.rb b/vendor/gems/aasm-2.2.0/spec/unit/before_after_callbacks_spec.rb new file mode 100644 index 00000000..9784befe --- /dev/null +++ b/vendor/gems/aasm-2.2.0/spec/unit/before_after_callbacks_spec.rb @@ -0,0 +1,79 @@ +require File.expand_path(File.join(File.dirname(__FILE__), '..', 'spec_helper')) + +class Foo2 + include AASM + aasm_initial_state :open + aasm_state :open, + :before_enter => :before_enter_open, + :before_exit => :before_exit_open, + :after_enter => :after_enter_open, + :after_exit => :after_exit_open + aasm_state :closed, + :before_enter => :before_enter_closed, + :before_exit => :before_exit_closed, + :after_enter => :after_enter_closed, + :after_exit => :after_exit_closed + + aasm_event :close, :before => :before, :after => :after do + transitions :to => :closed, :from => [:open] + end + + aasm_event :open, :before => :before, :after => :after do + transitions :to => :open, :from => :closed + end + + def before_enter_open + end + def before_exit_open + end + def after_enter_open + end + def after_exit_open + end + + def before_enter_closed + end + def before_exit_closed + end + def after_enter_closed + end + def after_exit_closed + end + + def before + end + def after + end +end + +describe Foo2, '- new callbacks' do + before(:each) do + @foo = Foo2.new + end + + it "should get close callbacks" do + @foo.should_receive(:before).once.ordered + @foo.should_receive(:before_exit_open).once.ordered # these should be before the state changes + @foo.should_receive(:before_enter_closed).once.ordered + @foo.should_receive(:aasm_write_state).once.ordered.and_return(true) # this is when the state changes + @foo.should_receive(:after_exit_open).once.ordered # these should be after the state changes + @foo.should_receive(:after_enter_closed).once.ordered + @foo.should_receive(:after).once.ordered + + @foo.close! + end + + it "should get open callbacks" do + @foo.close! + + @foo.should_receive(:before).once.ordered + @foo.should_receive(:before_exit_closed).once.ordered # these should be before the state changes + @foo.should_receive(:before_enter_open).once.ordered + @foo.should_receive(:aasm_write_state).once.ordered.and_return(true) # this is when the state changes + @foo.should_receive(:after_exit_closed).once.ordered # these should be after the state changes + @foo.should_receive(:after_enter_open).once.ordered + @foo.should_receive(:after).once.ordered + + @foo.open! + end +end diff --git a/vendor/gems/aasm-2.2.0/spec/unit/event_spec.rb b/vendor/gems/aasm-2.2.0/spec/unit/event_spec.rb new file mode 100644 index 00000000..88550963 --- /dev/null +++ b/vendor/gems/aasm-2.2.0/spec/unit/event_spec.rb @@ -0,0 +1,126 @@ +require File.expand_path(File.join(File.dirname(__FILE__), '..', 'spec_helper')) + +describe AASM::SupportingClasses::Event do + before(:each) do + @name = :close_order + @success = :success_callback + end + + def new_event + @event = AASM::SupportingClasses::Event.new(@name, {:success => @success}) do + transitions :to => :closed, :from => [:open, :received] + end + end + + it 'should set the name' do + new_event + @event.name.should == @name + end + + it 'should set the success option' do + new_event + @event.success.should == @success + end + + it 'should create StateTransitions' do + AASM::SupportingClasses::StateTransition.should_receive(:new).with({:to => :closed, :from => :open}) + AASM::SupportingClasses::StateTransition.should_receive(:new).with({:to => :closed, :from => :received}) + new_event + end +end + +describe AASM::SupportingClasses::Event, 'when firing an event' do + it 'should raise an AASM::InvalidTransition error if the transitions are empty' do + obj = mock('object') + obj.stub!(:aasm_current_state) + + event = AASM::SupportingClasses::Event.new(:event) + lambda { event.fire(obj) }.should raise_error(AASM::InvalidTransition) + end + + it 'should return the state of the first matching transition it finds' do + event = AASM::SupportingClasses::Event.new(:event) do + transitions :to => :closed, :from => [:open, :received] + end + + obj = mock('object') + obj.stub!(:aasm_current_state).and_return(:open) + + event.fire(obj).should == :closed + end +end + +describe AASM::SupportingClasses::Event, 'when executing the success callback' do + class ThisNameBetterNotBeInUse + include AASM + + aasm_state :initial + aasm_state :symbol + aasm_state :string + aasm_state :array + aasm_state :proc + end + + it "should send the success callback if it's a symbol" do + ThisNameBetterNotBeInUse.instance_eval { + aasm_event :with_symbol, :success => :symbol_success_callback do + transitions :to => :symbol, :from => [:initial] + end + } + + model = ThisNameBetterNotBeInUse.new + model.should_receive(:symbol_success_callback) + model.with_symbol! + end + + it "should send the success callback if it's a string" do + ThisNameBetterNotBeInUse.instance_eval { + aasm_event :with_string, :success => 'string_success_callback' do + transitions :to => :string, :from => [:initial] + end + } + + model = ThisNameBetterNotBeInUse.new + model.should_receive(:string_success_callback) + model.with_string! + end + + it "should call each success callback if passed an array of strings and/or symbols" do + ThisNameBetterNotBeInUse.instance_eval { + aasm_event :with_array, :success => [:success_callback1, 'success_callback2'] do + transitions :to => :array, :from => [:initial] + end + } + + model = ThisNameBetterNotBeInUse.new + model.should_receive(:success_callback1) + model.should_receive(:success_callback2) + model.with_array! + end + + it "should call each success callback if passed an array of strings and/or symbols and/or procs" do + ThisNameBetterNotBeInUse.instance_eval { + aasm_event :with_array_including_procs, :success => [:success_callback1, 'success_callback2', lambda { |obj| obj.proc_success_callback }] do + transitions :to => :array, :from => [:initial] + end + } + + model = ThisNameBetterNotBeInUse.new + model.should_receive(:success_callback1) + model.should_receive(:success_callback2) + model.should_receive(:proc_success_callback) + model.with_array_including_procs! + end + + it "should call the success callback if it's a proc" do + ThisNameBetterNotBeInUse.instance_eval { + aasm_event :with_proc, :success => lambda { |obj| obj.proc_success_callback } do + transitions :to => :proc, :from => [:initial] + end + } + + model = ThisNameBetterNotBeInUse.new + model.should_receive(:proc_success_callback) + model.with_proc! + end +end diff --git a/vendor/gems/aasm-2.2.0/spec/unit/state_spec.rb b/vendor/gems/aasm-2.2.0/spec/unit/state_spec.rb new file mode 100644 index 00000000..114163d9 --- /dev/null +++ b/vendor/gems/aasm-2.2.0/spec/unit/state_spec.rb @@ -0,0 +1,85 @@ +require File.expand_path(File.join(File.dirname(__FILE__), '..', 'spec_helper')) + +# TODO These are specs ported from original aasm +describe AASM::SupportingClasses::State do + before(:each) do + @name = :astate + @options = { :crazy_custom_key => 'key' } + end + + def new_state(options={}) + AASM::SupportingClasses::State.new(@name, @options.merge(options)) + end + + it 'should set the name' do + state = new_state + + state.name.should == :astate + end + + it 'should set the options and expose them as options' do + state = new_state + + state.options.should == @options + end + + it 'should be equal to a symbol of the same name' do + state = new_state + + state.should == :astate + end + + it 'should be equal to a State of the same name' do + new_state.should == new_state + end + + it 'should send a message to the record for an action if the action is present as a symbol' do + state = new_state(:entering => :foo) + + record = mock('record') + record.should_receive(:foo) + + state.call_action(:entering, record) + end + + it 'should send a message to the record for an action if the action is present as a string' do + state = new_state(:entering => 'foo') + + record = mock('record') + record.should_receive(:foo) + + state.call_action(:entering, record) + end + + it 'should send a message to the record for each action' do + state = new_state(:entering => [:a, :b, "c", lambda {|r| r.foobar }]) + + record = mock('record') + record.should_receive(:a) + record.should_receive(:b) + record.should_receive(:c) + record.should_receive(:foobar) + + state.call_action(:entering, record) + end + + it "should stop calling actions if one of them raises :halt_aasm_chain" do + state = new_state(:entering => [:a, :b, :c]) + + record = mock('record') + record.should_receive(:a) + record.should_receive(:b).and_throw(:halt_aasm_chain) + record.should_not_receive(:c) + + state.call_action(:entering, record) + end + + it 'should call a proc, passing in the record for an action if the action is present' do + state = new_state(:entering => Proc.new {|r| r.foobar}) + + record = mock('record') + record.should_receive(:foobar) + + state.call_action(:entering, record) + end +end diff --git a/vendor/gems/aasm-2.2.0/spec/unit/state_transition_spec.rb b/vendor/gems/aasm-2.2.0/spec/unit/state_transition_spec.rb new file mode 100644 index 00000000..d0812c57 --- /dev/null +++ b/vendor/gems/aasm-2.2.0/spec/unit/state_transition_spec.rb @@ -0,0 +1,84 @@ +require File.expand_path(File.join(File.dirname(__FILE__), '..', 'spec_helper')) + +describe AASM::SupportingClasses::StateTransition do + it 'should set from, to, and opts attr readers' do + opts = {:from => 'foo', :to => 'bar', :guard => 'g'} + st = AASM::SupportingClasses::StateTransition.new(opts) + + st.from.should == opts[:from] + st.to.should == opts[:to] + st.opts.should == opts + end + + it 'should pass equality check if from and to are the same' do + opts = {:from => 'foo', :to => 'bar', :guard => 'g'} + st = AASM::SupportingClasses::StateTransition.new(opts) + + obj = mock('object') + obj.stub!(:from).and_return(opts[:from]) + obj.stub!(:to).and_return(opts[:to]) + + st.should == obj + end + + it 'should fail equality check if from are not the same' do + opts = {:from => 'foo', :to => 'bar', :guard => 'g'} + st = AASM::SupportingClasses::StateTransition.new(opts) + + obj = mock('object') + obj.stub!(:from).and_return('blah') + obj.stub!(:to).and_return(opts[:to]) + + st.should_not == obj + end + + it 'should fail equality check if to are not the same' do + opts = {:from => 'foo', :to => 'bar', :guard => 'g'} + st = AASM::SupportingClasses::StateTransition.new(opts) + + obj = mock('object') + obj.stub!(:from).and_return(opts[:from]) + obj.stub!(:to).and_return('blah') + + st.should_not == obj + end +end + +describe AASM::SupportingClasses::StateTransition, '- when performing guard checks' do + it 'should return true of there is no guard' do + opts = {:from => 'foo', :to => 'bar'} + st = AASM::SupportingClasses::StateTransition.new(opts) + + st.perform(nil).should be_true + end + + it 'should call the method on the object if guard is a symbol' do + opts = {:from => 'foo', :to => 'bar', :guard => :test} + st = AASM::SupportingClasses::StateTransition.new(opts) + + obj = mock('object') + obj.should_receive(:test) + + st.perform(obj) + end + + it 'should call the method on the object if guard is a string' do + opts = {:from => 'foo', :to => 'bar', :guard => 'test'} + st = AASM::SupportingClasses::StateTransition.new(opts) + + obj = mock('object') + obj.should_receive(:test) + + st.perform(obj) + end + + it 'should call the proc passing the object if the guard is a proc' do + opts = {:from => 'foo', :to => 'bar', :guard => Proc.new {|o| o.test}} + st = AASM::SupportingClasses::StateTransition.new(opts) + + obj = mock('object') + obj.should_receive(:test) + + st.perform(obj) + end +end diff --git a/vendor/gems/aasm-2.2.0/test/functional/auth_machine_test.rb b/vendor/gems/aasm-2.2.0/test/functional/auth_machine_test.rb new file mode 100644 index 00000000..f9d8ed84 --- /dev/null +++ b/vendor/gems/aasm-2.2.0/test/functional/auth_machine_test.rb @@ -0,0 +1,120 @@ +require 'test_helper' + +class AuthMachine + include AASM + + attr_accessor :activation_code, :activated_at, :deleted_at + + aasm_initial_state :pending + + aasm_state :passive + aasm_state :pending, :enter => :make_activation_code + aasm_state :active, :enter => :do_activate + aasm_state :suspended + aasm_state :deleted, :enter => :do_delete, :exit => :do_undelete + + aasm_event :register do + transitions :from => :passive, :to => :pending, :guard => Proc.new {|u| u.can_register? } + end + + aasm_event :activate do + transitions :from => :pending, :to => :active + end + + aasm_event :suspend do + transitions :from => [:passive, :pending, :active], :to => :suspended + end + + aasm_event :delete do + transitions :from => [:passive, :pending, :active, :suspended], :to => :deleted + end + + aasm_event :unsuspend do + transitions :from => :suspended, :to => :active, :guard => Proc.new {|u| u.has_activated? } + transitions :from => :suspended, :to => :pending, :guard => Proc.new {|u| u.has_activation_code? } + transitions :from => :suspended, :to => :passive + end + + def initialize + # the AR backend uses a before_validate_on_create :aasm_ensure_initial_state + # lets do something similar here for testing purposes. + aasm_enter_initial_state + end + + def make_activation_code + @activation_code = 'moo' + end + + def do_activate + @activated_at = Time.now + @activation_code = nil + end + + def do_delete + @deleted_at = Time.now + end + + def do_undelete + @deleted_at = false + end + + def can_register? + true + end + + def has_activated? + !!@activated_at + end + + def has_activation_code? + !!@activation_code + end +end + +class AuthMachineTest < Test::Unit::TestCase + context 'authentication state machine' do + context 'on initialization' do + setup do + @auth = AuthMachine.new + end + + should 'be in the pending state' do + assert_equal :pending, @auth.aasm_current_state + end + + should 'have an activation code' do + assert @auth.has_activation_code? + assert_not_nil @auth.activation_code + end + end + + context 'when being unsuspended' do + should 'be active if previously activated' do + @auth = AuthMachine.new + @auth.activate! + @auth.suspend! + @auth.unsuspend! + + assert_equal :active, @auth.aasm_current_state + end + + should 'be pending if not previously activated, but an activation code is present' do + @auth = AuthMachine.new + @auth.suspend! + @auth.unsuspend! + + assert_equal :pending, @auth.aasm_current_state + end + + should 'be passive if not previously activated and there is no activation code' do + @auth = AuthMachine.new + @auth.activation_code = nil + @auth.suspend! + @auth.unsuspend! + + assert_equal :passive, @auth.aasm_current_state + end + end + + end +end diff --git a/vendor/gems/aasm-2.2.0/test/test_helper.rb b/vendor/gems/aasm-2.2.0/test/test_helper.rb new file mode 100644 index 00000000..5dc5fe1c --- /dev/null +++ b/vendor/gems/aasm-2.2.0/test/test_helper.rb @@ -0,0 +1,33 @@ +require 'ostruct' +require 'rubygems' + +begin + gem 'minitest' +rescue Gem::LoadError + puts 'minitest gem not found' +end + +begin + require 'minitest/autorun' + puts 'using minitest' +rescue LoadError + require 'test/unit' + puts 'using test/unit' +end + +require 'rr' +require 'shoulda' + +class Test::Unit::TestCase + include RR::Adapters::TestUnit +end + +begin + require 'ruby-debug' + Debugger.start +rescue LoadError +end + +$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib')) +$LOAD_PATH.unshift(File.dirname(__FILE__)) +require 'aasm' diff --git a/vendor/gems/aasm-2.2.0/test/unit/event_test.rb b/vendor/gems/aasm-2.2.0/test/unit/event_test.rb new file mode 100644 index 00000000..bb79573f --- /dev/null +++ b/vendor/gems/aasm-2.2.0/test/unit/event_test.rb @@ -0,0 +1,54 @@ +require 'test_helper' + +class EventTest < Test::Unit::TestCase + def new_event + @event = AASM::SupportingClasses::Event.new(@name, {:success => @success}) do + transitions :to => :closed, :from => [:open, :received] + end + end + + context 'event' do + setup do + @name = :close_order + @success = :success_callback + end + + should 'set the name' do + assert_equal @name, new_event.name + end + + should 'set the success option' do + assert_equal @success, new_event.success + end + + should 'create StateTransitions' do + mock(AASM::SupportingClasses::StateTransition).new({:to => :closed, :from => :open}) + mock(AASM::SupportingClasses::StateTransition).new({:to => :closed, :from => :received}) + new_event + end + + context 'when firing' do + should 'raise an AASM::InvalidTransition error if the transitions are empty' do + event = AASM::SupportingClasses::Event.new(:event) + + obj = OpenStruct.new + obj.aasm_current_state = :open + + assert_raise AASM::InvalidTransition do + event.fire(obj) + end + end + + should 'return the state of the first matching transition it finds' do + event = AASM::SupportingClasses::Event.new(:event) do + transitions :to => :closed, :from => [:open, :received] + end + + obj = OpenStruct.new + obj.aasm_current_state = :open + + assert_equal :closed, event.fire(obj) + end + end + end +end diff --git a/vendor/gems/aasm-2.2.0/test/unit/state_test.rb b/vendor/gems/aasm-2.2.0/test/unit/state_test.rb new file mode 100644 index 00000000..417c952b --- /dev/null +++ b/vendor/gems/aasm-2.2.0/test/unit/state_test.rb @@ -0,0 +1,69 @@ +require 'test_helper' + +class StateTest < Test::Unit::TestCase + def new_state(options={}) + AASM::SupportingClasses::State.new(@name, @options.merge(options)) + end + + context 'state' do + setup do + @name = :astate + @options = { :crazy_custom_key => 'key' } + end + + should 'set the name' do + assert_equal :astate, new_state.name + end + + should 'set the display_name from name' do + assert_equal "Astate", new_state.display_name + end + + should 'set the display_name from options' do + assert_equal "A State", new_state(:display => "A State").display_name + end + + should 'set the options and expose them as options' do + assert_equal @options, new_state.options + end + + should 'equal a symbol of the same name' do + assert_equal new_state, :astate + end + + should 'equal a state of the same name' do + assert_equal new_state, new_state + end + + should 'send a message to the record for an action if the action is present as a symbol' do + state = new_state(:entering => :foo) + mock(record = Object.new).foo + state.call_action(:entering, record) + end + + should 'send a message to the record for an action if the action is present as a string' do + state = new_state(:entering => 'foo') + mock(record = Object.new).foo + state.call_action(:entering, record) + end + + should 'call a proc with the record as its argument for an action if the action is present as a proc' do + state = new_state(:entering => Proc.new {|r| r.foobar}) + mock(record = Object.new).foobar + state.call_action(:entering, record) + end + + should 'send a message to the record for each action if the action is present as an array' do + state = new_state(:entering => [:a, :b, 'c', lambda {|r| r.foobar}]) + + record = Object.new + mock(record).a + mock(record).b + mock(record).c + mock(record).foobar + + state.call_action(:entering, record) + end + + end +end diff --git a/vendor/gems/aasm-2.2.0/test/unit/state_transition_test.rb b/vendor/gems/aasm-2.2.0/test/unit/state_transition_test.rb new file mode 100644 index 00000000..ed226287 --- /dev/null +++ b/vendor/gems/aasm-2.2.0/test/unit/state_transition_test.rb @@ -0,0 +1,75 @@ +require 'test_helper' + +class StateTransitionTest < Test::Unit::TestCase + context 'state transition' do + setup do + @opts = {:from => 'foo', :to => 'bar', :guard => 'g'} + @st = AASM::SupportingClasses::StateTransition.new(@opts) + end + + should 'set from, to, and opts attr readers' do + assert_equal @opts[:from], @st.from + assert_equal @opts[:to], @st.to + assert_equal @opts, @st.options + end + + should 'pass equality check if from and to are the same' do + obj = OpenStruct.new + obj.from = @opts[:from] + obj.to = @opts[:to] + + assert_equal @st, obj + end + + should 'fail equality check if from is not the same' do + obj = OpenStruct.new + obj.from = 'blah' + obj.to = @opts[:to] + + assert_not_equal @st, obj + end + + should 'fail equality check if to is not the same' do + obj = OpenStruct.new + obj.from = @opts[:from] + obj.to = 'blah' + + assert_not_equal @st, obj + end + + context 'when performing guard checks' do + should 'return true if there is no guard' do + opts = {:from => 'foo', :to => 'bar'} + st = AASM::SupportingClasses::StateTransition.new(opts) + assert st.perform(nil) + end + + should 'call the method on the object if guard is a symbol' do + opts = {:from => 'foo', :to => 'bar', :guard => :test_guard} + st = AASM::SupportingClasses::StateTransition.new(opts) + + mock(obj = Object.new).test_guard + + st.perform(obj) + end + + should 'call the method on the object if guard is a string' do + opts = {:from => 'foo', :to => 'bar', :guard => 'test_guard'} + st = AASM::SupportingClasses::StateTransition.new(opts) + + mock(obj = Object.new).test_guard + + st.perform(obj) + end + + should 'call the proc passing the object if guard is a proc' do + opts = {:from => 'foo', :to => 'bar', :guard => Proc.new {|o| o.test_guard}} + st = AASM::SupportingClasses::StateTransition.new(opts) + + mock(obj = Object.new).test_guard + + st.perform(obj) + end + end + end +end diff --git a/vendor/plugins/acts_as_state_machine/CHANGELOG b/vendor/plugins/acts_as_state_machine/CHANGELOG deleted file mode 100644 index b97ad744..00000000 --- a/vendor/plugins/acts_as_state_machine/CHANGELOG +++ /dev/null @@ -1,13 +0,0 @@ -* trunk * - break with true value [Kaspar Schiess] - -* 2.1 * - After actions [Saimon Moore] - -* 2.0 * (2006-01-20 15:26:28 -0500) - Enter / Exit actions - Transition guards - Guards and actions can be a symbol pointing to a method or a Proc - -* 1.0 * (2006-01-15 12:16:55 -0500) - Initial Release diff --git a/vendor/plugins/acts_as_state_machine/MIT-LICENSE b/vendor/plugins/acts_as_state_machine/MIT-LICENSE deleted file mode 100644 index 3189ba6b..00000000 --- a/vendor/plugins/acts_as_state_machine/MIT-LICENSE +++ /dev/null @@ -1,20 +0,0 @@ -Copyright (c) 2006 Scott Barron - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/vendor/plugins/acts_as_state_machine/README b/vendor/plugins/acts_as_state_machine/README deleted file mode 100644 index 2bbcced6..00000000 --- a/vendor/plugins/acts_as_state_machine/README +++ /dev/null @@ -1,33 +0,0 @@ -= Acts As State Machine - -This act gives an Active Record model the ability to act as a finite state -machine (FSM). - -Acquire via subversion at: - -http://elitists.textdriven.com/svn/plugins/acts_as_state_machine/trunk - -If prompted, use the user/pass anonymous/anonymous. - -== Example - - class Order < ActiveRecord::Base - acts_as_state_machine :initial => :opened - - state :opened - state :closed, :enter => Proc.new {|o| Mailer.send_notice(o)} - state :returned - - event :close do - transitions :to => :closed, :from => :opened - end - - event :return do - transitions :to => :returned, :from => :closed - end - end - - o = Order.create - o.close! # notice is sent by mailer - o.return! - diff --git a/vendor/plugins/acts_as_state_machine/Rakefile b/vendor/plugins/acts_as_state_machine/Rakefile deleted file mode 100644 index 101fdde9..00000000 --- a/vendor/plugins/acts_as_state_machine/Rakefile +++ /dev/null @@ -1,28 +0,0 @@ -require 'rake' -require 'rake/testtask' -require 'rake/rdoctask' - -desc 'Default: run unit tests.' -task :default => [:clean_db, :test] - -desc 'Remove the stale db file' -task :clean_db do - `rm -f #{File.dirname(__FILE__)}/test/state_machine.sqlite.db` -end - -desc 'Test the acts as state machine plugin.' -Rake::TestTask.new(:test) do |t| - t.libs << 'lib' - t.pattern = 'test/**/*_test.rb' - t.verbose = true -end - -desc 'Generate documentation for the acts as state machine plugin.' -Rake::RDocTask.new(:rdoc) do |rdoc| - rdoc.rdoc_dir = 'rdoc' - rdoc.title = 'Acts As State Machine' - rdoc.options << '--line-numbers --inline-source' - rdoc.rdoc_files.include('README') - rdoc.rdoc_files.include('TODO') - rdoc.rdoc_files.include('lib/**/*.rb') -end diff --git a/vendor/plugins/acts_as_state_machine/TODO b/vendor/plugins/acts_as_state_machine/TODO deleted file mode 100644 index 8d5d7063..00000000 --- a/vendor/plugins/acts_as_state_machine/TODO +++ /dev/null @@ -1,11 +0,0 @@ -* Currently invalid events are ignored, create an option so that they can be - ignored or raise an exception. - -* Query for a list of possible next states. - -* Make listing states optional since they can be inferred from the events. - Only required to list a state if you want to define a transition block for it. - -* Real transition actions - -* Default states diff --git a/vendor/plugins/acts_as_state_machine/init.rb b/vendor/plugins/acts_as_state_machine/init.rb deleted file mode 100644 index dd1b4cd2..00000000 --- a/vendor/plugins/acts_as_state_machine/init.rb +++ /dev/null @@ -1,5 +0,0 @@ -require 'acts_as_state_machine' - -ActiveRecord::Base.class_eval do - include ScottBarron::Acts::StateMachine -end diff --git a/vendor/plugins/acts_as_state_machine/lib/acts_as_state_machine.rb b/vendor/plugins/acts_as_state_machine/lib/acts_as_state_machine.rb deleted file mode 100644 index cbbf5f1f..00000000 --- a/vendor/plugins/acts_as_state_machine/lib/acts_as_state_machine.rb +++ /dev/null @@ -1,276 +0,0 @@ -module ScottBarron #:nodoc: - module Acts #:nodoc: - module StateMachine #:nodoc: - class InvalidState < Exception #:nodoc: - end - class NoInitialState < Exception #:nodoc: - end - - def self.included(base) #:nodoc: - base.extend ActMacro - end - - module SupportingClasses - class State - attr_reader :name - - def initialize(name, opts) - @name, @opts = name, opts - end - - def entering(record) - enteract = @opts[:enter] - record.send(:run_transition_action, enteract) if enteract - end - - def entered(record) - afteractions = @opts[:after] - return unless afteractions - Array(afteractions).each do |afteract| - record.send(:run_transition_action, afteract) - end - end - - def exited(record) - exitact = @opts[:exit] - record.send(:run_transition_action, exitact) if exitact - end - end - - class StateTransition - attr_reader :from, :to, :opts - - def initialize(opts) - @from, @to, @guard = opts[:from], opts[:to], opts[:guard] - @opts = opts - end - - def guard(obj) - @guard ? obj.send(:run_transition_action, @guard) : true - end - - def perform(record) - return false unless guard(record) - loopback = record.current_state == to - states = record.class.read_inheritable_attribute(:states) - next_state = states[to] - old_state = states[record.current_state] - - next_state.entering(record) unless loopback - if record.new_record? - record.send(record.class.state_column.to_s + '=', to.to_s) - else - record.update_attribute(record.class.state_column, to.to_s) - end - - next_state.entered(record) unless loopback - old_state.exited(record) unless loopback - true - end - - def ==(obj) - @from == obj.from && @to == obj.to - end - end - - class Event - attr_reader :name - attr_reader :transitions - attr_reader :opts - - def initialize(name, opts, transition_table, &block) - @name = name.to_sym - @transitions = transition_table[@name] = [] - instance_eval(&block) if block - @opts = opts - @opts.freeze - @transitions.freeze - freeze - end - - def next_states(record) - @transitions.select { |t| t.from == record.current_state } - end - - def fire(record) - next_states(record).each do |transition| - break true if transition.perform(record) - end - end - - def transitions(trans_opts) - Array(trans_opts[:from]).each do |s| - @transitions << SupportingClasses::StateTransition.new(trans_opts.merge({:from => s.to_sym})) - end - end - end - end - - module ActMacro - # Configuration options are - # - # * +column+ - specifies the column name to use for keeping the state (default: state) - # * +initial+ - specifies an initial state for newly created objects (required) - def acts_as_state_machine(opts) - self.extend(ClassMethods) - raise NoInitialState unless opts[:initial] - - write_inheritable_attribute :states, {} - write_inheritable_attribute :initial_state, opts[:initial] - write_inheritable_attribute :transition_table, {} - write_inheritable_attribute :event_table, {} - write_inheritable_attribute :state_column, opts[:column] || 'state' - - class_inheritable_reader :initial_state - class_inheritable_reader :state_column - class_inheritable_reader :transition_table - class_inheritable_reader :event_table - - self.send(:include, ScottBarron::Acts::StateMachine::InstanceMethods) - - before_create :set_initial_state - after_create :run_initial_state_actions - end - end - - module InstanceMethods - def set_initial_state #:nodoc: - write_attribute self.class.state_column, self.class.initial_state.to_s - end - - def run_initial_state_actions - initial = self.class.read_inheritable_attribute(:states)[self.class.initial_state.to_sym] - initial.entering(self) - initial.entered(self) - end - - # Returns the current state the object is in, as a Ruby symbol. - def current_state - x = self.send(self.class.state_column) - return x.to_sym if not x.nil? - - # if current state is not yet set, set it - self.set_initial_state - return self.current_state - end - - # Returns what the next state for a given event would be, as a Ruby symbol. - def next_state_for_event(event) - ns = next_states_for_event(event) - ns.empty? ? nil : ns.first.to - end - - def next_states_for_event(event) - self.class.read_inheritable_attribute(:transition_table)[event.to_sym].select do |s| - s.from == current_state - end - end - - def run_transition_action(action) - Symbol === action ? self.method(action).call : action.call(self) - end - private :run_transition_action - end - - module ClassMethods - # Returns an array of all known states. - def states - read_inheritable_attribute(:states).keys - end - - # Define an event. This takes a block which describes all valid transitions - # for this event. - # - # Example: - # - # class Order < ActiveRecord::Base - # acts_as_state_machine :initial => :open - # - # state :open - # state :closed - # - # event :close_order do - # transitions :to => :closed, :from => :open - # end - # end - # - # +transitions+ takes a hash where :to is the state to transition - # to and :from is a state (or Array of states) from which this - # event can be fired. - # - # This creates an instance method used for firing the event. The method - # created is the name of the event followed by an exclamation point (!). - # Example: order.close_order!. - def event(event, opts={}, &block) - tt = read_inheritable_attribute(:transition_table) - - et = read_inheritable_attribute(:event_table) - e = et[event.to_sym] = SupportingClasses::Event.new(event, opts, tt, &block) - define_method("#{event.to_s}!") { e.fire(self) } - end - - # Define a state of the system. +state+ can take an optional Proc object - # which will be executed every time the system transitions into that - # state. The proc will be passed the current object. - # - # Example: - # - # class Order < ActiveRecord::Base - # acts_as_state_machine :initial => :open - # - # state :open - # state :closed, Proc.new { |o| Mailer.send_notice(o) } - # end - def state(name, opts={}) - state = SupportingClasses::State.new(name.to_sym, opts) - read_inheritable_attribute(:states)[name.to_sym] = state - - define_method("#{state.name}?") { current_state == state.name } - end - - # Wraps ActiveRecord::Base.find to conveniently find all records in - # a given state. Options: - # - # * +number+ - This is just :first or :all from ActiveRecord +find+ - # * +state+ - The state to find - # * +args+ - The rest of the args are passed down to ActiveRecord +find+ - def find_in_state(number, state, *args) - with_state_scope state do - find(number, *args) - end - end - - # Wraps ActiveRecord::Base.count to conveniently count all records in - # a given state. Options: - # - # * +state+ - The state to find - # * +args+ - The rest of the args are passed down to ActiveRecord +find+ - def count_in_state(state, *args) - with_state_scope state do - count(*args) - end - end - - # Wraps ActiveRecord::Base.calculate to conveniently calculate all records in - # a given state. Options: - # - # * +state+ - The state to find - # * +args+ - The rest of the args are passed down to ActiveRecord +calculate+ - def calculate_in_state(state, *args) - with_state_scope state do - calculate(*args) - end - end - - protected - def with_state_scope(state) - raise InvalidState unless states.include?(state) - - with_scope :find => {:conditions => ["#{table_name}.#{state_column} = ?", state.to_s]} do - yield if block_given? - end - end - end - end - end -end \ No newline at end of file diff --git a/vendor/plugins/acts_as_state_machine/test/acts_as_state_machine_test.rb b/vendor/plugins/acts_as_state_machine/test/acts_as_state_machine_test.rb deleted file mode 100644 index e1135152..00000000 --- a/vendor/plugins/acts_as_state_machine/test/acts_as_state_machine_test.rb +++ /dev/null @@ -1,224 +0,0 @@ -require File.dirname(__FILE__) + '/test_helper' - -include ScottBarron::Acts::StateMachine - -class ActsAsStateMachineTest < Test::Unit::TestCase - fixtures :conversations - - def test_no_initial_value_raises_exception - assert_raise(NoInitialState) { - Person.acts_as_state_machine({}) - } - end - - def test_initial_state_value - assert_equal :needs_attention, Conversation.initial_state - end - - def test_column_was_set - assert_equal 'state_machine', Conversation.state_column - end - - def test_initial_state - c = Conversation.create - assert_equal :needs_attention, c.current_state - assert c.needs_attention? - end - - def test_states_were_set - [:needs_attention, :read, :closed, :awaiting_response, :junk].each do |s| - assert Conversation.states.include?(s) - end - end - - def test_event_methods_created - c = Conversation.create - %w(new_message! view! reply! close! junk! unjunk!).each do |event| - assert c.respond_to?(event) - end - end - - def test_query_methods_created - c = Conversation.create - %w(needs_attention? read? closed? awaiting_response? junk?).each do |event| - assert c.respond_to?(event) - end - end - - def test_transition_table - tt = Conversation.transition_table - - assert tt[:new_message].include?(SupportingClasses::StateTransition.new(:from => :read, :to => :needs_attention)) - assert tt[:new_message].include?(SupportingClasses::StateTransition.new(:from => :closed, :to => :needs_attention)) - assert tt[:new_message].include?(SupportingClasses::StateTransition.new(:from => :awaiting_response, :to => :needs_attention)) - end - - def test_next_state_for_event - c = Conversation.create - assert_equal :read, c.next_state_for_event(:view) - end - - def test_change_state - c = Conversation.create - c.view! - assert c.read? - end - - def test_can_go_from_read_to_closed_because_guard_passes - c = Conversation.create - c.can_close = true - c.view! - c.reply! - c.close! - assert_equal :closed, c.current_state - end - - def test_cannot_go_from_read_to_closed_because_of_guard - c = Conversation.create - c.can_close = false - c.view! - c.reply! - c.close! - assert_equal :read, c.current_state - end - - def test_ignore_invalid_events - c = Conversation.create - c.view! - c.junk! - - # This is the invalid event - c.new_message! - assert_equal :junk, c.current_state - end - - def test_entry_action_executed - c = Conversation.create - c.read_enter = false - c.view! - assert c.read_enter - end - - def test_after_actions_executed - c = Conversation.create - - c.read_after_first = false - c.read_after_second = false - c.closed_after = false - - c.view! - assert c.read_after_first - assert c.read_after_second - - c.can_close = true - c.close! - - assert c.closed_after - assert_equal :closed, c.current_state - end - - def test_after_actions_not_run_on_loopback_transition - c = Conversation.create - - c.view! - c.read_after_first = false - c.read_after_second = false - c.view! - - assert !c.read_after_first - assert !c.read_after_second - - c.can_close = true - - c.close! - c.closed_after = false - c.close! - - assert !c.closed_after - end - - def test_exit_action_executed - c = Conversation.create - c.read_exit = false - c.view! - c.junk! - assert c.read_exit - end - - def test_entry_and_exit_not_run_on_loopback_transition - c = Conversation.create - c.view! - c.read_enter = false - c.read_exit = false - c.view! - assert !c.read_enter - assert !c.read_exit - end - - def test_entry_and_after_actions_called_for_initial_state - c = Conversation.create - assert c.needs_attention_enter - assert c.needs_attention_after - end - - def test_run_transition_action_is_private - c = Conversation.create - assert_raise(NoMethodError) { c.run_transition_action :foo } - end - - def test_find_all_in_state - cs = Conversation.find_in_state(:all, :read) - - assert_equal 2, cs.size - end - - def test_find_first_in_state - c = Conversation.find_in_state(:first, :read) - - assert_equal conversations(:first).id, c.id - end - - def test_find_all_in_state_with_conditions - cs = Conversation.find_in_state(:all, :read, :conditions => ['subject = ?', conversations(:second).subject]) - - assert_equal 1, cs.size - assert_equal conversations(:second).id, cs.first.id - end - - def test_find_first_in_state_with_conditions - c = Conversation.find_in_state(:first, :read, :conditions => ['subject = ?', conversations(:second).subject]) - assert_equal conversations(:second).id, c.id - end - - def test_count_in_state - cnt0 = Conversation.count(['state_machine = ?', 'read']) - cnt = Conversation.count_in_state(:read) - - assert_equal cnt0, cnt - end - - def test_count_in_state_with_conditions - cnt0 = Conversation.count(['state_machine = ? AND subject = ?', 'read', 'Foo']) - cnt = Conversation.count_in_state(:read, ['subject = ?', 'Foo']) - - assert_equal cnt0, cnt - end - - def test_find_in_invalid_state_raises_exception - assert_raise(InvalidState) { - Conversation.find_in_state(:all, :dead) - } - end - - def test_count_in_invalid_state_raises_exception - assert_raise(InvalidState) { - Conversation.count_in_state(:dead) - } - end - - def test_can_access_events_via_event_table - event = Conversation.event_table[:junk] - assert_equal :junk, event.name - assert_equal "finished", event.opts[:note] - end -end diff --git a/vendor/plugins/acts_as_state_machine/test/database.yml b/vendor/plugins/acts_as_state_machine/test/database.yml deleted file mode 100644 index f012c25c..00000000 --- a/vendor/plugins/acts_as_state_machine/test/database.yml +++ /dev/null @@ -1,18 +0,0 @@ -sqlite: - :adapter: sqlite - :dbfile: state_machine.sqlite.db -sqlite3: - :adapter: sqlite3 - :dbfile: state_machine.sqlite3.db -postgresql: - :adapter: postgresql - :username: postgres - :password: postgres - :database: state_machine_test - :min_messages: ERROR -mysql: - :adapter: mysql - :host: localhost - :username: rails - :password: - :database: state_machine_test \ No newline at end of file diff --git a/vendor/plugins/acts_as_state_machine/test/fixtures/conversation.rb b/vendor/plugins/acts_as_state_machine/test/fixtures/conversation.rb deleted file mode 100644 index 8b414325..00000000 --- a/vendor/plugins/acts_as_state_machine/test/fixtures/conversation.rb +++ /dev/null @@ -1,67 +0,0 @@ -class Conversation < ActiveRecord::Base - attr_writer :can_close - attr_accessor :read_enter, :read_exit, :read_after_first, :read_after_second, - :closed_after, :needs_attention_enter, :needs_attention_after - - acts_as_state_machine :initial => :needs_attention, :column => 'state_machine' - - state :needs_attention, :enter => Proc.new { |o| o.needs_attention_enter = true }, - :after => Proc.new { |o| o.needs_attention_after = true } - - state :read, :enter => :read_enter_action, - :exit => Proc.new { |o| o.read_exit = true }, - :after => [:read_after_first_action, :read_after_second_action] - - state :closed, :after => :closed_after_action - state :awaiting_response - state :junk - - event :new_message do - transitions :to => :needs_attention, :from => [:read, :closed, :awaiting_response] - end - - event :view do - transitions :to => :read, :from => [:needs_attention, :read] - end - - event :reply do - transitions :to => :awaiting_response, :from => [:read, :closed] - end - - event :close do - transitions :to => :closed, :from => [:read, :awaiting_response], :guard => Proc.new {|o| o.can_close?} - transitions :to => :read, :from => [:read, :awaiting_response], :guard => :always_true - end - - event :junk, :note => "finished" do - transitions :to => :junk, :from => [:read, :closed, :awaiting_response] - end - - event :unjunk do - transitions :to => :closed, :from => :junk - end - - def can_close? - @can_close - end - - def read_enter_action - self.read_enter = true - end - - def always_true - true - end - - def read_after_first_action - self.read_after_first = true - end - - def read_after_second_action - self.read_after_second = true - end - - def closed_after_action - self.closed_after = true - end -end diff --git a/vendor/plugins/acts_as_state_machine/test/fixtures/conversations.yml b/vendor/plugins/acts_as_state_machine/test/fixtures/conversations.yml deleted file mode 100644 index 572e0ee1..00000000 --- a/vendor/plugins/acts_as_state_machine/test/fixtures/conversations.yml +++ /dev/null @@ -1,11 +0,0 @@ -first: - id: 1 - state_machine: read - subject: This is a test - closed: false - -second: - id: 2 - state_machine: read - subject: Foo - closed: false diff --git a/vendor/plugins/acts_as_state_machine/test/fixtures/person.rb b/vendor/plugins/acts_as_state_machine/test/fixtures/person.rb deleted file mode 100644 index e64a8262..00000000 --- a/vendor/plugins/acts_as_state_machine/test/fixtures/person.rb +++ /dev/null @@ -1,2 +0,0 @@ -class Person < ActiveRecord::Base -end \ No newline at end of file diff --git a/vendor/plugins/acts_as_state_machine/test/schema.rb b/vendor/plugins/acts_as_state_machine/test/schema.rb deleted file mode 100644 index 50128995..00000000 --- a/vendor/plugins/acts_as_state_machine/test/schema.rb +++ /dev/null @@ -1,11 +0,0 @@ -ActiveRecord::Schema.define(:version => 1) do - create_table :conversations, :force => true do |t| - t.column :state_machine, :string - t.column :subject, :string - t.column :closed, :boolean - end - - create_table :people, :force => true do |t| - t.column :name, :string - end -end diff --git a/vendor/plugins/acts_as_state_machine/test/test_helper.rb b/vendor/plugins/acts_as_state_machine/test/test_helper.rb deleted file mode 100644 index 95331d03..00000000 --- a/vendor/plugins/acts_as_state_machine/test/test_helper.rb +++ /dev/null @@ -1,38 +0,0 @@ -$:.unshift(File.dirname(__FILE__) + '/../lib') -RAILS_ROOT = File.dirname(__FILE__) - -require 'rubygems' -require 'test/unit' -require 'active_record' -require 'active_record/fixtures' -require 'active_support/binding_of_caller' -require 'active_support/breakpoint' -require "#{File.dirname(__FILE__)}/../init" - - -config = YAML::load(IO.read(File.dirname(__FILE__) + '/database.yml')) -ActiveRecord::Base.logger = Logger.new(File.dirname(__FILE__) + "/debug.log") -ActiveRecord::Base.establish_connection(config[ENV['DB'] || 'sqlite']) - -load(File.dirname(__FILE__) + "/schema.rb") if File.exist?(File.dirname(__FILE__) + "/schema.rb") - -Test::Unit::TestCase.fixture_path = File.dirname(__FILE__) + "/fixtures/" -$LOAD_PATH.unshift(Test::Unit::TestCase.fixture_path) - -class Test::Unit::TestCase #:nodoc: - def create_fixtures(*table_names) - if block_given? - Fixtures.create_fixtures(Test::Unit::TestCase.fixture_path, table_names) { yield } - else - Fixtures.create_fixtures(Test::Unit::TestCase.fixture_path, table_names) - end - end - - # Turn off transactional fixtures if you're working with MyISAM tables in MySQL - self.use_transactional_fixtures = true - - # Instantiated fixtures are slow, but give you @david where you otherwise would need people(:david) - self.use_instantiated_fixtures = false - - # Add more helper methods to be used by all tests here... -end \ No newline at end of file From fdbd2a6391848c8131444bffc483c137fa951254 Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Fri, 27 May 2011 03:44:32 +0800 Subject: [PATCH 2/5] fixing issue with wrong initial value of state column --- db/migrate/20110526192008_adapt_to_new_aasm.rb | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 db/migrate/20110526192008_adapt_to_new_aasm.rb diff --git a/db/migrate/20110526192008_adapt_to_new_aasm.rb b/db/migrate/20110526192008_adapt_to_new_aasm.rb new file mode 100644 index 00000000..98212a57 --- /dev/null +++ b/db/migrate/20110526192008_adapt_to_new_aasm.rb @@ -0,0 +1,11 @@ +class AdaptToNewAasm < ActiveRecord::Migration + def self.up + change_column :todos, :state, :string, :limit => 20, :default => "", :null => false + change_column :projects, :state, :string, :limit => 20, :default => "", :null => false + end + + def self.down + change_column :todos, :state, :string, :limit => 20, :default => "immediate", :null => false + change_column :projects, :state, :string, :limit => 20, :default => "active", :null => false + end +end From 1cf5967eb5ee85e30ce7fbc79e8c39778ae840e5 Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Thu, 2 Jun 2011 03:05:05 +0800 Subject: [PATCH 3/5] adding missing table --- db/migrate/20110526192008_adapt_to_new_aasm.rb | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/db/migrate/20110526192008_adapt_to_new_aasm.rb b/db/migrate/20110526192008_adapt_to_new_aasm.rb index 98212a57..787576bc 100644 --- a/db/migrate/20110526192008_adapt_to_new_aasm.rb +++ b/db/migrate/20110526192008_adapt_to_new_aasm.rb @@ -1,11 +1,13 @@ class AdaptToNewAasm < ActiveRecord::Migration def self.up - change_column :todos, :state, :string, :limit => 20, :default => "", :null => false - change_column :projects, :state, :string, :limit => 20, :default => "", :null => false + change_column :todos, :state, :string, :limit => 20, :default => "", :null => false + change_column :projects, :state, :string, :limit => 20, :default => "", :null => false + change_column :recurring_todos, :state, :string, :limit => 20, :default => "", :null => false end def self.down - change_column :todos, :state, :string, :limit => 20, :default => "immediate", :null => false - change_column :projects, :state, :string, :limit => 20, :default => "active", :null => false + change_column :todos, :state, :string, :limit => 20, :default => "immediate", :null => false + change_column :projects, :state, :string, :limit => 20, :default => "active", :null => false + change_column :recurring_todos, :state, :string, :limit => 20, :default => "active", :null => false end end From 056dbf08a7f7b0a6a654c6258d54b6199ed6b71a Mon Sep 17 00:00:00 2001 From: Reinier Balt Date: Fri, 10 Jun 2011 14:28:42 +0200 Subject: [PATCH 4/5] remove vendored gem and fix state model. Some old hacks did not work anymore on the newer aasm. reverted the hacks and fixed some tests --- app/models/project.rb | 10 +- app/models/recurring_todo.rb | 9 +- app/models/todo.rb | 20 +- config/environment.rb | 1 + test/fixtures/recurring_todos.yml | 2 +- test/functional/todos_controller_test.rb | 1 - test/unit/project_test.rb | 1 - test/unit/recurring_todo_test.rb | 31 +- vendor/gems/aasm-2.2.0/.document | 5 - vendor/gems/aasm-2.2.0/.gitignore | 7 - vendor/gems/aasm-2.2.0/README.rdoc | 137 ------ vendor/gems/aasm-2.2.0/Rakefile | 108 ---- vendor/gems/aasm-2.2.0/VERSION | 1 - vendor/gems/aasm-2.2.0/aasm.gemspec | 94 ---- vendor/gems/aasm-2.2.0/lib/aasm.rb | 9 - vendor/gems/aasm-2.2.0/lib/aasm/aasm.rb | 196 -------- vendor/gems/aasm-2.2.0/lib/aasm/event.rb | 109 ----- .../gems/aasm-2.2.0/lib/aasm/persistence.rb | 14 - .../persistence/active_record_persistence.rb | 259 ---------- vendor/gems/aasm-2.2.0/lib/aasm/state.rb | 53 -- .../gems/aasm-2.2.0/lib/aasm/state_machine.rb | 32 -- .../aasm-2.2.0/lib/aasm/state_transition.rb | 46 -- .../aasm-2.2.0/lib/aasm/supporting_classes.rb | 6 - .../spec/functional/conversation.rb | 49 -- .../spec/functional/conversation_spec.rb | 8 - vendor/gems/aasm-2.2.0/spec/spec_helper.rb | 11 - vendor/gems/aasm-2.2.0/spec/unit/aasm_spec.rb | 462 ------------------ .../unit/active_record_persistence_spec.rb | 255 ---------- .../spec/unit/before_after_callbacks_spec.rb | 79 --- .../gems/aasm-2.2.0/spec/unit/event_spec.rb | 126 ----- .../gems/aasm-2.2.0/spec/unit/state_spec.rb | 85 ---- .../spec/unit/state_transition_spec.rb | 84 ---- .../test/functional/auth_machine_test.rb | 120 ----- vendor/gems/aasm-2.2.0/test/test_helper.rb | 33 -- .../gems/aasm-2.2.0/test/unit/event_test.rb | 54 -- .../gems/aasm-2.2.0/test/unit/state_test.rb | 69 --- .../test/unit/state_transition_test.rb | 75 --- 37 files changed, 43 insertions(+), 2618 deletions(-) delete mode 100644 vendor/gems/aasm-2.2.0/.document delete mode 100644 vendor/gems/aasm-2.2.0/.gitignore delete mode 100644 vendor/gems/aasm-2.2.0/README.rdoc delete mode 100644 vendor/gems/aasm-2.2.0/Rakefile delete mode 100644 vendor/gems/aasm-2.2.0/VERSION delete mode 100644 vendor/gems/aasm-2.2.0/aasm.gemspec delete mode 100644 vendor/gems/aasm-2.2.0/lib/aasm.rb delete mode 100644 vendor/gems/aasm-2.2.0/lib/aasm/aasm.rb delete mode 100644 vendor/gems/aasm-2.2.0/lib/aasm/event.rb delete mode 100644 vendor/gems/aasm-2.2.0/lib/aasm/persistence.rb delete mode 100644 vendor/gems/aasm-2.2.0/lib/aasm/persistence/active_record_persistence.rb delete mode 100644 vendor/gems/aasm-2.2.0/lib/aasm/state.rb delete mode 100644 vendor/gems/aasm-2.2.0/lib/aasm/state_machine.rb delete mode 100644 vendor/gems/aasm-2.2.0/lib/aasm/state_transition.rb delete mode 100644 vendor/gems/aasm-2.2.0/lib/aasm/supporting_classes.rb delete mode 100644 vendor/gems/aasm-2.2.0/spec/functional/conversation.rb delete mode 100644 vendor/gems/aasm-2.2.0/spec/functional/conversation_spec.rb delete mode 100644 vendor/gems/aasm-2.2.0/spec/spec_helper.rb delete mode 100644 vendor/gems/aasm-2.2.0/spec/unit/aasm_spec.rb delete mode 100644 vendor/gems/aasm-2.2.0/spec/unit/active_record_persistence_spec.rb delete mode 100644 vendor/gems/aasm-2.2.0/spec/unit/before_after_callbacks_spec.rb delete mode 100644 vendor/gems/aasm-2.2.0/spec/unit/event_spec.rb delete mode 100644 vendor/gems/aasm-2.2.0/spec/unit/state_spec.rb delete mode 100644 vendor/gems/aasm-2.2.0/spec/unit/state_transition_spec.rb delete mode 100644 vendor/gems/aasm-2.2.0/test/functional/auth_machine_test.rb delete mode 100644 vendor/gems/aasm-2.2.0/test/test_helper.rb delete mode 100644 vendor/gems/aasm-2.2.0/test/unit/event_test.rb delete mode 100644 vendor/gems/aasm-2.2.0/test/unit/state_test.rb delete mode 100644 vendor/gems/aasm-2.2.0/test/unit/state_transition_test.rb diff --git a/app/models/project.rb b/app/models/project.rb index 9c29c01c..13819cf2 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -50,7 +50,7 @@ class Project < ActiveRecord::Base aasm_state :active aasm_state :hidden, :enter => :hide_todos, :exit => :unhide_todos - aasm_state :completed, :enter => Proc.new { |p| p.completed_at = Time.zone.now }, :exit => Proc.new { |p| p.completed_at = nil } + aasm_state :completed, :enter => :set_completed_at_date, :exit => :clear_completed_at_date aasm_event :activate do transitions :to => :active, :from => [:active, :hidden, :completed] @@ -96,6 +96,14 @@ class Project < ActiveRecord::Base end end + def set_completed_at_date + self.completed_at = Time.zone.now + end + + def clear_completed_at_date + self.completed_at = nil + end + def note_count cached_note_count || notes.count end diff --git a/app/models/recurring_todo.rb b/app/models/recurring_todo.rb index 04066ffd..e46ad36e 100644 --- a/app/models/recurring_todo.rb +++ b/app/models/recurring_todo.rb @@ -15,10 +15,7 @@ class RecurringTodo < ActiveRecord::Base aasm_column :state aasm_initial_state :active - aasm_state :active, :enter => Proc.new { |t| - t[:show_from], t.completed_at = nil, nil - t.occurences_count = 0 - } + aasm_state :active, :enter => Proc.new { |t| t.occurences_count = 0 } aasm_state :completed, :enter => Proc.new { |t| t.completed_at = Time.zone.now }, :exit => Proc.new { |t| t.completed_at = nil } aasm_event :complete do @@ -43,8 +40,7 @@ class RecurringTodo < ActiveRecord::Base validate :set_recurrence_on_validations def period_specific_validations - periods = %W[daily weekly monthly yearly] - if periods.include?(recurring_period) + if %W[daily weekly monthly yearly].include?(recurring_period) self.send("validate_#{recurring_period}") else errors.add(:recurring_period, "is an unknown recurrence pattern: '#{self.recurring_period}'") @@ -96,7 +92,6 @@ class RecurringTodo < ActiveRecord::Base end end - def starts_and_ends_on_validations errors.add_to_base("The start date needs to be filled in") if start_from.nil? || start_from.blank? case self.ends_on diff --git a/app/models/todo.rb b/app/models/todo.rb index 601f666f..58dcc30a 100644 --- a/app/models/todo.rb +++ b/app/models/todo.rb @@ -51,11 +51,11 @@ class Todo < ActiveRecord::Base # when entering active state, also remove completed_at date. Looks like :exit # of state completed is not run, see #679 - aasm_state :active, :enter => Proc.new { |t| t[:show_from], t.completed_at = nil, nil } + aasm_state :active aasm_state :project_hidden, :enter => Proc.new { |t| t.completed_at = Time.zone.now }, :exit => Proc.new { |t| t.completed_at = nil } - aasm_state :completed - aasm_state :deferred - aasm_state :pending + aasm_state :completed, :exit => Proc.new { |t| t.completed_at = nil } + aasm_state :deferred, :exit => Proc.new { |t| t[:show_from] = nil } + aasm_state :pending aasm_event :defer do transitions :to => :deferred, :from => [:active] @@ -99,7 +99,7 @@ class Todo < ActiveRecord::Base @predecessor_array = nil # Used for deferred save of predecessors @removed_predecessors = nil end - + def no_uncompleted_predecessors_or_deferral? return (show_from.blank? or Time.zone.now > show_from and uncompleted_predecessors.empty?) end @@ -155,10 +155,8 @@ class Todo < ActiveRecord::Base end def remove_predecessor(predecessor) - puts "@@@ before delete" # remove predecessor and activate myself self.predecessors.delete(predecessor) - puts "@@@ before activate" self.activate! end @@ -216,10 +214,14 @@ class Todo < ActiveRecord::Base def show_from=(date) # parse Date objects into the proper timezone date = user.at_midnight(date) if (date.is_a? Date) + + # show_from needs to be set before state_change because of "bug" in aasm. + # If show_From is not set, the todo will not validate and thus aasm will not save + # (see http://stackoverflow.com/questions/682920/persisting-the-state-column-on-transition-using-rubyist-aasm-acts-as-state-machi) + self[:show_from] = date + activate! if deferred? && date.blank? defer! if active? && !date.blank? && date > user.date - - self[:show_from] = date end alias_method :original_project, :project diff --git a/config/environment.rb b/config/environment.rb index a16ce4c8..bb4e50fc 100644 --- a/config/environment.rb +++ b/config/environment.rb @@ -29,6 +29,7 @@ Rails::Initializer.run do |config| config.gem 'rack', :version => '1.1.0' config.gem 'will_paginate', :version => '~> 2.3.15' config.gem 'has_many_polymorphs' + config.gem 'aasm', :version => '2.2.0' config.action_controller.use_accept_header = true diff --git a/test/fixtures/recurring_todos.yml b/test/fixtures/recurring_todos.yml index a9bfb18c..84872204 100644 --- a/test/fixtures/recurring_todos.yml +++ b/test/fixtures/recurring_todos.yml @@ -41,7 +41,7 @@ call_bill_gates_every_day: show_from_delta: ~ recurring_period: daily recurrence_selector: ~ - show_always: 0 + show_always: 1 every_other1: 1 every_other2: ~ every_other3: ~ diff --git a/test/functional/todos_controller_test.rb b/test/functional/todos_controller_test.rb index 52543c8b..d080bfc5 100644 --- a/test/functional/todos_controller_test.rb +++ b/test/functional/todos_controller_test.rb @@ -62,7 +62,6 @@ class TodosControllerTest < ActionController::TestCase assert_equal 2, t.tags.count end - def test_not_done_counts_after_hiding_project p = Project.find(1) p.hide! diff --git a/test/unit/project_test.rb b/test/unit/project_test.rb index a9a95679..76f61cec 100644 --- a/test/unit/project_test.rb +++ b/test/unit/project_test.rb @@ -160,7 +160,6 @@ class ProjectTest < ActiveSupport::TestCase assert_equal 1, @timemachine.deferred_todos.count assert_equal 0, @moremoney.deferred_todos.count @moremoney.todos[0].show_from = next_week - @moremoney.todos[0].save assert_equal :deferred, @moremoney.todos[0].aasm_current_state assert_equal 1, @moremoney.deferred_todos.count end diff --git a/test/unit/recurring_todo_test.rb b/test/unit/recurring_todo_test.rb index 60b96915..b82bc59e 100644 --- a/test/unit/recurring_todo_test.rb +++ b/test/unit/recurring_todo_test.rb @@ -275,25 +275,31 @@ class RecurringTodoTest < ActiveSupport::TestCase end def test_toggle_completion - t = @yearly - assert_equal :active, t.aasm_current_state - t.toggle_completion! - assert_equal :completed, t.aasm_current_state - t.toggle_completion! - assert_equal :active, t.aasm_current_state + assert @yearly.active? + assert @yearly.toggle_completion! + assert @yearly.completed? + + # entering completed state should set completed_at + assert !@yearly.completed_at.nil? + + assert @yearly.toggle_completion! + assert @yearly.active? + + # re-entering active state should clear completed_at + assert @yearly.completed_at.nil? end def test_starred @yearly.tag_with("1, 2, starred") @yearly.tags.reload - assert_equal true, @yearly.starred? - assert_equal false, @weekly_every_day.starred? + assert @yearly.starred? + assert !@weekly_every_day.starred? @yearly.toggle_star! - assert_equal false, @yearly.starred? + assert !@yearly.starred? @yearly.toggle_star! - assert_equal true, @yearly.starred? + assert @yearly.starred? end def test_occurence_count @@ -307,8 +313,9 @@ class RecurringTodoTest < ActiveSupport::TestCase # after completion, when you reactivate the recurring todo, the occurences # count should be reset assert_equal 2, @every_day.occurences_count - @every_day.toggle_completion! - @every_day.toggle_completion! + assert @every_day.toggle_completion! + assert @every_day.toggle_completion! + assert_equal true, @every_day.has_next_todo(@in_three_days) assert_equal 0, @every_day.occurences_count end diff --git a/vendor/gems/aasm-2.2.0/.document b/vendor/gems/aasm-2.2.0/.document deleted file mode 100644 index ecf36731..00000000 --- a/vendor/gems/aasm-2.2.0/.document +++ /dev/null @@ -1,5 +0,0 @@ -README.rdoc -lib/**/*.rb -bin/* -features/**/*.feature -LICENSE diff --git a/vendor/gems/aasm-2.2.0/.gitignore b/vendor/gems/aasm-2.2.0/.gitignore deleted file mode 100644 index 4e80aa16..00000000 --- a/vendor/gems/aasm-2.2.0/.gitignore +++ /dev/null @@ -1,7 +0,0 @@ -*.sw? -*~ -.DS_Store -.idea -coverage -pkg -rdoc diff --git a/vendor/gems/aasm-2.2.0/README.rdoc b/vendor/gems/aasm-2.2.0/README.rdoc deleted file mode 100644 index 9504eaee..00000000 --- a/vendor/gems/aasm-2.2.0/README.rdoc +++ /dev/null @@ -1,137 +0,0 @@ -= Alternatives - -If you are looking for an alternative to AASM, I would highly suggest transitions: http://github.com/qoobaa/transitions - -= AASM - Ruby state machines - -This package contains AASM, a library for adding finite state machines to Ruby classes. - -AASM started as the acts_as_state_machine plugin but has evolved into a more generic library that no longer targets only ActiveRecord models. - -AASM has the following features: - -* States -* Machines -* Events -* Transitions - -== New Callbacks - -The callback chain & order on a successful event looks like: - - oldstate:exit* - event:before - __find transition, if possible__ - transition:on_transition* - oldstate:before_exit - newstate:before_enter - newstate:enter* - __update state__ - event:success* - oldstate:after_exit - newstate:after_enter - event:after - obj:aasm_event_fired* - - (*) marks old callbacks - - -== Download - -The latest AASM can currently be pulled from the git repository on github. - -* http://github.com/rubyist/aasm/tree/master - - -== Installation - -=== From gemcutter - - % sudo gem install gemcutter - % sudo gem tumble - % sudo gem install aasm - -=== From GitHub hosted gems (only older releases are available) - - % sudo gem sources -a http://gems.github.com # (you only need to do this once) - % sudo gem install rubyist-aasm - -=== Building your own gems - - % rake gemspec - % rake build - % sudo gem install pkg/aasm-2.1.gem - - -== Simple Example - -Here's a quick example highlighting some of the features. - - class Conversation - include AASM - - aasm_column :current_state # defaults to aasm_state - - aasm_initial_state :unread - - aasm_state :unread - aasm_state :read - aasm_state :closed - - - aasm_event :view do - transitions :to => :read, :from => [:unread] - end - - aasm_event :close do - transitions :to => :closed, :from => [:read, :unread] - end - end - -== A Slightly More Complex Example - -This example uses a few of the more complex features available. - - class Relationship - include AASM - - aasm_column :status - - aasm_initial_state Proc.new { |relationship| relationship.strictly_for_fun? ? :intimate : :dating } - - aasm_state :dating, :enter => :make_happy, :exit => :make_depressed - aasm_state :intimate, :enter => :make_very_happy, :exit => :never_speak_again - aasm_state :married, :enter => :give_up_intimacy, :exit => :buy_exotic_car_and_wear_a_combover - - aasm_event :get_intimate do - transitions :to => :intimate, :from => [:dating], :guard => :drunk? - end - - aasm_event :get_married do - transitions :to => :married, :from => [:dating, :intimate], :guard => :willing_to_give_up_manhood? - end - - def strictly_for_fun?; end - def drunk?; end - def willing_to_give_up_manhood?; end - def make_happy; end - def make_depressed; end - def make_very_happy; end - def never_speak_again; end - def give_up_intimacy; end - def buy_exotic_car_and_wear_a_combover; end - end - -= Other Stuff - -Author:: Scott Barron -License:: Original code Copyright 2006, 2007, 2008 by Scott Barron. - Released under an MIT-style license. See the LICENSE file - included in the distribution. - -== Warranty - -This software is provided "as is" and without any express or -implied warranties, including, without limitation, the implied -warranties of merchantibility and fitness for a particular -purpose. diff --git a/vendor/gems/aasm-2.2.0/Rakefile b/vendor/gems/aasm-2.2.0/Rakefile deleted file mode 100644 index e6f8d173..00000000 --- a/vendor/gems/aasm-2.2.0/Rakefile +++ /dev/null @@ -1,108 +0,0 @@ -require 'rubygems' -require 'rake' - -begin - require 'jeweler' - Jeweler::Tasks.new do |gem| - gem.name = "aasm" - gem.summary = %Q{State machine mixin for Ruby objects} - gem.description = %Q{AASM is a continuation of the acts as state machine rails plugin, built for plain Ruby objects.} - gem.homepage = "http://rubyist.github.com/aasm/" - gem.authors = ["Scott Barron", "Scott Petersen", "Travis Tilley"] - gem.email = "scott@elitists.net, ttilley@gmail.com" - gem.add_development_dependency "rspec" - gem.add_development_dependency "shoulda" - gem.add_development_dependency 'sdoc' - # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings - end - Jeweler::GemcutterTasks.new -rescue LoadError - puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler" -end - -require 'spec/rake/spectask' -require 'rake/testtask' - -Rake::TestTask.new(:test) do |test| - test.libs << 'lib' << 'test' - test.pattern = 'test/**/*_test.rb' - test.verbose = true -end - -begin - require 'rcov/rcovtask' - Rcov::RcovTask.new(:rcov_shoulda) do |test| - test.libs << 'test' - test.pattern = 'test/**/*_test.rb' - test.verbose = true - end -rescue LoadError - task :rcov do - abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov" - end -end - -Spec::Rake::SpecTask.new(:spec) do |spec| - spec.libs << 'lib' << 'spec' - spec.spec_files = FileList['spec/**/*_spec.rb'] - spec.spec_opts = ['-cfs'] -end - -Spec::Rake::SpecTask.new(:rcov_rspec) do |spec| - spec.libs << 'lib' << 'spec' - spec.pattern = 'spec/**/*_spec.rb' - spec.rcov = true -end - -task :test => :check_dependencies -task :spec => :check_dependencies - -begin - require 'reek/rake_task' - Reek::RakeTask.new do |t| - t.fail_on_error = true - t.verbose = false - t.source_files = 'lib/**/*.rb' - end -rescue LoadError - task :reek do - abort "Reek is not available. In order to run reek, you must: sudo gem install reek" - end -end - -begin - require 'roodi' - require 'roodi_task' - RoodiTask.new do |t| - t.verbose = false - end -rescue LoadError - task :roodi do - abort "Roodi is not available. In order to run roodi, you must: sudo gem install roodi" - end -end - -task :default => :test - -begin - require 'rake/rdoctask' - require 'sdoc' - Rake::RDocTask.new do |rdoc| - if File.exist?('VERSION') - version = File.read('VERSION') - else - version = "" - end - - rdoc.rdoc_dir = 'rdoc' - rdoc.title = "aasm #{version}" - rdoc.rdoc_files.include('README*') - rdoc.rdoc_files.include('lib/**/*.rb') - - rdoc.options << '--fmt' << 'shtml' - rdoc.template = 'direct' - end -rescue LoadError - puts "aasm makes use of the sdoc gem. Install it with: sudo gem install sdoc" -end - diff --git a/vendor/gems/aasm-2.2.0/VERSION b/vendor/gems/aasm-2.2.0/VERSION deleted file mode 100644 index ccbccc3d..00000000 --- a/vendor/gems/aasm-2.2.0/VERSION +++ /dev/null @@ -1 +0,0 @@ -2.2.0 diff --git a/vendor/gems/aasm-2.2.0/aasm.gemspec b/vendor/gems/aasm-2.2.0/aasm.gemspec deleted file mode 100644 index 10947796..00000000 --- a/vendor/gems/aasm-2.2.0/aasm.gemspec +++ /dev/null @@ -1,94 +0,0 @@ -# Generated by jeweler -# DO NOT EDIT THIS FILE DIRECTLY -# Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command -# -*- encoding: utf-8 -*- - -Gem::Specification.new do |s| - s.name = %q{aasm} - s.version = "2.2.0" - - s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version= - s.authors = ["Scott Barron", "Scott Petersen", "Travis Tilley"] - s.date = %q{2010-09-13} - s.description = %q{AASM is a continuation of the acts as state machine rails plugin, built for plain Ruby objects.} - s.email = %q{scott@elitists.net, ttilley@gmail.com} - s.extra_rdoc_files = [ - "LICENSE", - "README.rdoc" - ] - s.files = [ - ".document", - ".gitignore", - "LICENSE", - "README.rdoc", - "Rakefile", - "VERSION", - "aasm.gemspec", - "lib/aasm.rb", - "lib/aasm/aasm.rb", - "lib/aasm/event.rb", - "lib/aasm/persistence.rb", - "lib/aasm/persistence/active_record_persistence.rb", - "lib/aasm/state.rb", - "lib/aasm/state_machine.rb", - "lib/aasm/state_transition.rb", - "lib/aasm/supporting_classes.rb", - "spec/functional/conversation.rb", - "spec/functional/conversation_spec.rb", - "spec/spec_helper.rb", - "spec/unit/aasm_spec.rb", - "spec/unit/active_record_persistence_spec.rb", - "spec/unit/before_after_callbacks_spec.rb", - "spec/unit/event_spec.rb", - "spec/unit/state_spec.rb", - "spec/unit/state_transition_spec.rb", - "test/functional/auth_machine_test.rb", - "test/test_helper.rb", - "test/unit/aasm_test.rb", - "test/unit/event_test.rb", - "test/unit/state_test.rb", - "test/unit/state_transition_test.rb" - ] - s.homepage = %q{http://rubyist.github.com/aasm/} - s.rdoc_options = ["--charset=UTF-8"] - s.require_paths = ["lib"] - s.rubygems_version = %q{1.3.7} - s.summary = %q{State machine mixin for Ruby objects} - s.test_files = [ - "spec/functional/conversation.rb", - "spec/functional/conversation_spec.rb", - "spec/spec_helper.rb", - "spec/unit/aasm_spec.rb", - "spec/unit/active_record_persistence_spec.rb", - "spec/unit/before_after_callbacks_spec.rb", - "spec/unit/event_spec.rb", - "spec/unit/state_spec.rb", - "spec/unit/state_transition_spec.rb", - "test/functional/auth_machine_test.rb", - "test/test_helper.rb", - "test/unit/aasm_test.rb", - "test/unit/event_test.rb", - "test/unit/state_test.rb", - "test/unit/state_transition_test.rb" - ] - - if s.respond_to? :specification_version then - current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION - s.specification_version = 3 - - if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then - s.add_development_dependency(%q, [">= 0"]) - s.add_development_dependency(%q, [">= 0"]) - s.add_development_dependency(%q, [">= 0"]) - else - s.add_dependency(%q, [">= 0"]) - s.add_dependency(%q, [">= 0"]) - s.add_dependency(%q, [">= 0"]) - end - else - s.add_dependency(%q, [">= 0"]) - s.add_dependency(%q, [">= 0"]) - s.add_dependency(%q, [">= 0"]) - end -end - diff --git a/vendor/gems/aasm-2.2.0/lib/aasm.rb b/vendor/gems/aasm-2.2.0/lib/aasm.rb deleted file mode 100644 index 659d1d1d..00000000 --- a/vendor/gems/aasm-2.2.0/lib/aasm.rb +++ /dev/null @@ -1,9 +0,0 @@ -module AASM -end - -require 'ostruct' - -require File.join(File.dirname(__FILE__), 'aasm', 'supporting_classes') -require File.join(File.dirname(__FILE__), 'aasm', 'state_machine') -require File.join(File.dirname(__FILE__), 'aasm', 'persistence') -require File.join(File.dirname(__FILE__), 'aasm', 'aasm') diff --git a/vendor/gems/aasm-2.2.0/lib/aasm/aasm.rb b/vendor/gems/aasm-2.2.0/lib/aasm/aasm.rb deleted file mode 100644 index b08c5223..00000000 --- a/vendor/gems/aasm-2.2.0/lib/aasm/aasm.rb +++ /dev/null @@ -1,196 +0,0 @@ -module AASM - class InvalidTransition < RuntimeError - end - - class UndefinedState < RuntimeError - end - - def self.included(base) #:nodoc: - base.extend AASM::ClassMethods - AASM::Persistence.set_persistence(base) - unless AASM::StateMachine[base] - AASM::StateMachine[base] = AASM::StateMachine.new('') - end - super - end - - module ClassMethods - def inherited(klass) - AASM::StateMachine[klass] = AASM::StateMachine[self].clone - super - end - - def aasm_initial_state(set_state=nil) - if set_state - AASM::StateMachine[self].initial_state = set_state - else - AASM::StateMachine[self].initial_state - end - end - - def aasm_initial_state=(state) - AASM::StateMachine[self].initial_state = state - end - - def aasm_state(name, options={}) - sm = AASM::StateMachine[self] - sm.create_state(name, options) - sm.initial_state = name unless sm.initial_state - - define_method("#{name.to_s}?") do - aasm_current_state == name - end - end - - def aasm_event(name, options = {}, &block) - sm = AASM::StateMachine[self] - - unless sm.events.has_key?(name) - sm.events[name] = AASM::SupportingClasses::Event.new(name, options, &block) - end - - define_method("#{name.to_s}!") do |*args| - aasm_fire_event(name, true, *args) - end - - define_method("#{name.to_s}") do |*args| - aasm_fire_event(name, false, *args) - end - end - - def aasm_states - AASM::StateMachine[self].states - end - - def aasm_events - AASM::StateMachine[self].events - end - - def aasm_states_for_select - AASM::StateMachine[self].states.map { |state| state.for_select } - end - - end - - # Instance methods - def aasm_current_state - return @aasm_current_state if @aasm_current_state - - if self.respond_to?(:aasm_read_state) || self.private_methods.include?('aasm_read_state') - @aasm_current_state = aasm_read_state - end - return @aasm_current_state if @aasm_current_state - - aasm_enter_initial_state - end - - def aasm_enter_initial_state - state_name = aasm_determine_state_name(self.class.aasm_initial_state) - state = aasm_state_object_for_state(state_name) - - state.call_action(:before_enter, self) - state.call_action(:enter, self) - self.aasm_current_state = state_name - state.call_action(:after_enter, self) - - state_name - end - - def aasm_events_for_current_state - aasm_events_for_state(aasm_current_state) - end - - def aasm_events_for_state(state) - events = self.class.aasm_events.values.select {|event| event.transitions_from_state?(state) } - events.map {|event| event.name} - end - - private - - def set_aasm_current_state_with_persistence(state) - save_success = true - if self.respond_to?(:aasm_write_state) || self.private_methods.include?('aasm_write_state') - save_success = aasm_write_state(state) - end - self.aasm_current_state = state if save_success - - save_success - end - - def aasm_current_state=(state) - if self.respond_to?(:aasm_write_state_without_persistence) || self.private_methods.include?('aasm_write_state_without_persistence') - aasm_write_state_without_persistence(state) - end - @aasm_current_state = state - end - - def aasm_determine_state_name(state) - case state - when Symbol, String - state - when Proc - state.call(self) - else - raise NotImplementedError, "Unrecognized state-type given. Expected Symbol, String, or Proc." - end - end - - def aasm_state_object_for_state(name) - obj = self.class.aasm_states.find {|s| s == name} - raise AASM::UndefinedState, "State :#{name} doesn't exist" if obj.nil? - obj - end - - def aasm_fire_event(name, persist, *args) - event = self.class.aasm_events[name] - begin - old_state = aasm_state_object_for_state(aasm_current_state) - - - old_state.call_action(:exit, self) - - # new event before callback - event.call_action(:before, self) - - new_state_name = event.fire(self, *args) - - unless new_state_name.nil? - new_state = aasm_state_object_for_state(new_state_name) - - # new before_ callbacks - old_state.call_action(:before_exit, self) - new_state.call_action(:before_enter, self) - - new_state.call_action(:enter, self) - - persist_successful = true - if persist - persist_successful = set_aasm_current_state_with_persistence(new_state_name) - event.execute_success_callback(self) if persist_successful - else - self.aasm_current_state = new_state_name - end - - if persist_successful - old_state.call_action(:after_exit, self) - new_state.call_action(:after_enter, self) - event.call_action(:after, self) - - self.aasm_event_fired(name, old_state.name, self.aasm_current_state) if self.respond_to?(:aasm_event_fired) - else - self.aasm_event_failed(name, old_state.name) if self.respond_to?(:aasm_event_failed) - end - - persist_successful - else - if self.respond_to?(:aasm_event_failed) - self.aasm_event_failed(name, old_state.name) - end - - false - end - rescue StandardError => e - event.execute_error_callback(self, e) - end - end -end diff --git a/vendor/gems/aasm-2.2.0/lib/aasm/event.rb b/vendor/gems/aasm-2.2.0/lib/aasm/event.rb deleted file mode 100644 index 22133ae3..00000000 --- a/vendor/gems/aasm-2.2.0/lib/aasm/event.rb +++ /dev/null @@ -1,109 +0,0 @@ -class AASM::SupportingClasses::Event - attr_reader :name, :success, :options - - def initialize(name, options = {}, &block) - @name = name - @transitions = [] - update(options, &block) - end - - def fire(obj, to_state=nil, *args) - transitions = @transitions.select { |t| t.from == obj.aasm_current_state } - raise AASM::InvalidTransition, "Event '#{name}' cannot transition from '#{obj.aasm_current_state}'" if transitions.size == 0 - - next_state = nil - transitions.each do |transition| - next if to_state and !Array(transition.to).include?(to_state) - if transition.perform(obj) - next_state = to_state || Array(transition.to).first - transition.execute(obj, *args) - break - end - end - next_state - end - - def transitions_from_state?(state) - @transitions.any? { |t| t.from == state } - end - - def transitions_from_state(state) - @transitions.select { |t| t.from == state } - end - - def all_transitions - @transitions - end - - def call_action(action, record) - action = @options[action] - action.is_a?(Array) ? - action.each {|a| _call_action(a, record)} : - _call_action(action, record) - end - - def ==(event) - if event.is_a? Symbol - name == event - else - name == event.name - end - end - - def update(options = {}, &block) - if options.key?(:success) then - @success = options[:success] - end - if options.key?(:error) then - @error = options[:error] - end - if block then - instance_eval(&block) - end - @options = options - self - end - - def execute_success_callback(obj, success = nil) - callback = success || @success - case(callback) - when String, Symbol - obj.send(callback) - when Proc - callback.call(obj) - when Array - callback.each{|meth|self.execute_success_callback(obj, meth)} - end - end - - def execute_error_callback(obj, error, error_callback=nil) - callback = error_callback || @error - raise error unless callback - case(callback) - when String, Symbol - raise NoMethodError unless obj.respond_to?(callback.to_sym) - obj.send(callback, error) - when Proc - callback.call(obj, error) - when Array - callback.each{|meth|self.execute_error_callback(obj, error, meth)} - end - end - - private - - def _call_action(action, record) - case action - when Symbol, String - record.send(action) - when Proc - action.call(record) - end - end - - def transitions(trans_opts) - Array(trans_opts[:from]).each do |s| - @transitions << AASM::SupportingClasses::StateTransition.new(trans_opts.merge({:from => s.to_sym})) - end - end -end diff --git a/vendor/gems/aasm-2.2.0/lib/aasm/persistence.rb b/vendor/gems/aasm-2.2.0/lib/aasm/persistence.rb deleted file mode 100644 index 5704d802..00000000 --- a/vendor/gems/aasm-2.2.0/lib/aasm/persistence.rb +++ /dev/null @@ -1,14 +0,0 @@ -module AASM::Persistence - - # Checks to see this class or any of it's superclasses inherit from - # ActiveRecord::Base and if so includes ActiveRecordPersistence - def self.set_persistence(base) - # Use a fancier auto-loading thingy, perhaps. When there are more persistence engines. - hierarchy = base.ancestors.map {|klass| klass.to_s} - - if hierarchy.include?("ActiveRecord::Base") - require File.join(File.dirname(__FILE__), 'persistence', 'active_record_persistence') - base.send(:include, AASM::Persistence::ActiveRecordPersistence) - end - end -end diff --git a/vendor/gems/aasm-2.2.0/lib/aasm/persistence/active_record_persistence.rb b/vendor/gems/aasm-2.2.0/lib/aasm/persistence/active_record_persistence.rb deleted file mode 100644 index 528b404f..00000000 --- a/vendor/gems/aasm-2.2.0/lib/aasm/persistence/active_record_persistence.rb +++ /dev/null @@ -1,259 +0,0 @@ -module AASM - module Persistence - module ActiveRecordPersistence - # This method: - # - # * extends the model with ClassMethods - # * includes InstanceMethods - # - # Unless the corresponding methods are already defined, it includes - # * ReadState - # * WriteState - # * WriteStateWithoutPersistence - # - # Adds - # - # before_validation :aasm_ensure_initial_state, :on => :create - # - # As a result, it doesn't matter when you define your methods - the following 2 are equivalent - # - # class Foo < ActiveRecord::Base - # def aasm_write_state(state) - # "bar" - # end - # include AASM - # end - # - # class Foo < ActiveRecord::Base - # include AASM - # def aasm_write_state(state) - # "bar" - # end - # end - # - def self.included(base) - base.extend AASM::Persistence::ActiveRecordPersistence::ClassMethods - base.send(:include, AASM::Persistence::ActiveRecordPersistence::InstanceMethods) - base.send(:include, AASM::Persistence::ActiveRecordPersistence::ReadState) unless base.method_defined?(:aasm_read_state) - base.send(:include, AASM::Persistence::ActiveRecordPersistence::WriteState) unless base.method_defined?(:aasm_write_state) - base.send(:include, AASM::Persistence::ActiveRecordPersistence::WriteStateWithoutPersistence) unless base.method_defined?(:aasm_write_state_without_persistence) - - if base.respond_to?(:named_scope) || base.respond_to?(:scope) - base.extend(AASM::Persistence::ActiveRecordPersistence::NamedScopeMethods) - - base.class_eval do - class << self - unless method_defined?(:aasm_state_without_scope) - alias_method :aasm_state_without_scope, :aasm_state - alias_method :aasm_state, :aasm_state_with_scope - end - end - end - end - - if ActiveRecord::VERSION::MAJOR >= 3 - base.before_validation(:aasm_ensure_initial_state, :on => :create) - else - base.before_validation_on_create(:aasm_ensure_initial_state) - end - end - - module ClassMethods - # Maps to the aasm_column in the database. Defaults to "aasm_state". You can write: - # - # create_table :foos do |t| - # t.string :name - # t.string :aasm_state - # end - # - # class Foo < ActiveRecord::Base - # include AASM - # end - # - # OR: - # - # create_table :foos do |t| - # t.string :name - # t.string :status - # end - # - # class Foo < ActiveRecord::Base - # include AASM - # aasm_column :status - # end - # - # This method is both a getter and a setter - def aasm_column(column_name=nil) - if column_name - AASM::StateMachine[self].config.column = column_name.to_sym - # @aasm_column = column_name.to_sym - else - AASM::StateMachine[self].config.column ||= :aasm_state - # @aasm_column ||= :aasm_state - end - # @aasm_column - AASM::StateMachine[self].config.column - end - - def find_in_state(number, state, *args) - with_state_scope state do - find(number, *args) - end - end - - def count_in_state(state, *args) - with_state_scope state do - count(*args) - end - end - - def calculate_in_state(state, *args) - with_state_scope state do - calculate(*args) - end - end - - protected - def with_state_scope(state) - with_scope :find => {:conditions => ["#{table_name}.#{aasm_column} = ?", state.to_s]} do - yield if block_given? - end - end - end - - module InstanceMethods - - # Returns the current aasm_state of the object. Respects reload and - # any changes made to the aasm_state field directly - # - # Internally just calls aasm_read_state - # - # foo = Foo.find(1) - # foo.aasm_current_state # => :pending - # foo.aasm_state = "opened" - # foo.aasm_current_state # => :opened - # foo.close # => calls aasm_write_state_without_persistence - # foo.aasm_current_state # => :closed - # foo.reload - # foo.aasm_current_state # => :pending - # - def aasm_current_state - @current_state = aasm_read_state - end - - private - - # Ensures that if the aasm_state column is nil and the record is new - # that the initial state gets populated before validation on create - # - # foo = Foo.new - # foo.aasm_state # => nil - # foo.valid? - # foo.aasm_state # => "open" (where :open is the initial state) - # - # - # foo = Foo.find(:first) - # foo.aasm_state # => 1 - # foo.aasm_state = nil - # foo.valid? - # foo.aasm_state # => nil - # - def aasm_ensure_initial_state - send("#{self.class.aasm_column}=", self.aasm_enter_initial_state.to_s) if send(self.class.aasm_column).blank? - end - - end - - module WriteStateWithoutPersistence - # Writes state to the state column, but does not persist it to the database - # - # foo = Foo.find(1) - # foo.aasm_current_state # => :opened - # foo.close - # foo.aasm_current_state # => :closed - # Foo.find(1).aasm_current_state # => :opened - # foo.save - # foo.aasm_current_state # => :closed - # Foo.find(1).aasm_current_state # => :closed - # - # NOTE: intended to be called from an event - def aasm_write_state_without_persistence(state) - write_attribute(self.class.aasm_column, state.to_s) - end - end - - module WriteState - # Writes state to the state column and persists it to the database - # - # foo = Foo.find(1) - # foo.aasm_current_state # => :opened - # foo.close! - # foo.aasm_current_state # => :closed - # Foo.find(1).aasm_current_state # => :closed - # - # NOTE: intended to be called from an event - def aasm_write_state(state) - old_value = read_attribute(self.class.aasm_column) - write_attribute(self.class.aasm_column, state.to_s) - - # see https://github.com/rubyist/aasm/issues/2 - unless self.save - write_attribute(self.class.aasm_column, old_value) - # return false - return true - end - - true - end - end - - module ReadState - - # Returns the value of the aasm_column - called from aasm_current_state - # - # If it's a new record, and the aasm state column is blank it returns the initial state: - # - # class Foo < ActiveRecord::Base - # include AASM - # aasm_column :status - # aasm_state :opened - # aasm_state :closed - # end - # - # foo = Foo.new - # foo.current_state # => :opened - # foo.close - # foo.current_state # => :closed - # - # foo = Foo.find(1) - # foo.current_state # => :opened - # foo.aasm_state = nil - # foo.current_state # => nil - # - # NOTE: intended to be called from an event - # - # This allows for nil aasm states - be sure to add validation to your model - def aasm_read_state - if new_record? - send(self.class.aasm_column).blank? ? aasm_determine_state_name(self.class.aasm_initial_state) : send(self.class.aasm_column).to_sym - else - send(self.class.aasm_column).nil? ? nil : send(self.class.aasm_column).to_sym - end - end - end - - module NamedScopeMethods - def aasm_state_with_scope name, options = {} - aasm_state_without_scope name, options - - unless self.respond_to?(name) - scope_options = {:conditions => { "#{table_name}.#{self.aasm_column}" => name.to_s}} - scope_method = ActiveRecord::VERSION::MAJOR >= 3 ? :scope : :named_scope - self.send(scope_method, name, scope_options) - end - - end - end - end - end -end diff --git a/vendor/gems/aasm-2.2.0/lib/aasm/state.rb b/vendor/gems/aasm-2.2.0/lib/aasm/state.rb deleted file mode 100644 index df3840f7..00000000 --- a/vendor/gems/aasm-2.2.0/lib/aasm/state.rb +++ /dev/null @@ -1,53 +0,0 @@ -class AASM::SupportingClasses::State - attr_reader :name, :options - - def initialize(name, options={}) - @name = name - update(options) - end - - def ==(state) - if state.is_a? Symbol - name == state - else - name == state.name - end - end - - def call_action(action, record) - action = @options[action] - catch :halt_aasm_chain do - action.is_a?(Array) ? - action.each {|a| _call_action(a, record)} : - _call_action(action, record) - end - end - - def display_name - @display_name ||= name.to_s.gsub(/_/, ' ').capitalize - end - - def for_select - [display_name, name.to_s] - end - - def update(options = {}) - if options.key?(:display) then - @display_name = options.delete(:display) - end - @options = options - self - end - - private - - def _call_action(action, record) - case action - when Symbol, String - record.send(action) - when Proc - action.call(record) - end - end - -end diff --git a/vendor/gems/aasm-2.2.0/lib/aasm/state_machine.rb b/vendor/gems/aasm-2.2.0/lib/aasm/state_machine.rb deleted file mode 100644 index 92313cf4..00000000 --- a/vendor/gems/aasm-2.2.0/lib/aasm/state_machine.rb +++ /dev/null @@ -1,32 +0,0 @@ -class AASM::StateMachine - def self.[](*args) - (@machines ||= {})[args] - end - - def self.[]=(*args) - val = args.pop - (@machines ||= {})[args] = val - end - - attr_accessor :states, :events, :initial_state, :config - attr_reader :name - - def initialize(name) - @name = name - @initial_state = nil - @states = [] - @events = {} - @config = OpenStruct.new - end - - def clone - klone = super - klone.states = states.clone - klone.events = events.clone - klone - end - - def create_state(name, options) - @states << AASM::SupportingClasses::State.new(name, options) unless @states.include?(name) - end -end diff --git a/vendor/gems/aasm-2.2.0/lib/aasm/state_transition.rb b/vendor/gems/aasm-2.2.0/lib/aasm/state_transition.rb deleted file mode 100644 index c5dce1df..00000000 --- a/vendor/gems/aasm-2.2.0/lib/aasm/state_transition.rb +++ /dev/null @@ -1,46 +0,0 @@ -class AASM::SupportingClasses::StateTransition - attr_reader :from, :to, :opts - alias_method :options, :opts - - def initialize(opts) - @from, @to, @guard, @on_transition = opts[:from], opts[:to], opts[:guard], opts[:on_transition] - @opts = opts - end - - def perform(obj) - case @guard - when Symbol, String - obj.send(@guard) - when Proc - @guard.call(obj) - else - true - end - end - - def execute(obj, *args) - @on_transition.is_a?(Array) ? - @on_transition.each {|ot| _execute(obj, ot, *args)} : - _execute(obj, @on_transition, *args) - end - - def ==(obj) - @from == obj.from && @to == obj.to - end - - def from?(value) - @from == value - end - - private - - def _execute(obj, on_transition, *args) - case on_transition - when Symbol, String - obj.send(on_transition, *args) - when Proc - on_transition.call(obj, *args) - end - end - -end diff --git a/vendor/gems/aasm-2.2.0/lib/aasm/supporting_classes.rb b/vendor/gems/aasm-2.2.0/lib/aasm/supporting_classes.rb deleted file mode 100644 index 145eba5a..00000000 --- a/vendor/gems/aasm-2.2.0/lib/aasm/supporting_classes.rb +++ /dev/null @@ -1,6 +0,0 @@ -module AASM::SupportingClasses -end - -require File.join(File.dirname(__FILE__), 'state_transition') -require File.join(File.dirname(__FILE__), 'event') -require File.join(File.dirname(__FILE__), 'state') diff --git a/vendor/gems/aasm-2.2.0/spec/functional/conversation.rb b/vendor/gems/aasm-2.2.0/spec/functional/conversation.rb deleted file mode 100644 index da6e2bba..00000000 --- a/vendor/gems/aasm-2.2.0/spec/functional/conversation.rb +++ /dev/null @@ -1,49 +0,0 @@ -require File.join(File.dirname(__FILE__), '..', '..', 'lib', 'aasm') - -class Conversation - include AASM - - aasm_initial_state :needs_attention - - aasm_state :needs_attention - aasm_state :read - aasm_state :closed - aasm_state :awaiting_response - aasm_state :junk - - aasm_event :new_message do - end - - aasm_event :view do - transitions :to => :read, :from => [:needs_attention] - end - - aasm_event :reply do - end - - aasm_event :close do - transitions :to => :closed, :from => [:read, :awaiting_response] - end - - aasm_event :junk do - transitions :to => :junk, :from => [:read] - end - - aasm_event :unjunk do - end - - def initialize(persister) - @persister = persister - end - - - private - def aasm_read_state - @persister.read_state - end - - def aasm_write_state(state) - @persister.write_state(state) - end - -end diff --git a/vendor/gems/aasm-2.2.0/spec/functional/conversation_spec.rb b/vendor/gems/aasm-2.2.0/spec/functional/conversation_spec.rb deleted file mode 100644 index 8cfc97c9..00000000 --- a/vendor/gems/aasm-2.2.0/spec/functional/conversation_spec.rb +++ /dev/null @@ -1,8 +0,0 @@ -require File.expand_path(File.join(File.dirname(__FILE__), '..', 'spec_helper')) -require File.expand_path(File.join(File.dirname(__FILE__), 'conversation')) - -describe Conversation, 'description' do - it '.aasm_states should contain all of the states' do - Conversation.aasm_states.should == [:needs_attention, :read, :closed, :awaiting_response, :junk] - end -end diff --git a/vendor/gems/aasm-2.2.0/spec/spec_helper.rb b/vendor/gems/aasm-2.2.0/spec/spec_helper.rb deleted file mode 100644 index 9b9df8e5..00000000 --- a/vendor/gems/aasm-2.2.0/spec/spec_helper.rb +++ /dev/null @@ -1,11 +0,0 @@ -$LOAD_PATH.unshift(File.expand_path(File.dirname(__FILE__))) -$LOAD_PATH.unshift(File.expand_path(File.join(File.dirname(__FILE__), '..', 'lib'))) - -require 'aasm' - -require 'spec' -require 'spec/autorun' - -Spec::Runner.configure do |config| - -end diff --git a/vendor/gems/aasm-2.2.0/spec/unit/aasm_spec.rb b/vendor/gems/aasm-2.2.0/spec/unit/aasm_spec.rb deleted file mode 100644 index 7d7e0613..00000000 --- a/vendor/gems/aasm-2.2.0/spec/unit/aasm_spec.rb +++ /dev/null @@ -1,462 +0,0 @@ -require File.expand_path(File.join(File.dirname(__FILE__), '..', 'spec_helper')) - -class Foo - include AASM - aasm_initial_state :open - aasm_state :open, :exit => :exit - aasm_state :closed, :enter => :enter - - aasm_event :close, :success => :success_callback do - transitions :to => :closed, :from => [:open] - end - - aasm_event :null do - transitions :to => :closed, :from => [:open], :guard => :always_false - end - - def always_false - false - end - - def success_callback - end - - def enter - end - def exit - end -end - -class FooTwo < Foo - include AASM - aasm_state :foo -end - -class Bar - include AASM - - aasm_state :read - aasm_state :ended - - aasm_event :foo do - transitions :to => :ended, :from => [:read] - end -end - -class Baz < Bar -end - -class Banker - include AASM - aasm_initial_state Proc.new { |banker| banker.rich? ? :retired : :selling_bad_mortgages } - aasm_state :retired - aasm_state :selling_bad_mortgages - RICH = 1_000_000 - attr_accessor :balance - def initialize(balance = 0); self.balance = balance; end - def rich?; self.balance >= RICH; end -end - - -describe AASM, '- class level definitions' do - it 'should define a class level aasm_initial_state() method on its including class' do - Foo.should respond_to(:aasm_initial_state) - end - - it 'should define a class level aasm_state() method on its including class' do - Foo.should respond_to(:aasm_state) - end - - it 'should define a class level aasm_event() method on its including class' do - Foo.should respond_to(:aasm_event) - end - - it 'should define a class level aasm_states() method on its including class' do - Foo.should respond_to(:aasm_states) - end - - it 'should define a class level aasm_states_for_select() method on its including class' do - Foo.should respond_to(:aasm_states_for_select) - end - - it 'should define a class level aasm_events() method on its including class' do - Foo.should respond_to(:aasm_events) - end - -end - - -describe AASM, '- subclassing' do - it 'should have the parent states' do - Foo.aasm_states.each do |state| - FooTwo.aasm_states.should include(state) - end - end - - it 'should not add the child states to the parent machine' do - Foo.aasm_states.should_not include(:foo) - end -end - - -describe AASM, '- aasm_states_for_select' do - it "should return a select friendly array of states in the form of [['Friendly name', 'state_name']]" do - Foo.aasm_states_for_select.should == [['Open', 'open'], ['Closed', 'closed']] - end -end - -describe AASM, '- instance level definitions' do - before(:each) do - @foo = Foo.new - end - - it 'should define a state querying instance method on including class' do - @foo.should respond_to(:open?) - end - - it 'should define an event! inance method' do - @foo.should respond_to(:close!) - end -end - -describe AASM, '- initial states' do - before(:each) do - @foo = Foo.new - @bar = Bar.new - end - - it 'should set the initial state' do - @foo.aasm_current_state.should == :open - end - - it '#open? should be initially true' do - @foo.open?.should be_true - end - - it '#closed? should be initially false' do - @foo.closed?.should be_false - end - - it 'should use the first state defined if no initial state is given' do - @bar.aasm_current_state.should == :read - end - - it 'should determine initial state from the Proc results' do - Banker.new(Banker::RICH - 1).aasm_current_state.should == :selling_bad_mortgages - Banker.new(Banker::RICH + 1).aasm_current_state.should == :retired - end -end - -describe AASM, '- event firing with persistence' do - it 'should fire the Event' do - foo = Foo.new - - Foo.aasm_events[:close].should_receive(:fire).with(foo) - foo.close! - end - - it 'should update the current state' do - foo = Foo.new - foo.close! - - foo.aasm_current_state.should == :closed - end - - it 'should call the success callback if one was provided' do - foo = Foo.new - - foo.should_receive(:success_callback) - - foo.close! - end - - it 'should attempt to persist if aasm_write_state is defined' do - foo = Foo.new - - def foo.aasm_write_state - end - - foo.should_receive(:aasm_write_state) - - foo.close! - end - - it 'should return true if aasm_write_state is defined and returns true' do - foo = Foo.new - - def foo.aasm_write_state(state) - true - end - - foo.close!.should be_true - end - - it 'should return false if aasm_write_state is defined and returns false' do - foo = Foo.new - - def foo.aasm_write_state(state) - false - end - - foo.close!.should be_false - end - - it "should not update the aasm_current_state if the write fails" do - foo = Foo.new - - def foo.aasm_write_state - false - end - - foo.should_receive(:aasm_write_state) - - foo.close! - foo.aasm_current_state.should == :open - end -end - -describe AASM, '- event firing without persistence' do - it 'should fire the Event' do - foo = Foo.new - - Foo.aasm_events[:close].should_receive(:fire).with(foo) - foo.close - end - - it 'should update the current state' do - foo = Foo.new - foo.close - - foo.aasm_current_state.should == :closed - end - - it 'should attempt to persist if aasm_write_state is defined' do - foo = Foo.new - - def foo.aasm_write_state - end - - foo.should_receive(:aasm_write_state_without_persistence).twice - - foo.close - end -end - -describe AASM, '- persistence' do - it 'should read the state if it has not been set and aasm_read_state is defined' do - foo = Foo.new - def foo.aasm_read_state - end - - foo.should_receive(:aasm_read_state) - - foo.aasm_current_state - end -end - -describe AASM, '- getting events for a state' do - it '#aasm_events_for_current_state should use current state' do - foo = Foo.new - foo.should_receive(:aasm_current_state) - foo.aasm_events_for_current_state - end - - it '#aasm_events_for_current_state should use aasm_events_for_state' do - foo = Foo.new - foo.stub!(:aasm_current_state).and_return(:foo) - foo.should_receive(:aasm_events_for_state).with(:foo) - foo.aasm_events_for_current_state - end -end - -describe AASM, '- event callbacks' do - describe "with an error callback defined" do - before do - class Foo - aasm_event :safe_close, :success => :success_callback, :error => :error_callback do - transitions :to => :closed, :from => [:open] - end - end - - @foo = Foo.new - end - - it "should run error_callback if an exception is raised and error_callback defined" do - def @foo.error_callback(e) - end - @foo.stub!(:enter).and_raise(e=StandardError.new) - @foo.should_receive(:error_callback).with(e) - @foo.safe_close! - end - - it "should raise NoMethodError if exceptionis raised and error_callback is declared but not defined" do - @foo.stub!(:enter).and_raise(StandardError) - lambda{@foo.safe_close!}.should raise_error(NoMethodError) - end - - it "should propagate an error if no error callback is declared" do - @foo.stub!(:enter).and_raise("Cannot enter safe") - lambda{@foo.close!}.should raise_error(StandardError, "Cannot enter safe") - end - end - - describe "with aasm_event_fired defined" do - before do - @foo = Foo.new - def @foo.aasm_event_fired(event, from, to) - end - end - - it 'should call it for successful bang fire' do - @foo.should_receive(:aasm_event_fired).with(:close, :open, :closed) - @foo.close! - end - - it 'should call it for successful non-bang fire' do - @foo.should_receive(:aasm_event_fired) - @foo.close - end - - it 'should not call it for failing bang fire' do - @foo.stub!(:set_aasm_current_state_with_persistence).and_return(false) - @foo.should_not_receive(:aasm_event_fired) - @foo.close! - end - end - - describe "with aasm_event_failed defined" do - before do - @foo = Foo.new - def @foo.aasm_event_failed(event, from) - end - end - - it 'should call it when transition failed for bang fire' do - @foo.should_receive(:aasm_event_failed).with(:null, :open) - @foo.null! - end - - it 'should call it when transition failed for non-bang fire' do - @foo.should_receive(:aasm_event_failed).with(:null, :open) - @foo.null - end - - it 'should not call it if persist fails for bang fire' do - @foo.stub!(:set_aasm_current_state_with_persistence).and_return(false) - @foo.should_receive(:aasm_event_failed) - @foo.close! - end - end -end - -describe AASM, '- state actions' do - it "should call enter when entering state" do - foo = Foo.new - foo.should_receive(:enter) - - foo.close - end - - it "should call exit when exiting state" do - foo = Foo.new - foo.should_receive(:exit) - - foo.close - end -end - - -describe Baz do - it "should have the same states as it's parent" do - Baz.aasm_states.should == Bar.aasm_states - end - - it "should have the same events as it's parent" do - Baz.aasm_events.should == Bar.aasm_events - end -end - - -class ChetanPatil - include AASM - aasm_initial_state :sleeping - aasm_state :sleeping - aasm_state :showering - aasm_state :working - aasm_state :dating - aasm_state :prettying_up - - aasm_event :wakeup do - transitions :from => :sleeping, :to => [:showering, :working] - end - - aasm_event :dress do - transitions :from => :sleeping, :to => :working, :on_transition => :wear_clothes - transitions :from => :showering, :to => [:working, :dating], :on_transition => Proc.new { |obj, *args| obj.wear_clothes(*args) } - transitions :from => :showering, :to => :prettying_up, :on_transition => [:condition_hair, :fix_hair] - end - - def wear_clothes(shirt_color, trouser_type) - end - - def condition_hair - end - - def fix_hair - end -end - - -describe ChetanPatil do - it 'should transition to specified next state (sleeping to showering)' do - cp = ChetanPatil.new - cp.wakeup! :showering - - cp.aasm_current_state.should == :showering - end - - it 'should transition to specified next state (sleeping to working)' do - cp = ChetanPatil.new - cp.wakeup! :working - - cp.aasm_current_state.should == :working - end - - it 'should transition to default (first or showering) state' do - cp = ChetanPatil.new - cp.wakeup! - - cp.aasm_current_state.should == :showering - end - - it 'should transition to default state when on_transition invoked' do - cp = ChetanPatil.new - cp.dress!(nil, 'purple', 'dressy') - - cp.aasm_current_state.should == :working - end - - it 'should call on_transition method with args' do - cp = ChetanPatil.new - cp.wakeup! :showering - - cp.should_receive(:wear_clothes).with('blue', 'jeans') - cp.dress! :working, 'blue', 'jeans' - end - - it 'should call on_transition proc' do - cp = ChetanPatil.new - cp.wakeup! :showering - - cp.should_receive(:wear_clothes).with('purple', 'slacks') - cp.dress!(:dating, 'purple', 'slacks') - end - - it 'should call on_transition with an array of methods' do - cp = ChetanPatil.new - cp.wakeup! :showering - cp.should_receive(:condition_hair) - cp.should_receive(:fix_hair) - cp.dress!(:prettying_up) - end -end diff --git a/vendor/gems/aasm-2.2.0/spec/unit/active_record_persistence_spec.rb b/vendor/gems/aasm-2.2.0/spec/unit/active_record_persistence_spec.rb deleted file mode 100644 index 75b87c7f..00000000 --- a/vendor/gems/aasm-2.2.0/spec/unit/active_record_persistence_spec.rb +++ /dev/null @@ -1,255 +0,0 @@ -begin - require 'rubygems' - require 'active_record' - require 'logger' - - ActiveRecord::Base.logger = Logger.new(STDERR) - - # A dummy class for mocking the activerecord connection class - class Connection - end - - class FooBar < ActiveRecord::Base - include AASM - - # Fake this column for testing purposes - attr_accessor :aasm_state - - aasm_state :open - aasm_state :closed - - aasm_event :view do - transitions :to => :read, :from => [:needs_attention] - end - end - - class Fi < ActiveRecord::Base - def aasm_read_state - "fi" - end - include AASM - end - - class Fo < ActiveRecord::Base - def aasm_write_state(state) - "fo" - end - include AASM - end - - class Fum < ActiveRecord::Base - def aasm_write_state_without_persistence(state) - "fum" - end - include AASM - end - - class June < ActiveRecord::Base - include AASM - aasm_column :status - end - - class Beaver < June - end - - class Thief < ActiveRecord::Base - include AASM - aasm_initial_state Proc.new { |thief| thief.skilled ? :rich : :jailed } - aasm_state :rich - aasm_state :jailed - attr_accessor :skilled, :aasm_state - end - - describe "aasm model", :shared => true do - it "should include AASM::Persistence::ActiveRecordPersistence" do - @klass.included_modules.should be_include(AASM::Persistence::ActiveRecordPersistence) - end - it "should include AASM::Persistence::ActiveRecordPersistence::InstanceMethods" do - @klass.included_modules.should be_include(AASM::Persistence::ActiveRecordPersistence::InstanceMethods) - end - end - - describe FooBar, "class methods" do - before(:each) do - @klass = FooBar - end - it_should_behave_like "aasm model" - it "should include AASM::Persistence::ActiveRecordPersistence::ReadState" do - @klass.included_modules.should be_include(AASM::Persistence::ActiveRecordPersistence::ReadState) - end - it "should include AASM::Persistence::ActiveRecordPersistence::WriteState" do - @klass.included_modules.should be_include(AASM::Persistence::ActiveRecordPersistence::WriteState) - end - it "should include AASM::Persistence::ActiveRecordPersistence::WriteStateWithoutPersistence" do - @klass.included_modules.should be_include(AASM::Persistence::ActiveRecordPersistence::WriteStateWithoutPersistence) - end - end - - describe Fi, "class methods" do - before(:each) do - @klass = Fi - end - it_should_behave_like "aasm model" - it "should not include AASM::Persistence::ActiveRecordPersistence::ReadState" do - @klass.included_modules.should_not be_include(AASM::Persistence::ActiveRecordPersistence::ReadState) - end - it "should include AASM::Persistence::ActiveRecordPersistence::WriteState" do - @klass.included_modules.should be_include(AASM::Persistence::ActiveRecordPersistence::WriteState) - end - it "should include AASM::Persistence::ActiveRecordPersistence::WriteStateWithoutPersistence" do - @klass.included_modules.should be_include(AASM::Persistence::ActiveRecordPersistence::WriteStateWithoutPersistence) - end - end - - describe Fo, "class methods" do - before(:each) do - @klass = Fo - end - it_should_behave_like "aasm model" - it "should include AASM::Persistence::ActiveRecordPersistence::ReadState" do - @klass.included_modules.should be_include(AASM::Persistence::ActiveRecordPersistence::ReadState) - end - it "should not include AASM::Persistence::ActiveRecordPersistence::WriteState" do - @klass.included_modules.should_not be_include(AASM::Persistence::ActiveRecordPersistence::WriteState) - end - it "should include AASM::Persistence::ActiveRecordPersistence::WriteStateWithoutPersistence" do - @klass.included_modules.should be_include(AASM::Persistence::ActiveRecordPersistence::WriteStateWithoutPersistence) - end - end - - describe Fum, "class methods" do - before(:each) do - @klass = Fum - end - it_should_behave_like "aasm model" - it "should include AASM::Persistence::ActiveRecordPersistence::ReadState" do - @klass.included_modules.should be_include(AASM::Persistence::ActiveRecordPersistence::ReadState) - end - it "should include AASM::Persistence::ActiveRecordPersistence::WriteState" do - @klass.included_modules.should be_include(AASM::Persistence::ActiveRecordPersistence::WriteState) - end - it "should not include AASM::Persistence::ActiveRecordPersistence::WriteStateWithoutPersistence" do - @klass.included_modules.should_not be_include(AASM::Persistence::ActiveRecordPersistence::WriteStateWithoutPersistence) - end - end - - describe FooBar, "instance methods" do - before(:each) do - connection = mock(Connection, :columns => []) - FooBar.stub!(:connection).and_return(connection) - end - - it "should respond to aasm read state when not previously defined" do - FooBar.new.should respond_to(:aasm_read_state) - end - - it "should respond to aasm write state when not previously defined" do - FooBar.new.should respond_to(:aasm_write_state) - end - - it "should respond to aasm write state without persistence when not previously defined" do - FooBar.new.should respond_to(:aasm_write_state_without_persistence) - end - - it "should return the initial state when new and the aasm field is nil" do - FooBar.new.aasm_current_state.should == :open - end - - it "should return the aasm column when new and the aasm field is not nil" do - foo = FooBar.new - foo.aasm_state = "closed" - foo.aasm_current_state.should == :closed - end - - it "should return the aasm column when not new and the aasm_column is not nil" do - foo = FooBar.new - foo.stub!(:new_record?).and_return(false) - foo.aasm_state = "state" - foo.aasm_current_state.should == :state - end - - it "should allow a nil state" do - foo = FooBar.new - foo.stub!(:new_record?).and_return(false) - foo.aasm_state = nil - foo.aasm_current_state.should be_nil - end - - it "should have aasm_ensure_initial_state" do - foo = FooBar.new - foo.send :aasm_ensure_initial_state - end - - it "should call aasm_ensure_initial_state on validation before create" do - foo = FooBar.new - foo.should_receive(:aasm_ensure_initial_state).and_return(true) - foo.valid? - end - - it "should call aasm_ensure_initial_state on validation before create" do - foo = FooBar.new - foo.stub!(:new_record?).and_return(false) - foo.should_not_receive(:aasm_ensure_initial_state) - foo.valid? - end - - end - - describe 'Beavers' do - it "should have the same states as it's parent" do - Beaver.aasm_states.should == June.aasm_states - end - - it "should have the same events as it's parent" do - Beaver.aasm_events.should == June.aasm_events - end - - it "should have the same column as it's parent" do - Beaver.aasm_column.should == :status - end - end - - describe AASM::Persistence::ActiveRecordPersistence::NamedScopeMethods do - class NamedScopeExample < ActiveRecord::Base - include AASM - end - - context "Does not already respond_to? the scope name" do - it "should add a scope" do - NamedScopeExample.aasm_state :unknown_scope - NamedScopeExample.scopes.keys.should include(:unknown_scope) - end - end - - context "Already respond_to? the scope name" do - it "should not add a scope" do - NamedScopeExample.aasm_state :new - NamedScopeExample.scopes.keys.should_not include(:new) - end - end - end - - describe 'Thieves' do - before(:each) do - connection = mock(Connection, :columns => []) - Thief.stub!(:connection).and_return(connection) - end - - it 'should be rich if they\'re skilled' do - Thief.new(:skilled => true).aasm_current_state.should == :rich - end - - it 'should be jailed if they\'re unskilled' do - Thief.new(:skilled => false).aasm_current_state.should == :jailed - end - end - - # TODO: figure out how to test ActiveRecord reload! without a database - -rescue LoadError => e - if e.message == "no such file to load -- active_record" - puts "You must install active record to run this spec. Install with sudo gem install activerecord" - else - raise - end -end diff --git a/vendor/gems/aasm-2.2.0/spec/unit/before_after_callbacks_spec.rb b/vendor/gems/aasm-2.2.0/spec/unit/before_after_callbacks_spec.rb deleted file mode 100644 index 9784befe..00000000 --- a/vendor/gems/aasm-2.2.0/spec/unit/before_after_callbacks_spec.rb +++ /dev/null @@ -1,79 +0,0 @@ -require File.expand_path(File.join(File.dirname(__FILE__), '..', 'spec_helper')) - -class Foo2 - include AASM - aasm_initial_state :open - aasm_state :open, - :before_enter => :before_enter_open, - :before_exit => :before_exit_open, - :after_enter => :after_enter_open, - :after_exit => :after_exit_open - aasm_state :closed, - :before_enter => :before_enter_closed, - :before_exit => :before_exit_closed, - :after_enter => :after_enter_closed, - :after_exit => :after_exit_closed - - aasm_event :close, :before => :before, :after => :after do - transitions :to => :closed, :from => [:open] - end - - aasm_event :open, :before => :before, :after => :after do - transitions :to => :open, :from => :closed - end - - def before_enter_open - end - def before_exit_open - end - def after_enter_open - end - def after_exit_open - end - - def before_enter_closed - end - def before_exit_closed - end - def after_enter_closed - end - def after_exit_closed - end - - def before - end - def after - end -end - -describe Foo2, '- new callbacks' do - before(:each) do - @foo = Foo2.new - end - - it "should get close callbacks" do - @foo.should_receive(:before).once.ordered - @foo.should_receive(:before_exit_open).once.ordered # these should be before the state changes - @foo.should_receive(:before_enter_closed).once.ordered - @foo.should_receive(:aasm_write_state).once.ordered.and_return(true) # this is when the state changes - @foo.should_receive(:after_exit_open).once.ordered # these should be after the state changes - @foo.should_receive(:after_enter_closed).once.ordered - @foo.should_receive(:after).once.ordered - - @foo.close! - end - - it "should get open callbacks" do - @foo.close! - - @foo.should_receive(:before).once.ordered - @foo.should_receive(:before_exit_closed).once.ordered # these should be before the state changes - @foo.should_receive(:before_enter_open).once.ordered - @foo.should_receive(:aasm_write_state).once.ordered.and_return(true) # this is when the state changes - @foo.should_receive(:after_exit_closed).once.ordered # these should be after the state changes - @foo.should_receive(:after_enter_open).once.ordered - @foo.should_receive(:after).once.ordered - - @foo.open! - end -end diff --git a/vendor/gems/aasm-2.2.0/spec/unit/event_spec.rb b/vendor/gems/aasm-2.2.0/spec/unit/event_spec.rb deleted file mode 100644 index 88550963..00000000 --- a/vendor/gems/aasm-2.2.0/spec/unit/event_spec.rb +++ /dev/null @@ -1,126 +0,0 @@ -require File.expand_path(File.join(File.dirname(__FILE__), '..', 'spec_helper')) - -describe AASM::SupportingClasses::Event do - before(:each) do - @name = :close_order - @success = :success_callback - end - - def new_event - @event = AASM::SupportingClasses::Event.new(@name, {:success => @success}) do - transitions :to => :closed, :from => [:open, :received] - end - end - - it 'should set the name' do - new_event - @event.name.should == @name - end - - it 'should set the success option' do - new_event - @event.success.should == @success - end - - it 'should create StateTransitions' do - AASM::SupportingClasses::StateTransition.should_receive(:new).with({:to => :closed, :from => :open}) - AASM::SupportingClasses::StateTransition.should_receive(:new).with({:to => :closed, :from => :received}) - new_event - end -end - -describe AASM::SupportingClasses::Event, 'when firing an event' do - it 'should raise an AASM::InvalidTransition error if the transitions are empty' do - obj = mock('object') - obj.stub!(:aasm_current_state) - - event = AASM::SupportingClasses::Event.new(:event) - lambda { event.fire(obj) }.should raise_error(AASM::InvalidTransition) - end - - it 'should return the state of the first matching transition it finds' do - event = AASM::SupportingClasses::Event.new(:event) do - transitions :to => :closed, :from => [:open, :received] - end - - obj = mock('object') - obj.stub!(:aasm_current_state).and_return(:open) - - event.fire(obj).should == :closed - end -end - -describe AASM::SupportingClasses::Event, 'when executing the success callback' do - class ThisNameBetterNotBeInUse - include AASM - - aasm_state :initial - aasm_state :symbol - aasm_state :string - aasm_state :array - aasm_state :proc - end - - it "should send the success callback if it's a symbol" do - ThisNameBetterNotBeInUse.instance_eval { - aasm_event :with_symbol, :success => :symbol_success_callback do - transitions :to => :symbol, :from => [:initial] - end - } - - model = ThisNameBetterNotBeInUse.new - model.should_receive(:symbol_success_callback) - model.with_symbol! - end - - it "should send the success callback if it's a string" do - ThisNameBetterNotBeInUse.instance_eval { - aasm_event :with_string, :success => 'string_success_callback' do - transitions :to => :string, :from => [:initial] - end - } - - model = ThisNameBetterNotBeInUse.new - model.should_receive(:string_success_callback) - model.with_string! - end - - it "should call each success callback if passed an array of strings and/or symbols" do - ThisNameBetterNotBeInUse.instance_eval { - aasm_event :with_array, :success => [:success_callback1, 'success_callback2'] do - transitions :to => :array, :from => [:initial] - end - } - - model = ThisNameBetterNotBeInUse.new - model.should_receive(:success_callback1) - model.should_receive(:success_callback2) - model.with_array! - end - - it "should call each success callback if passed an array of strings and/or symbols and/or procs" do - ThisNameBetterNotBeInUse.instance_eval { - aasm_event :with_array_including_procs, :success => [:success_callback1, 'success_callback2', lambda { |obj| obj.proc_success_callback }] do - transitions :to => :array, :from => [:initial] - end - } - - model = ThisNameBetterNotBeInUse.new - model.should_receive(:success_callback1) - model.should_receive(:success_callback2) - model.should_receive(:proc_success_callback) - model.with_array_including_procs! - end - - it "should call the success callback if it's a proc" do - ThisNameBetterNotBeInUse.instance_eval { - aasm_event :with_proc, :success => lambda { |obj| obj.proc_success_callback } do - transitions :to => :proc, :from => [:initial] - end - } - - model = ThisNameBetterNotBeInUse.new - model.should_receive(:proc_success_callback) - model.with_proc! - end -end diff --git a/vendor/gems/aasm-2.2.0/spec/unit/state_spec.rb b/vendor/gems/aasm-2.2.0/spec/unit/state_spec.rb deleted file mode 100644 index 114163d9..00000000 --- a/vendor/gems/aasm-2.2.0/spec/unit/state_spec.rb +++ /dev/null @@ -1,85 +0,0 @@ -require File.expand_path(File.join(File.dirname(__FILE__), '..', 'spec_helper')) - -# TODO These are specs ported from original aasm -describe AASM::SupportingClasses::State do - before(:each) do - @name = :astate - @options = { :crazy_custom_key => 'key' } - end - - def new_state(options={}) - AASM::SupportingClasses::State.new(@name, @options.merge(options)) - end - - it 'should set the name' do - state = new_state - - state.name.should == :astate - end - - it 'should set the options and expose them as options' do - state = new_state - - state.options.should == @options - end - - it 'should be equal to a symbol of the same name' do - state = new_state - - state.should == :astate - end - - it 'should be equal to a State of the same name' do - new_state.should == new_state - end - - it 'should send a message to the record for an action if the action is present as a symbol' do - state = new_state(:entering => :foo) - - record = mock('record') - record.should_receive(:foo) - - state.call_action(:entering, record) - end - - it 'should send a message to the record for an action if the action is present as a string' do - state = new_state(:entering => 'foo') - - record = mock('record') - record.should_receive(:foo) - - state.call_action(:entering, record) - end - - it 'should send a message to the record for each action' do - state = new_state(:entering => [:a, :b, "c", lambda {|r| r.foobar }]) - - record = mock('record') - record.should_receive(:a) - record.should_receive(:b) - record.should_receive(:c) - record.should_receive(:foobar) - - state.call_action(:entering, record) - end - - it "should stop calling actions if one of them raises :halt_aasm_chain" do - state = new_state(:entering => [:a, :b, :c]) - - record = mock('record') - record.should_receive(:a) - record.should_receive(:b).and_throw(:halt_aasm_chain) - record.should_not_receive(:c) - - state.call_action(:entering, record) - end - - it 'should call a proc, passing in the record for an action if the action is present' do - state = new_state(:entering => Proc.new {|r| r.foobar}) - - record = mock('record') - record.should_receive(:foobar) - - state.call_action(:entering, record) - end -end diff --git a/vendor/gems/aasm-2.2.0/spec/unit/state_transition_spec.rb b/vendor/gems/aasm-2.2.0/spec/unit/state_transition_spec.rb deleted file mode 100644 index d0812c57..00000000 --- a/vendor/gems/aasm-2.2.0/spec/unit/state_transition_spec.rb +++ /dev/null @@ -1,84 +0,0 @@ -require File.expand_path(File.join(File.dirname(__FILE__), '..', 'spec_helper')) - -describe AASM::SupportingClasses::StateTransition do - it 'should set from, to, and opts attr readers' do - opts = {:from => 'foo', :to => 'bar', :guard => 'g'} - st = AASM::SupportingClasses::StateTransition.new(opts) - - st.from.should == opts[:from] - st.to.should == opts[:to] - st.opts.should == opts - end - - it 'should pass equality check if from and to are the same' do - opts = {:from => 'foo', :to => 'bar', :guard => 'g'} - st = AASM::SupportingClasses::StateTransition.new(opts) - - obj = mock('object') - obj.stub!(:from).and_return(opts[:from]) - obj.stub!(:to).and_return(opts[:to]) - - st.should == obj - end - - it 'should fail equality check if from are not the same' do - opts = {:from => 'foo', :to => 'bar', :guard => 'g'} - st = AASM::SupportingClasses::StateTransition.new(opts) - - obj = mock('object') - obj.stub!(:from).and_return('blah') - obj.stub!(:to).and_return(opts[:to]) - - st.should_not == obj - end - - it 'should fail equality check if to are not the same' do - opts = {:from => 'foo', :to => 'bar', :guard => 'g'} - st = AASM::SupportingClasses::StateTransition.new(opts) - - obj = mock('object') - obj.stub!(:from).and_return(opts[:from]) - obj.stub!(:to).and_return('blah') - - st.should_not == obj - end -end - -describe AASM::SupportingClasses::StateTransition, '- when performing guard checks' do - it 'should return true of there is no guard' do - opts = {:from => 'foo', :to => 'bar'} - st = AASM::SupportingClasses::StateTransition.new(opts) - - st.perform(nil).should be_true - end - - it 'should call the method on the object if guard is a symbol' do - opts = {:from => 'foo', :to => 'bar', :guard => :test} - st = AASM::SupportingClasses::StateTransition.new(opts) - - obj = mock('object') - obj.should_receive(:test) - - st.perform(obj) - end - - it 'should call the method on the object if guard is a string' do - opts = {:from => 'foo', :to => 'bar', :guard => 'test'} - st = AASM::SupportingClasses::StateTransition.new(opts) - - obj = mock('object') - obj.should_receive(:test) - - st.perform(obj) - end - - it 'should call the proc passing the object if the guard is a proc' do - opts = {:from => 'foo', :to => 'bar', :guard => Proc.new {|o| o.test}} - st = AASM::SupportingClasses::StateTransition.new(opts) - - obj = mock('object') - obj.should_receive(:test) - - st.perform(obj) - end -end diff --git a/vendor/gems/aasm-2.2.0/test/functional/auth_machine_test.rb b/vendor/gems/aasm-2.2.0/test/functional/auth_machine_test.rb deleted file mode 100644 index f9d8ed84..00000000 --- a/vendor/gems/aasm-2.2.0/test/functional/auth_machine_test.rb +++ /dev/null @@ -1,120 +0,0 @@ -require 'test_helper' - -class AuthMachine - include AASM - - attr_accessor :activation_code, :activated_at, :deleted_at - - aasm_initial_state :pending - - aasm_state :passive - aasm_state :pending, :enter => :make_activation_code - aasm_state :active, :enter => :do_activate - aasm_state :suspended - aasm_state :deleted, :enter => :do_delete, :exit => :do_undelete - - aasm_event :register do - transitions :from => :passive, :to => :pending, :guard => Proc.new {|u| u.can_register? } - end - - aasm_event :activate do - transitions :from => :pending, :to => :active - end - - aasm_event :suspend do - transitions :from => [:passive, :pending, :active], :to => :suspended - end - - aasm_event :delete do - transitions :from => [:passive, :pending, :active, :suspended], :to => :deleted - end - - aasm_event :unsuspend do - transitions :from => :suspended, :to => :active, :guard => Proc.new {|u| u.has_activated? } - transitions :from => :suspended, :to => :pending, :guard => Proc.new {|u| u.has_activation_code? } - transitions :from => :suspended, :to => :passive - end - - def initialize - # the AR backend uses a before_validate_on_create :aasm_ensure_initial_state - # lets do something similar here for testing purposes. - aasm_enter_initial_state - end - - def make_activation_code - @activation_code = 'moo' - end - - def do_activate - @activated_at = Time.now - @activation_code = nil - end - - def do_delete - @deleted_at = Time.now - end - - def do_undelete - @deleted_at = false - end - - def can_register? - true - end - - def has_activated? - !!@activated_at - end - - def has_activation_code? - !!@activation_code - end -end - -class AuthMachineTest < Test::Unit::TestCase - context 'authentication state machine' do - context 'on initialization' do - setup do - @auth = AuthMachine.new - end - - should 'be in the pending state' do - assert_equal :pending, @auth.aasm_current_state - end - - should 'have an activation code' do - assert @auth.has_activation_code? - assert_not_nil @auth.activation_code - end - end - - context 'when being unsuspended' do - should 'be active if previously activated' do - @auth = AuthMachine.new - @auth.activate! - @auth.suspend! - @auth.unsuspend! - - assert_equal :active, @auth.aasm_current_state - end - - should 'be pending if not previously activated, but an activation code is present' do - @auth = AuthMachine.new - @auth.suspend! - @auth.unsuspend! - - assert_equal :pending, @auth.aasm_current_state - end - - should 'be passive if not previously activated and there is no activation code' do - @auth = AuthMachine.new - @auth.activation_code = nil - @auth.suspend! - @auth.unsuspend! - - assert_equal :passive, @auth.aasm_current_state - end - end - - end -end diff --git a/vendor/gems/aasm-2.2.0/test/test_helper.rb b/vendor/gems/aasm-2.2.0/test/test_helper.rb deleted file mode 100644 index 5dc5fe1c..00000000 --- a/vendor/gems/aasm-2.2.0/test/test_helper.rb +++ /dev/null @@ -1,33 +0,0 @@ -require 'ostruct' -require 'rubygems' - -begin - gem 'minitest' -rescue Gem::LoadError - puts 'minitest gem not found' -end - -begin - require 'minitest/autorun' - puts 'using minitest' -rescue LoadError - require 'test/unit' - puts 'using test/unit' -end - -require 'rr' -require 'shoulda' - -class Test::Unit::TestCase - include RR::Adapters::TestUnit -end - -begin - require 'ruby-debug' - Debugger.start -rescue LoadError -end - -$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib')) -$LOAD_PATH.unshift(File.dirname(__FILE__)) -require 'aasm' diff --git a/vendor/gems/aasm-2.2.0/test/unit/event_test.rb b/vendor/gems/aasm-2.2.0/test/unit/event_test.rb deleted file mode 100644 index bb79573f..00000000 --- a/vendor/gems/aasm-2.2.0/test/unit/event_test.rb +++ /dev/null @@ -1,54 +0,0 @@ -require 'test_helper' - -class EventTest < Test::Unit::TestCase - def new_event - @event = AASM::SupportingClasses::Event.new(@name, {:success => @success}) do - transitions :to => :closed, :from => [:open, :received] - end - end - - context 'event' do - setup do - @name = :close_order - @success = :success_callback - end - - should 'set the name' do - assert_equal @name, new_event.name - end - - should 'set the success option' do - assert_equal @success, new_event.success - end - - should 'create StateTransitions' do - mock(AASM::SupportingClasses::StateTransition).new({:to => :closed, :from => :open}) - mock(AASM::SupportingClasses::StateTransition).new({:to => :closed, :from => :received}) - new_event - end - - context 'when firing' do - should 'raise an AASM::InvalidTransition error if the transitions are empty' do - event = AASM::SupportingClasses::Event.new(:event) - - obj = OpenStruct.new - obj.aasm_current_state = :open - - assert_raise AASM::InvalidTransition do - event.fire(obj) - end - end - - should 'return the state of the first matching transition it finds' do - event = AASM::SupportingClasses::Event.new(:event) do - transitions :to => :closed, :from => [:open, :received] - end - - obj = OpenStruct.new - obj.aasm_current_state = :open - - assert_equal :closed, event.fire(obj) - end - end - end -end diff --git a/vendor/gems/aasm-2.2.0/test/unit/state_test.rb b/vendor/gems/aasm-2.2.0/test/unit/state_test.rb deleted file mode 100644 index 417c952b..00000000 --- a/vendor/gems/aasm-2.2.0/test/unit/state_test.rb +++ /dev/null @@ -1,69 +0,0 @@ -require 'test_helper' - -class StateTest < Test::Unit::TestCase - def new_state(options={}) - AASM::SupportingClasses::State.new(@name, @options.merge(options)) - end - - context 'state' do - setup do - @name = :astate - @options = { :crazy_custom_key => 'key' } - end - - should 'set the name' do - assert_equal :astate, new_state.name - end - - should 'set the display_name from name' do - assert_equal "Astate", new_state.display_name - end - - should 'set the display_name from options' do - assert_equal "A State", new_state(:display => "A State").display_name - end - - should 'set the options and expose them as options' do - assert_equal @options, new_state.options - end - - should 'equal a symbol of the same name' do - assert_equal new_state, :astate - end - - should 'equal a state of the same name' do - assert_equal new_state, new_state - end - - should 'send a message to the record for an action if the action is present as a symbol' do - state = new_state(:entering => :foo) - mock(record = Object.new).foo - state.call_action(:entering, record) - end - - should 'send a message to the record for an action if the action is present as a string' do - state = new_state(:entering => 'foo') - mock(record = Object.new).foo - state.call_action(:entering, record) - end - - should 'call a proc with the record as its argument for an action if the action is present as a proc' do - state = new_state(:entering => Proc.new {|r| r.foobar}) - mock(record = Object.new).foobar - state.call_action(:entering, record) - end - - should 'send a message to the record for each action if the action is present as an array' do - state = new_state(:entering => [:a, :b, 'c', lambda {|r| r.foobar}]) - - record = Object.new - mock(record).a - mock(record).b - mock(record).c - mock(record).foobar - - state.call_action(:entering, record) - end - - end -end diff --git a/vendor/gems/aasm-2.2.0/test/unit/state_transition_test.rb b/vendor/gems/aasm-2.2.0/test/unit/state_transition_test.rb deleted file mode 100644 index ed226287..00000000 --- a/vendor/gems/aasm-2.2.0/test/unit/state_transition_test.rb +++ /dev/null @@ -1,75 +0,0 @@ -require 'test_helper' - -class StateTransitionTest < Test::Unit::TestCase - context 'state transition' do - setup do - @opts = {:from => 'foo', :to => 'bar', :guard => 'g'} - @st = AASM::SupportingClasses::StateTransition.new(@opts) - end - - should 'set from, to, and opts attr readers' do - assert_equal @opts[:from], @st.from - assert_equal @opts[:to], @st.to - assert_equal @opts, @st.options - end - - should 'pass equality check if from and to are the same' do - obj = OpenStruct.new - obj.from = @opts[:from] - obj.to = @opts[:to] - - assert_equal @st, obj - end - - should 'fail equality check if from is not the same' do - obj = OpenStruct.new - obj.from = 'blah' - obj.to = @opts[:to] - - assert_not_equal @st, obj - end - - should 'fail equality check if to is not the same' do - obj = OpenStruct.new - obj.from = @opts[:from] - obj.to = 'blah' - - assert_not_equal @st, obj - end - - context 'when performing guard checks' do - should 'return true if there is no guard' do - opts = {:from => 'foo', :to => 'bar'} - st = AASM::SupportingClasses::StateTransition.new(opts) - assert st.perform(nil) - end - - should 'call the method on the object if guard is a symbol' do - opts = {:from => 'foo', :to => 'bar', :guard => :test_guard} - st = AASM::SupportingClasses::StateTransition.new(opts) - - mock(obj = Object.new).test_guard - - st.perform(obj) - end - - should 'call the method on the object if guard is a string' do - opts = {:from => 'foo', :to => 'bar', :guard => 'test_guard'} - st = AASM::SupportingClasses::StateTransition.new(opts) - - mock(obj = Object.new).test_guard - - st.perform(obj) - end - - should 'call the proc passing the object if guard is a proc' do - opts = {:from => 'foo', :to => 'bar', :guard => Proc.new {|o| o.test_guard}} - st = AASM::SupportingClasses::StateTransition.new(opts) - - mock(obj = Object.new).test_guard - - st.perform(obj) - end - end - end -end From c2be07c6c39021c11dfe7fdb36b9d7bd7b872d68 Mon Sep 17 00:00:00 2001 From: Reinier Balt Date: Fri, 10 Jun 2011 22:43:07 +0200 Subject: [PATCH 5/5] update migration to make the default nil instead of empty string to maintain backward compatibility running 2.0 (old aasm) tests on migrated db gives a lot of errors because of the empty string --- db/migrate/20110526192008_adapt_to_new_aasm.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/db/migrate/20110526192008_adapt_to_new_aasm.rb b/db/migrate/20110526192008_adapt_to_new_aasm.rb index 787576bc..206a6ec6 100644 --- a/db/migrate/20110526192008_adapt_to_new_aasm.rb +++ b/db/migrate/20110526192008_adapt_to_new_aasm.rb @@ -1,8 +1,8 @@ class AdaptToNewAasm < ActiveRecord::Migration def self.up - change_column :todos, :state, :string, :limit => 20, :default => "", :null => false - change_column :projects, :state, :string, :limit => 20, :default => "", :null => false - change_column :recurring_todos, :state, :string, :limit => 20, :default => "", :null => false + change_column_default :todos, :state, nil + change_column_default :projects, :state, nil + change_column_default :recurring_todos, :state, nil end def self.down