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..13819cf2 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 => :set_completed_at_date, :exit => :clear_completed_at_date - 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 @@ -92,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 @@ -106,7 +118,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..e46ad36e 100644 --- a/app/models/recurring_todo.rb +++ b/app/models/recurring_todo.rb @@ -10,20 +10,19 @@ 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| - 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 } + include AASM + aasm_column :state + aasm_initial_state :active + + 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 } - 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 @@ -41,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}'") @@ -94,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 6ddbd5b0..58dcc30a 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 + 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, :exit => Proc.new { |t| t.completed_at = nil } + aasm_state :deferred, :exit => Proc.new { |t| t[:show_from] = nil } + 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 @@ -97,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 @@ -153,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 @@ -214,9 +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 @@ -224,27 +229,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/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/db/migrate/20110526192008_adapt_to_new_aasm.rb b/db/migrate/20110526192008_adapt_to_new_aasm.rb new file mode 100644 index 00000000..206a6ec6 --- /dev/null +++ b/db/migrate/20110526192008_adapt_to_new_aasm.rb @@ -0,0 +1,13 @@ +class AdaptToNewAasm < ActiveRecord::Migration + def self.up + change_column_default :todos, :state, nil + change_column_default :projects, :state, nil + change_column_default :recurring_todos, :state, nil + 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 :recurring_todos, :state, :string, :limit => 20, :default => "active", :null => false + end +end 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/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/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 180f0876..76f61cec 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,26 @@ 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 + 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..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.current_state - t.toggle_completion! - assert_equal :completed, t.current_state - t.toggle_completion! - assert_equal :active, t.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/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/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