mirror of
https://github.com/TracksApp/tracks.git
synced 2025-09-22 05:50:47 +02:00
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
This commit is contained in:
parent
1cf5967eb5
commit
056dbf08a7
37 changed files with 43 additions and 2618 deletions
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
2
test/fixtures/recurring_todos.yml
vendored
2
test/fixtures/recurring_todos.yml
vendored
|
@ -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: ~
|
||||
|
|
|
@ -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!
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
5
vendor/gems/aasm-2.2.0/.document
vendored
5
vendor/gems/aasm-2.2.0/.document
vendored
|
@ -1,5 +0,0 @@
|
|||
README.rdoc
|
||||
lib/**/*.rb
|
||||
bin/*
|
||||
features/**/*.feature
|
||||
LICENSE
|
7
vendor/gems/aasm-2.2.0/.gitignore
vendored
7
vendor/gems/aasm-2.2.0/.gitignore
vendored
|
@ -1,7 +0,0 @@
|
|||
*.sw?
|
||||
*~
|
||||
.DS_Store
|
||||
.idea
|
||||
coverage
|
||||
pkg
|
||||
rdoc
|
137
vendor/gems/aasm-2.2.0/README.rdoc
vendored
137
vendor/gems/aasm-2.2.0/README.rdoc
vendored
|
@ -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 <scott at elitists dot net>
|
||||
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.
|
108
vendor/gems/aasm-2.2.0/Rakefile
vendored
108
vendor/gems/aasm-2.2.0/Rakefile
vendored
|
@ -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
|
||||
|
1
vendor/gems/aasm-2.2.0/VERSION
vendored
1
vendor/gems/aasm-2.2.0/VERSION
vendored
|
@ -1 +0,0 @@
|
|||
2.2.0
|
94
vendor/gems/aasm-2.2.0/aasm.gemspec
vendored
94
vendor/gems/aasm-2.2.0/aasm.gemspec
vendored
|
@ -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<rspec>, [">= 0"])
|
||||
s.add_development_dependency(%q<shoulda>, [">= 0"])
|
||||
s.add_development_dependency(%q<sdoc>, [">= 0"])
|
||||
else
|
||||
s.add_dependency(%q<rspec>, [">= 0"])
|
||||
s.add_dependency(%q<shoulda>, [">= 0"])
|
||||
s.add_dependency(%q<sdoc>, [">= 0"])
|
||||
end
|
||||
else
|
||||
s.add_dependency(%q<rspec>, [">= 0"])
|
||||
s.add_dependency(%q<shoulda>, [">= 0"])
|
||||
s.add_dependency(%q<sdoc>, [">= 0"])
|
||||
end
|
||||
end
|
||||
|
9
vendor/gems/aasm-2.2.0/lib/aasm.rb
vendored
9
vendor/gems/aasm-2.2.0/lib/aasm.rb
vendored
|
@ -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')
|
196
vendor/gems/aasm-2.2.0/lib/aasm/aasm.rb
vendored
196
vendor/gems/aasm-2.2.0/lib/aasm/aasm.rb
vendored
|
@ -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
|
109
vendor/gems/aasm-2.2.0/lib/aasm/event.rb
vendored
109
vendor/gems/aasm-2.2.0/lib/aasm/event.rb
vendored
|
@ -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
|
14
vendor/gems/aasm-2.2.0/lib/aasm/persistence.rb
vendored
14
vendor/gems/aasm-2.2.0/lib/aasm/persistence.rb
vendored
|
@ -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
|
|
@ -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 <tt>aasm_read_state</tt>
|
||||
#
|
||||
# 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 <tt>state</tt> 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 <tt>state</tt> 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 <tt>aasm_current_state</tt>
|
||||
#
|
||||
# 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
|
53
vendor/gems/aasm-2.2.0/lib/aasm/state.rb
vendored
53
vendor/gems/aasm-2.2.0/lib/aasm/state.rb
vendored
|
@ -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
|
32
vendor/gems/aasm-2.2.0/lib/aasm/state_machine.rb
vendored
32
vendor/gems/aasm-2.2.0/lib/aasm/state_machine.rb
vendored
|
@ -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
|
|
@ -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
|
|
@ -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')
|
|
@ -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
|
|
@ -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
|
11
vendor/gems/aasm-2.2.0/spec/spec_helper.rb
vendored
11
vendor/gems/aasm-2.2.0/spec/spec_helper.rb
vendored
|
@ -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
|
462
vendor/gems/aasm-2.2.0/spec/unit/aasm_spec.rb
vendored
462
vendor/gems/aasm-2.2.0/spec/unit/aasm_spec.rb
vendored
|
@ -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
|
|
@ -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
|
|
@ -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
|
126
vendor/gems/aasm-2.2.0/spec/unit/event_spec.rb
vendored
126
vendor/gems/aasm-2.2.0/spec/unit/event_spec.rb
vendored
|
@ -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
|
85
vendor/gems/aasm-2.2.0/spec/unit/state_spec.rb
vendored
85
vendor/gems/aasm-2.2.0/spec/unit/state_spec.rb
vendored
|
@ -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
|
|
@ -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
|
|
@ -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
|
33
vendor/gems/aasm-2.2.0/test/test_helper.rb
vendored
33
vendor/gems/aasm-2.2.0/test/test_helper.rb
vendored
|
@ -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'
|
54
vendor/gems/aasm-2.2.0/test/unit/event_test.rb
vendored
54
vendor/gems/aasm-2.2.0/test/unit/event_test.rb
vendored
|
@ -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
|
69
vendor/gems/aasm-2.2.0/test/unit/state_test.rb
vendored
69
vendor/gems/aasm-2.2.0/test/unit/state_test.rb
vendored
|
@ -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
|
|
@ -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
|
Loading…
Add table
Add a link
Reference in a new issue