ministry_of_state 0.0.1 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: fee29b6c22b9b8a1e96cd23c447879ecffa61e66
4
+ data.tar.gz: 265f34f8d6f14f2a8044fc7018737b28ad29cf39
5
+ SHA512:
6
+ metadata.gz: 95b251d93d73210d8c70497701df729e64abc286b61b5c6f96b83c800e5488f67744152c8318e70b883815391675391f3966600d4696e604fffcf5d010d3ed3e
7
+ data.tar.gz: 3bd244877747f72622cea22d3bf73cceaa5ab6fbd241a7f8e3e248c49e46ffdacec86f2aca7dc8c161fe0dcd236d9ec7a12ca826e5bb71a7dfa787263875b271
data/.gitignore ADDED
@@ -0,0 +1,52 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ InstalledFiles
6
+ lib/bundler/man
7
+ test/tmp
8
+ test/version_tmp
9
+ tmp
10
+
11
+ pkg # jeweler generated
12
+
13
+ # yard generated
14
+ doc/
15
+ .yardoc
16
+ _yardoc
17
+
18
+ spec/reports
19
+ coverage # rcov generated
20
+ rdoc # rdoc generated
21
+
22
+ # sqlite3 database
23
+ *.sqlite3
24
+ *.sqlite
25
+
26
+ Gemfile.lock
27
+
28
+ .rvmrc
29
+ .ruby-version
30
+ .ruby-gemset
31
+ .powrc
32
+
33
+ # For MacOS:
34
+ .DS_Store
35
+
36
+ # For TextMate
37
+ *.tmproj
38
+ tmtags
39
+
40
+ # For emacs:
41
+ *~
42
+ \#*
43
+ .\#*
44
+
45
+ # For vim:
46
+ *.swp
47
+
48
+ # for rubymine IDE
49
+ .idea/
50
+
51
+ vendor
52
+
data/.travis.yml ADDED
@@ -0,0 +1,11 @@
1
+ language: ruby
2
+ rvm:
3
+ - 1.9.3
4
+ - 2.0.0
5
+
6
+ gemfile:
7
+ - Gemfile
8
+ - gemfiles/Gemfile.rails-3.2.13
9
+
10
+ script:
11
+ - bundle exec rake test
data/Gemfile CHANGED
@@ -1,10 +1,4 @@
1
- source "http://rubygems.org"
1
+ source "https://rubygems.org"
2
2
 
3
- gem 'rails', "3.0.3"
4
- gem 'mysql2'
3
+ gemspec
5
4
 
6
- group :development do
7
- gem "shoulda", ">= 0"
8
- gem "bundler", "~> 1.0.0"
9
- gem "jeweler", "~> 1.5.2"
10
- end
data/LICENSE.txt CHANGED
@@ -1,4 +1,6 @@
1
- Copyright (c) 2011 Hemant Kumar
1
+ Copyright (c) 2013 Hemant Kumar
2
+
3
+ MIT License
2
4
 
3
5
  Permission is hereby granted, free of charge, to any person obtaining
4
6
  a copy of this software and associated documentation files (the
data/README.rdoc CHANGED
@@ -2,7 +2,11 @@
2
2
 
3
3
  Because State machines are simple, they do not have to be greater than 2000 lines of code (and complexity).
4
4
 
5
+ {<img src="https://travis-ci.org/code-mancers/ministry_of_state.png" />}[https://travis-ci.org/code-mancers/ministry_of_state]
6
+ {<img src="https://codeclimate.com/repos/51d2f06213d6373729049ad3/badges/b353d7ce9d30e4c37c2f/gpa.png" />}[https://codeclimate.com/repos/51d2f06213d6373729049ad3/feed]
7
+
5
8
  = Features
9
+ * Supports rails4 now. No changes required.
6
10
  * Events are wrapped in a transaction and record is locked before going for a state change.
7
11
  * Ignores dirty attributes (still on the fence with this one)
8
12
  * Events and states can be inhereted across classes.
@@ -12,17 +16,33 @@ Because State machines are simple, they do not have to be greater than 2000 line
12
16
 
13
17
  class User < ActiveRecord::Base
14
18
  include MinistryOfState
15
- ministry_of_state(:initial_state => 'pending', :state_column => 'status' )
16
- add_state :active
17
- add_state :pending_payment
18
-
19
- add_event(:activate) do
20
- transitions(:from => :pending, :to => :active)
19
+ ministry_of_state('status') do
20
+ add_initial_state 'pending'
21
+ add_state :active
22
+ add_state :pending_payment
23
+
24
+ add_event(:activate) do
25
+ transitions(:from => :pending, :to => :active)
26
+ end
21
27
  end
22
28
  end
23
29
 
30
+ = Installation
31
+
32
+ Add this line to your application's Gemfile:
33
+
34
+ gem 'ministry_of_state'
35
+
36
+ And then execute:
37
+
38
+ $ bundle
39
+
40
+ Or install it yourself as:
41
+
42
+ $ gem ministry_of_state
43
+
24
44
  == Contributing to ministry_of_state
25
-
45
+
26
46
  * Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet
27
47
  * Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it
28
48
  * Fork the project
@@ -35,5 +55,3 @@ Because State machines are simple, they do not have to be greater than 2000 line
35
55
 
36
56
  Copyright (c) 2011 Hemant, Neeraj and Vishnu. See LICENSE.txt for
37
57
  further details.
38
-
39
-
data/Rakefile CHANGED
@@ -7,33 +7,21 @@ rescue Bundler::BundlerError => e
7
7
  $stderr.puts "Run `bundle install` to install missing gems"
8
8
  exit e.status_code
9
9
  end
10
- require 'rake'
11
10
 
12
- require 'jeweler'
13
- Jeweler::Tasks.new do |gem|
14
- # gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
15
- gem.name = "ministry_of_state"
16
- gem.homepage = "http://github.com/gnufied/ministry_of_state"
17
- gem.license = "MIT"
18
- gem.summary = %Q{Handling state machines}
19
- gem.description = %Q{A ActiveRecord plugin for working with state machines}
20
- gem.email = "hkumar@crri.co.in"
21
- gem.authors = ["Hemant Kumar"]
22
- end
11
+ require "bundler/gem_tasks"
23
12
 
24
- Jeweler::RubygemsDotOrgTasks.new
13
+ require 'rake'
25
14
 
26
15
  require 'rake/testtask'
27
16
  Rake::TestTask.new(:test) do |test|
28
- test.libs << 'lib' << 'test'
17
+ test.libs << 'lib' << 'test' << "./"
29
18
  test.pattern = 'test/**/test_*.rb'
30
19
  test.verbose = true
31
20
  end
32
21
 
33
-
34
22
  task :default => :test
35
23
 
36
- require 'rake/rdoctask'
24
+ require 'rdoc/task'
37
25
  Rake::RDocTask.new do |rdoc|
38
26
  version = File.exist?('VERSION') ? File.read('VERSION') : ""
39
27
 
@@ -0,0 +1,6 @@
1
+ # -*- ruby -*-
2
+
3
+ source "http://rubygems.org"
4
+
5
+ gemspec path: '..'
6
+ gem 'rails', "~> 3.2.13"
@@ -1,4 +1,6 @@
1
1
  module MinistryOfState
2
- VERSION = "0.0.1"
2
+ unless MinistryOfState.const_defined?(:VERSION)
3
+ VERSION = "0.0.2"
4
+ end
3
5
  require "ministry_of_state/railtie"
4
6
  end
@@ -1,42 +1,80 @@
1
1
  module MinistryOfState
2
2
  extend ActiveSupport::Concern
3
3
 
4
+ class InvalidState < StandardError; end
5
+ class NoInitialState < StandardError; end
6
+ class TransitionNotAllowed < StandardError; end
7
+ class InvalidStateColumn < StandardError; end
8
+
9
+ class MosState
10
+ def initialize(name, column, opts)
11
+ @name, @column, @opts = name, column, opts
12
+ end
13
+
14
+ attr_reader :name, :column, :opts
15
+
16
+ def initial?
17
+ opts[:initial]
18
+ end
19
+ end
20
+
21
+ class MosEvent
22
+ def initialize(name, column, opts)
23
+ @name, @column, @opts = name, column, opts
24
+ end
25
+
26
+ attr_reader :name, :column, :opts
27
+ end
4
28
 
5
- class InvalidState < Exception; end
6
- class NoInitialState < Exception; end
7
- class TransitionNotAllowed < Exception; end
8
- class InvalidStateColumn < Exception; end
9
-
10
29
  module ClassMethods
11
- def ministry_of_state(opts = {})
12
- class_attribute :states
13
- class_attribute :events
14
30
 
15
- class_attribute :initial_state
16
- class_attribute :state_column
31
+ # create a hash for states
32
+ def prepare_mos_attributes
33
+ unless self.respond_to?(:states)
34
+ class_attribute :states
35
+ class_attribute :events
36
+
37
+ self.states = HashWithIndifferentAccess.new
38
+ self.events = HashWithIndifferentAccess.new
39
+
40
+ before_create :set_initial_states
41
+ after_create :run_initial_state_actions
42
+ end
43
+ end
44
+
45
+ def get_initial_state_for(column)
46
+ self.states.each do |name, state|
47
+ return state if column == state.column && state.initial?
48
+ end
49
+ nil
50
+ end
17
51
 
18
- raise NoInitialState.new("You need to specify initial state") unless opts[:initial_state]
52
+ def ministry_of_state(column)
53
+ prepare_mos_attributes
54
+ @mos_current_column_ = column
55
+ yield
19
56
 
20
- self.initial_state = opts[:initial_state]
21
- self.state_column = opts[:state_column] || 'status'
22
- self.states = HashWithIndifferentAccess.new
23
- self.events = HashWithIndifferentAccess.new
57
+ initial_state = get_initial_state_for(column)
58
+ raise NoInitialState.new("You need to specify initial state") unless initial_state
59
+ end
24
60
 
25
- add_state(self.initial_state)
26
- before_create :set_initial_state
27
- after_create :run_initial_state_actions
61
+ def add_initial_state(name)
62
+ add_state(name, :initial => true)
28
63
  end
29
64
 
30
65
  def add_state(name, options={})
31
- self.states.merge!(name => options)
66
+ state = MosState.new(name.to_s, @mos_current_column_, options)
67
+ self.states.merge!(name.to_s => state)
32
68
  class_eval <<-RUBY,__FILE__,__LINE__+1
33
- def #{name}?; check_state('#{name}'); end
69
+ def #{name.to_s}?; check_state('#{name}'); end
34
70
  RUBY
35
71
  end
36
72
 
37
- def add_event(name, &block)
38
- opts = class_eval(&block)
39
- self.events.merge!(name => opts)
73
+ def add_event(name, options = {},&block)
74
+ opts = yield
75
+ event_options = opts.merge(options)
76
+ event = MosEvent.new(name.to_s, @mos_current_column_, event_options)
77
+ self.events.merge!(name.to_s => event)
40
78
  class_eval <<-RUBY,__FILE__,__LINE__+1
41
79
  def #{name.to_s}!
42
80
  fire('#{name}')
@@ -53,83 +91,101 @@ module MinistryOfState
53
91
  end
54
92
  end
55
93
 
56
- module InstanceMethods
57
-
58
- def set_initial_state
94
+ def set_initial_states
95
+ states.each do |name, state|
96
+ next unless state.initial?
97
+
59
98
  begin
60
- enter = states[initial_state][:enter]
99
+ enter = state.opts[:enter]
61
100
  invoke_callback(enter) if enter
62
101
  true
63
102
  rescue StandardError => e
64
103
  errors.add(:base, e.to_s)
65
104
  false
66
105
  end
67
- write_attribute state_machine_column, initial_state
106
+ default_state = read_attribute( state_machine_column(state.column) )
107
+ write_attribute(state_machine_column(state.column), state.name) unless default_state
68
108
  end
109
+ end
110
+
111
+ def run_initial_state_actions
112
+ states.each do |name, state|
113
+ next unless state.initial?
69
114
 
70
- def run_initial_state_actions
71
115
  begin
72
- after = states[initial_state][:after]
73
- invoke_callback(after) if after
116
+ after = state.opts[:after]
117
+ invoke_callback(enter) if after
74
118
  true
75
119
  rescue StandardError => e
76
120
  errors.add(:base, e.to_s)
77
121
  false
78
122
  end
79
123
  end
124
+ end
80
125
 
81
- def current_state
82
- send("#{state_machine_column}_was").to_sym
83
- end
126
+ def current_state(column)
127
+ send("#{column}_was").to_sym
128
+ end
84
129
 
85
- def check_state(state)
86
- send("#{state_machine_column}_was") == state.to_s
87
- end
130
+ def check_state(state)
131
+ column = states[state].column
132
+ send("#{column}_was") == state.to_s
133
+ end
88
134
 
89
- def fire(event)
90
- options = events[event]
91
- to_state = options[:to]
92
- raise TransitionNotAllowed.new("Invalid 'to' state '#{to_state}'") unless states[to_state]
93
- check_guard = options[:guard] ? invoke_callback(options[:guard]) : true
94
- return unless check_guard
95
- begin
96
- transaction do
97
- enter = states[to_state][:enter]
98
- after = states[to_state][:after]
99
- exit = states[to_state][:exit]
100
-
101
- invoke_callback(enter) if enter
102
- self.lock!
103
- t_current_state = send(state_machine_column).try(:to_sym)
104
- check_transitions?(t_current_state, options)
105
- write_attribute(state_machine_column,to_state.to_s)
106
- save
107
- invoke_callback(exit) if exit
108
- invoke_callback(after) if after
109
- end
110
- self.errors.empty?
111
- rescue StandardError => e
112
- errors.add(:base, e.to_s)
113
- false
114
- end
115
- end
135
+ def fire(event)
136
+ options = events[event].opts
137
+ to_state = options[:to]
138
+ column = events[event].column
139
+
140
+ raise TransitionNotAllowed.new("Invalid 'to' state '#{to_state}'") unless states[to_state]
141
+ check_guard = options[:guard] ? invoke_callback(options[:guard]) : true
142
+ return unless check_guard
116
143
 
117
- def state_machine_column
118
- if(self.class.column_names.include?(state_column))
119
- state_column
120
- else
121
- raise InvalidStateColumn.new("State column '#{state_column}' does not exist in table '#{self.class.table_name}'")
144
+ before_event_callback = options[:before]
145
+ after_event_callback = options[:after]
146
+
147
+ enter = states[to_state].opts[:enter]
148
+ after = states[to_state].opts[:after]
149
+ exit = states[to_state].opts[:exit]
150
+
151
+ invoke_callback(before_event_callback) if before_event_callback
152
+ invoke_callback(enter) if enter
153
+
154
+ begin
155
+ transaction do
156
+ self.lock!
157
+ t_current_state = send( state_machine_column(column) ).try(:to_sym)
158
+ check_transitions?(t_current_state, options)
159
+ write_attribute( state_machine_column(column), to_state.to_s )
160
+ save
122
161
  end
162
+
163
+ invoke_callback(exit) if exit
164
+ invoke_callback(after) if after
165
+ invoke_callback(after_event_callback) if after_event_callback
166
+
167
+ self.errors.empty?
168
+ rescue StandardError => e
169
+ errors.add(:base, e.to_s)
170
+ false
123
171
  end
124
-
125
- def check_transitions?(t_current_state, opts)
126
- unless opts[:from].include?(t_current_state)
127
- raise InvalidState.new("Invalid from state '#{t_current_state}' for target state '#{opts[:to]}'")
128
- end
172
+ end
173
+
174
+ def state_machine_column(column)
175
+ if(self.class.column_names.include?(column))
176
+ column
177
+ else
178
+ raise InvalidStateColumn.new("State column '#{column}' does not exist in table '#{self.class.table_name}'")
129
179
  end
180
+ end
130
181
 
131
- def invoke_callback(callback)
132
- callback.is_a?(Proc) ? callback.call(self) : send(callback)
182
+ def check_transitions?(t_current_state, opts)
183
+ unless opts[:from].include?(t_current_state)
184
+ raise InvalidState.new("Invalid from state '#{t_current_state}' for target state '#{opts[:to]}'")
133
185
  end
134
186
  end
187
+
188
+ def invoke_callback(callback)
189
+ callback.is_a?(Proc) ? callback.call(self) : send(callback)
190
+ end
135
191
  end
@@ -2,7 +2,6 @@ require "rails"
2
2
  require "active_record"
3
3
  require "active_support"
4
4
  require "active_support/core_ext/class"
5
- require "active_support/memoizable"
6
5
  require File.dirname(__FILE__) + "/ministry_of_state"
7
6
 
8
7
  module MinistryOfState
@@ -0,0 +1,3 @@
1
+ module MinistryOfState
2
+ VERSION = "0.1.0"
3
+ end
@@ -1,78 +1,34 @@
1
- # Generated by jeweler
2
- # DO NOT EDIT THIS FILE DIRECTLY
3
- # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
- # -*- encoding: utf-8 -*-
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'ministry_of_state/version'
5
5
 
6
- Gem::Specification.new do |s|
7
- s.name = %q{ministry_of_state}
8
- s.version = "0.0.1"
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "ministry_of_state"
8
+ spec.version = MinistryOfState::VERSION
9
9
 
10
- s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
- s.authors = ["Hemant Kumar"]
12
- s.date = %q{2011-02-01}
13
- s.description = %q{A ActiveRecord plugin for working with state machines}
14
- s.email = %q{hkumar@crri.co.in}
15
- s.extra_rdoc_files = [
16
- "LICENSE.txt",
17
- "README.rdoc"
18
- ]
19
- s.files = [
20
- ".document",
21
- "Gemfile",
22
- "Gemfile.lock",
23
- "LICENSE.txt",
24
- "README.rdoc",
25
- "Rakefile",
26
- "VERSION",
27
- "lib/ministry_of_state.rb",
28
- "lib/ministry_of_state/ministry_of_state.rb",
29
- "lib/ministry_of_state/railtie.rb",
30
- "ministry_of_state.gemspec",
31
- "test/article.rb",
32
- "test/blog.rb",
33
- "test/helper.rb",
34
- "test/post.rb",
35
- "test/student.rb",
36
- "test/test_ministry_of_state.rb",
37
- "test/user.rb"
38
- ]
39
- s.homepage = %q{http://github.com/gnufied/ministry_of_state}
40
- s.licenses = ["MIT"]
41
- s.require_paths = ["lib"]
42
- s.rubygems_version = %q{1.4.1}
43
- s.summary = %q{Handling state machines}
44
- s.test_files = [
45
- "test/article.rb",
46
- "test/blog.rb",
47
- "test/helper.rb",
48
- "test/post.rb",
49
- "test/student.rb",
50
- "test/test_ministry_of_state.rb",
51
- "test/user.rb"
52
- ]
10
+ spec.authors = ["Hemant Kumar"]
11
+ spec.email = ["gethemant@gmail.com"]
12
+ spec.description = %q{A ActiveRecord plugin for working with state machines}
13
+ spec.summary = %q{Handling state machines}
14
+ spec.homepage = %q{http://github.com/gnufied/ministry_of_state}
53
15
 
54
- if s.respond_to? :specification_version then
55
- s.specification_version = 3
16
+ spec.license = "MIT"
56
17
 
57
- if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
58
- s.add_runtime_dependency(%q<rails>, ["= 3.0.3"])
59
- s.add_runtime_dependency(%q<mysql2>, [">= 0"])
60
- s.add_development_dependency(%q<shoulda>, [">= 0"])
61
- s.add_development_dependency(%q<bundler>, ["~> 1.0.0"])
62
- s.add_development_dependency(%q<jeweler>, ["~> 1.5.2"])
63
- else
64
- s.add_dependency(%q<rails>, ["= 3.0.3"])
65
- s.add_dependency(%q<mysql2>, [">= 0"])
66
- s.add_dependency(%q<shoulda>, [">= 0"])
67
- s.add_dependency(%q<bundler>, ["~> 1.0.0"])
68
- s.add_dependency(%q<jeweler>, ["~> 1.5.2"])
69
- end
70
- else
71
- s.add_dependency(%q<rails>, ["= 3.0.3"])
72
- s.add_dependency(%q<mysql2>, [">= 0"])
73
- s.add_dependency(%q<shoulda>, [">= 0"])
74
- s.add_dependency(%q<bundler>, ["~> 1.0.0"])
75
- s.add_dependency(%q<jeweler>, ["~> 1.5.2"])
76
- end
77
- end
18
+ spec.files = `git ls-files`.split($/)
19
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
20
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
21
+ spec.require_paths = ["lib"]
22
+
23
+ spec.has_rdoc = true
24
+ spec.extra_rdoc_files = ["LICENSE.txt",
25
+ "README.rdoc"]
78
26
 
27
+ spec.add_dependency "rails", ">= 3.2.13"
28
+
29
+ spec.add_development_dependency "bundler", "~> 1.3"
30
+ spec.add_development_dependency "rake"
31
+ spec.add_development_dependency "sqlite3", "~> 1.3.7"
32
+ spec.add_development_dependency "shoulda", "~> 3.5.0"
33
+ spec.add_development_dependency "mocha", "~> 0.14.0"
34
+ end
data/test/article.rb CHANGED
@@ -1,4 +1,8 @@
1
1
  class Article < ActiveRecord::Base
2
- include MinistryOfState
3
- ministry_of_state(:initial_state => 'pending', :state_column => 'status' )
2
+ include MinistryOfState
3
+
4
+ ministry_of_state('status') do
5
+ add_initial_state 'pending'
6
+ end
7
+
4
8
  end
data/test/blog.rb CHANGED
@@ -2,13 +2,17 @@ class Blog < ActiveRecord::Base
2
2
  include MinistryOfState
3
3
  validates_presence_of :text
4
4
 
5
- ministry_of_state(:initial_state => 'pending', :state_column => 'status' )
6
- attr_accessor :foo
7
- add_state :approved, :enter => :test_method
5
+ attr_accessor :foo
8
6
 
9
- add_event :approve do
10
- transitions :from => 'pending', :to => 'approved'
11
- end
7
+ ministry_of_state('status') do
8
+ add_initial_state 'pending'
9
+
10
+ add_state :approved, :enter => :test_method
11
+
12
+ add_event :approve do
13
+ transitions :from => 'pending', :to => 'approved'
14
+ end
15
+ end
12
16
 
13
17
  def test_method
14
18
  @foo = true
data/test/cargo.rb ADDED
@@ -0,0 +1,26 @@
1
+ class Cargo < ActiveRecord::Base
2
+ include MinistryOfState
3
+
4
+ ministry_of_state('payment') do
5
+ add_initial_state 'unpaid'
6
+ add_state :paid
7
+
8
+ add_event(:pay) do
9
+ transitions(:from => :unpaid, :to => :paid)
10
+ end
11
+ end
12
+
13
+ ministry_of_state('shippment') do
14
+ add_initial_state 'unshipped'
15
+ add_state :shipped
16
+ add_state :delivered
17
+
18
+ add_event(:bill_paid) do
19
+ transitions(:from => :unshipped, :to => :shipped)
20
+ end
21
+
22
+ add_event(:cargo_delivered) do
23
+ transitions(:from => :shipped, :to => :delivered)
24
+ end
25
+ end
26
+ end
data/test/helper.rb CHANGED
@@ -10,6 +10,11 @@ end
10
10
  require 'test/unit'
11
11
  require 'shoulda'
12
12
 
13
+ # TODO: Fix this one when shoulda-context patches MiniTest::Unit::TestCase
14
+ if defined?(MiniTest::Unit::TestCase)
15
+ MiniTest::Unit::TestCase.class_eval { include ShouldaContextLoadable }
16
+ end
17
+
13
18
  $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
14
19
  $LOAD_PATH.unshift(File.dirname(__FILE__))
15
20
  require 'ministry_of_state'
data/test/post.rb CHANGED
@@ -1,18 +1,26 @@
1
1
  class Post < ActiveRecord::Base
2
2
  include MinistryOfState
3
- ministry_of_state(:initial_state => 'pending', :state_column => 'status' )
3
+ attr_accessor :public, :private
4
+ attr_accessor :published_flag, :archived_flag
4
5
 
5
- add_state :published, :after => :make_public
6
- add_state :archived, :enter => :make_private
6
+ ministry_of_state('status') do
7
+ add_initial_state 'pending'
8
+ add_state :published, :after => :make_public
9
+ add_state :archived, :enter => :make_private
7
10
 
8
- attr_accessor :public, :private
9
11
 
10
- add_event(:publish) do
11
- transitions(:from => :pending, :to => :published)
12
+
13
+ add_event(:publish, :before => :about_to_publish) do
14
+ transitions(:from => :pending, :to => :published)
15
+ end
16
+
17
+ add_event(:archive, :after => lambda { |x| x.archived_flag = true }) do
18
+ transitions(:from => [:pending,:published], :to => :archived)
19
+ end
12
20
  end
13
21
 
14
- add_event(:archive) do
15
- transitions(:from => [:pending,:published], :to => :archived)
22
+ def about_to_publish
23
+ @published_flag = true
16
24
  end
17
25
 
18
26
  def make_public
data/test/student.rb CHANGED
@@ -1,11 +1,13 @@
1
1
  class Student < User
2
- add_state :foo
3
-
4
- add_event(:activate) do
5
- transitions(:from => [:foo,:pending],:to => :active)
6
- end
2
+ ministry_of_state('status') do
3
+ add_state :foo
4
+
5
+ add_event(:activate) do
6
+ transitions(:from => [:foo,:pending],:to => :active)
7
+ end
7
8
 
8
- add_event(:make_foo) do
9
- transitions(:from => [:pending,:active], :to => :foo)
9
+ add_event(:make_foo) do
10
+ transitions(:from => [:pending,:active], :to => :foo)
11
+ end
10
12
  end
11
13
  end
@@ -4,13 +4,13 @@ require File.dirname(__FILE__) + '/user'
4
4
  require File.dirname(__FILE__) + '/article'
5
5
  require File.dirname(__FILE__) + '/student'
6
6
  require File.dirname(__FILE__) + '/post'
7
+ require File.dirname(__FILE__) + '/cargo'
7
8
 
8
9
  ActiveRecord::Base.configurations = {
9
10
  'db1' => {
10
- :adapter => 'mysql2',
11
- :username => 'root',
11
+ :adapter => 'sqlite3',
12
12
  :encoding => 'utf8',
13
- :database => 'ministry_of_state_test',
13
+ :database => ':memory:',
14
14
  }
15
15
  }
16
16
 
@@ -25,7 +25,7 @@ class TestMinistryOfState < ActiveSupport::TestCase
25
25
  t.column :status, :string
26
26
  t.timestamps
27
27
  end
28
-
28
+
29
29
  User.connection.drop_table('users') if User.connection.table_exists?(:users)
30
30
  User.connection.create_table :users do |u|
31
31
  u.string :status
@@ -51,6 +51,12 @@ class TestMinistryOfState < ActiveSupport::TestCase
51
51
  p.text :content
52
52
  p.timestamps
53
53
  end
54
+
55
+ Cargo.connection.drop_table('cargos') if Cargo.connection.table_exists?(:cargos)
56
+ Cargo.connection.create_table :cargos do |c|
57
+ c.string :payment
58
+ c.string :shippment
59
+ end
54
60
  end
55
61
 
56
62
  context "User should be able to define state" do
@@ -117,10 +123,12 @@ class TestMinistryOfState < ActiveSupport::TestCase
117
123
  assert_raise(MinistryOfState::TransitionNotAllowed) do
118
124
  class Foo < ActiveRecord::Base
119
125
  include MinistryOfState
120
- ministry_of_state(:state_column => 'status',:initial_state => :pending)
121
- add_state :active
122
- add_event(:activate) do
123
- transitions(:to => :active)
126
+ ministry_of_state('status') do
127
+ add_initial_state :pending
128
+ add_state :active
129
+ add_event(:activate) do
130
+ transitions(:to => :active)
131
+ end
124
132
  end
125
133
  end
126
134
  end
@@ -132,7 +140,8 @@ class TestMinistryOfState < ActiveSupport::TestCase
132
140
  assert_raise(MinistryOfState::NoInitialState) do
133
141
  class Note < ActiveRecord::Base
134
142
  include MinistryOfState
135
- ministry_of_state(:state_column => 'status' )
143
+ ministry_of_state('status') do
144
+ end
136
145
  end
137
146
  end
138
147
  end
@@ -144,17 +153,22 @@ class TestMinistryOfState < ActiveSupport::TestCase
144
153
  end
145
154
  should "call proper callbacks" do
146
155
  assert @post.pending?
156
+
147
157
  assert_nil @post.public
158
+ assert_nil @post.published_flag
148
159
 
149
160
  assert @post.publish!
150
161
  assert @post.published?
151
- assert_equal :published, @post.current_state
162
+ assert_equal :published, @post.current_state('status')
152
163
  assert @post.public
164
+ assert @post.published_flag
153
165
 
154
166
  assert_nil @post.private
167
+ assert_nil @post.archived_flag
155
168
  assert @post.archive!
156
169
  assert @post.archived?
157
170
  assert @post.private
171
+ assert @post.archived_flag
158
172
  end
159
173
  end
160
174
 
@@ -186,4 +200,31 @@ class TestMinistryOfState < ActiveSupport::TestCase
186
200
  end
187
201
 
188
202
  end
203
+
204
+ context "for cargo with multiple stages" do
205
+ setup do
206
+ @cargo = Cargo.create
207
+ end
208
+
209
+ should "able to be delivered to destination" do
210
+ assert @cargo.unpaid?
211
+ assert @cargo.pay!
212
+ assert @cargo.paid?
213
+
214
+ assert @cargo.unshipped?
215
+ assert @cargo.bill_paid!
216
+ assert @cargo.shipped?
217
+ assert @cargo.cargo_delivered!
218
+ assert @cargo.delivered?
219
+ end
220
+ end
221
+
222
+ context "honour default states set by user" do
223
+ should "able to honour default state" do
224
+ @cargo = Cargo.new
225
+ @cargo.payment = 'paid'
226
+ @cargo.save
227
+ assert @cargo.paid?
228
+ end
229
+ end
189
230
  end
data/test/user.rb CHANGED
@@ -3,22 +3,24 @@ class User < ActiveRecord::Base
3
3
  validates_presence_of :gender, :on => :update, :if => :allow_gender_validation
4
4
  validates_presence_of :firstname, :lastname
5
5
 
6
- ministry_of_state(:initial_state => 'pending', :state_column => 'status' )
7
- add_state :active
8
- add_state :pending_payment
9
-
10
- add_event(:activate) do
11
- transitions(:from => :pending, :to => :active)
12
- end
6
+ ministry_of_state('status') do
7
+ add_initial_state 'pending'
8
+ add_state :active
9
+ add_state :pending_payment
13
10
 
14
- add_event(:pending_payment) do
15
- transitions(:from => :active, :to => :pending_payment)
16
- end
11
+ add_event(:activate) do
12
+ transitions(:from => :pending, :to => :active)
13
+ end
17
14
 
18
- add_event(:foobar) do
19
- transitions(:from => :pending, :to => :foobar)
15
+ add_event(:pending_payment) do
16
+ transitions(:from => :active, :to => :pending_payment)
17
+ end
18
+
19
+ add_event(:foobar) do
20
+ transitions(:from => :pending, :to => :foobar)
21
+ end
20
22
  end
21
-
23
+
22
24
  def allow_gender_validation
23
25
  !pending?
24
26
  end
metadata CHANGED
@@ -1,164 +1,158 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: ministry_of_state
3
- version: !ruby/object:Gem::Version
4
- hash: 29
5
- prerelease:
6
- segments:
7
- - 0
8
- - 0
9
- - 1
10
- version: 0.0.1
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
11
5
  platform: ruby
12
- authors:
6
+ authors:
13
7
  - Hemant Kumar
14
8
  autorequire:
15
9
  bindir: bin
16
10
  cert_chain: []
17
-
18
- date: 2011-02-01 00:00:00 +05:30
19
- default_executable:
20
- dependencies:
21
- - !ruby/object:Gem::Dependency
22
- type: :runtime
23
- version_requirements: &id001 !ruby/object:Gem::Requirement
24
- none: false
25
- requirements:
26
- - - "="
27
- - !ruby/object:Gem::Version
28
- hash: 1
29
- segments:
30
- - 3
31
- - 0
32
- - 3
33
- version: 3.0.3
34
- requirement: *id001
35
- prerelease: false
11
+ date: 2013-09-02 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
36
14
  name: rails
37
- - !ruby/object:Gem::Dependency
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - '>='
18
+ - !ruby/object:Gem::Version
19
+ version: 3.2.13
38
20
  type: :runtime
39
- version_requirements: &id002 !ruby/object:Gem::Requirement
40
- none: false
41
- requirements:
42
- - - ">="
43
- - !ruby/object:Gem::Version
44
- hash: 3
45
- segments:
46
- - 0
47
- version: "0"
48
- requirement: *id002
49
21
  prerelease: false
50
- name: mysql2
51
- - !ruby/object:Gem::Dependency
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - '>='
25
+ - !ruby/object:Gem::Version
26
+ version: 3.2.13
27
+ - !ruby/object:Gem::Dependency
28
+ name: bundler
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ~>
32
+ - !ruby/object:Gem::Version
33
+ version: '1.3'
52
34
  type: :development
53
- version_requirements: &id003 !ruby/object:Gem::Requirement
54
- none: false
55
- requirements:
56
- - - ">="
57
- - !ruby/object:Gem::Version
58
- hash: 3
59
- segments:
60
- - 0
61
- version: "0"
62
- requirement: *id003
63
35
  prerelease: false
64
- name: shoulda
65
- - !ruby/object:Gem::Dependency
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ~>
39
+ - !ruby/object:Gem::Version
40
+ version: '1.3'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rake
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - '>='
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
66
48
  type: :development
67
- version_requirements: &id004 !ruby/object:Gem::Requirement
68
- none: false
69
- requirements:
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: sqlite3
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
70
59
  - - ~>
71
- - !ruby/object:Gem::Version
72
- hash: 23
73
- segments:
74
- - 1
75
- - 0
76
- - 0
77
- version: 1.0.0
78
- requirement: *id004
60
+ - !ruby/object:Gem::Version
61
+ version: 1.3.7
62
+ type: :development
79
63
  prerelease: false
80
- name: bundler
81
- - !ruby/object:Gem::Dependency
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ~>
67
+ - !ruby/object:Gem::Version
68
+ version: 1.3.7
69
+ - !ruby/object:Gem::Dependency
70
+ name: shoulda
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ~>
74
+ - !ruby/object:Gem::Version
75
+ version: 3.5.0
82
76
  type: :development
83
- version_requirements: &id005 !ruby/object:Gem::Requirement
84
- none: false
85
- requirements:
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ~>
81
+ - !ruby/object:Gem::Version
82
+ version: 3.5.0
83
+ - !ruby/object:Gem::Dependency
84
+ name: mocha
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
86
87
  - - ~>
87
- - !ruby/object:Gem::Version
88
- hash: 7
89
- segments:
90
- - 1
91
- - 5
92
- - 2
93
- version: 1.5.2
94
- requirement: *id005
88
+ - !ruby/object:Gem::Version
89
+ version: 0.14.0
90
+ type: :development
95
91
  prerelease: false
96
- name: jeweler
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ~>
95
+ - !ruby/object:Gem::Version
96
+ version: 0.14.0
97
97
  description: A ActiveRecord plugin for working with state machines
98
- email: hkumar@crri.co.in
98
+ email:
99
+ - gethemant@gmail.com
99
100
  executables: []
100
-
101
101
  extensions: []
102
-
103
- extra_rdoc_files:
102
+ extra_rdoc_files:
104
103
  - LICENSE.txt
105
104
  - README.rdoc
106
- files:
105
+ files:
107
106
  - .document
107
+ - .gitignore
108
+ - .travis.yml
108
109
  - Gemfile
109
- - Gemfile.lock
110
110
  - LICENSE.txt
111
111
  - README.rdoc
112
112
  - Rakefile
113
113
  - VERSION
114
+ - gemfiles/Gemfile.rails-3.2.13
114
115
  - lib/ministry_of_state.rb
115
116
  - lib/ministry_of_state/ministry_of_state.rb
116
117
  - lib/ministry_of_state/railtie.rb
118
+ - lib/ministry_of_state/version.rb
117
119
  - ministry_of_state.gemspec
118
120
  - test/article.rb
119
121
  - test/blog.rb
122
+ - test/cargo.rb
120
123
  - test/helper.rb
121
124
  - test/post.rb
122
125
  - test/student.rb
123
126
  - test/test_ministry_of_state.rb
124
127
  - test/user.rb
125
- has_rdoc: true
126
128
  homepage: http://github.com/gnufied/ministry_of_state
127
- licenses:
129
+ licenses:
128
130
  - MIT
131
+ metadata: {}
129
132
  post_install_message:
130
133
  rdoc_options: []
131
-
132
- require_paths:
134
+ require_paths:
133
135
  - lib
134
- required_ruby_version: !ruby/object:Gem::Requirement
135
- none: false
136
- requirements:
137
- - - ">="
138
- - !ruby/object:Gem::Version
139
- hash: 3
140
- segments:
141
- - 0
142
- version: "0"
143
- required_rubygems_version: !ruby/object:Gem::Requirement
144
- none: false
145
- requirements:
146
- - - ">="
147
- - !ruby/object:Gem::Version
148
- hash: 3
149
- segments:
150
- - 0
151
- version: "0"
136
+ required_ruby_version: !ruby/object:Gem::Requirement
137
+ requirements:
138
+ - - '>='
139
+ - !ruby/object:Gem::Version
140
+ version: '0'
141
+ required_rubygems_version: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - '>='
144
+ - !ruby/object:Gem::Version
145
+ version: '0'
152
146
  requirements: []
153
-
154
147
  rubyforge_project:
155
- rubygems_version: 1.4.1
148
+ rubygems_version: 2.0.3
156
149
  signing_key:
157
- specification_version: 3
150
+ specification_version: 4
158
151
  summary: Handling state machines
159
- test_files:
152
+ test_files:
160
153
  - test/article.rb
161
154
  - test/blog.rb
155
+ - test/cargo.rb
162
156
  - test/helper.rb
163
157
  - test/post.rb
164
158
  - test/student.rb
data/Gemfile.lock DELETED
@@ -1,82 +0,0 @@
1
- GEM
2
- remote: http://rubygems.org/
3
- specs:
4
- abstract (1.0.0)
5
- actionmailer (3.0.3)
6
- actionpack (= 3.0.3)
7
- mail (~> 2.2.9)
8
- actionpack (3.0.3)
9
- activemodel (= 3.0.3)
10
- activesupport (= 3.0.3)
11
- builder (~> 2.1.2)
12
- erubis (~> 2.6.6)
13
- i18n (~> 0.4)
14
- rack (~> 1.2.1)
15
- rack-mount (~> 0.6.13)
16
- rack-test (~> 0.5.6)
17
- tzinfo (~> 0.3.23)
18
- activemodel (3.0.3)
19
- activesupport (= 3.0.3)
20
- builder (~> 2.1.2)
21
- i18n (~> 0.4)
22
- activerecord (3.0.3)
23
- activemodel (= 3.0.3)
24
- activesupport (= 3.0.3)
25
- arel (~> 2.0.2)
26
- tzinfo (~> 0.3.23)
27
- activeresource (3.0.3)
28
- activemodel (= 3.0.3)
29
- activesupport (= 3.0.3)
30
- activesupport (3.0.3)
31
- arel (2.0.7)
32
- builder (2.1.2)
33
- erubis (2.6.6)
34
- abstract (>= 1.0.0)
35
- git (1.2.5)
36
- i18n (0.5.0)
37
- jeweler (1.5.2)
38
- bundler (~> 1.0.0)
39
- git (>= 1.2.5)
40
- rake
41
- mail (2.2.14)
42
- activesupport (>= 2.3.6)
43
- i18n (>= 0.4.0)
44
- mime-types (~> 1.16)
45
- treetop (~> 1.4.8)
46
- mime-types (1.16)
47
- mysql2 (0.2.6)
48
- polyglot (0.3.1)
49
- rack (1.2.1)
50
- rack-mount (0.6.13)
51
- rack (>= 1.0.0)
52
- rack-test (0.5.7)
53
- rack (>= 1.0)
54
- rails (3.0.3)
55
- actionmailer (= 3.0.3)
56
- actionpack (= 3.0.3)
57
- activerecord (= 3.0.3)
58
- activeresource (= 3.0.3)
59
- activesupport (= 3.0.3)
60
- bundler (~> 1.0)
61
- railties (= 3.0.3)
62
- railties (3.0.3)
63
- actionpack (= 3.0.3)
64
- activesupport (= 3.0.3)
65
- rake (>= 0.8.7)
66
- thor (~> 0.14.4)
67
- rake (0.8.7)
68
- shoulda (2.11.3)
69
- thor (0.14.6)
70
- treetop (1.4.9)
71
- polyglot (>= 0.3.1)
72
- tzinfo (0.3.24)
73
-
74
- PLATFORMS
75
- ruby
76
-
77
- DEPENDENCIES
78
- bundler (~> 1.0.0)
79
- jeweler (~> 1.5.2)
80
- mysql2
81
- rails (= 3.0.3)
82
- shoulda