enumerated_state 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +6 -0
- data/LICENSE +20 -0
- data/README.rdoc +58 -0
- data/Rakefile +69 -0
- data/init.rb +1 -0
- data/lib/enumerated_state.rb +68 -0
- data/spec/enumerated_state_spec.rb +396 -0
- data/spec/spec.opts +4 -0
- data/spec/spec_helper.rb +9 -0
- metadata +113 -0
data/.gitignore
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2006-2009 Jeff Patmon
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.rdoc
ADDED
@@ -0,0 +1,58 @@
|
|
1
|
+
= enumerated_state
|
2
|
+
|
3
|
+
Implement state patterns for your enumerated_attributes
|
4
|
+
|
5
|
+
== Resources
|
6
|
+
|
7
|
+
Install
|
8
|
+
|
9
|
+
* sudo gem enumerated_state
|
10
|
+
|
11
|
+
Use
|
12
|
+
|
13
|
+
* require 'enumerated_state'
|
14
|
+
|
15
|
+
|
16
|
+
== Description
|
17
|
+
|
18
|
+
This gem falls under the family of gems ASPIUM, ie (Another State Pattern Implementation Using Mixology). However,
|
19
|
+
this one adds much needed state pattern support for enumerated attributes (see http://github.com/jeffp/enumerated_attribute)
|
20
|
+
and supports multiple states per objection since each attribute manages a state.
|
21
|
+
|
22
|
+
== Basic implementation
|
23
|
+
|
24
|
+
So if you are using enumerated_attribute for an object tractor, you can replace the following code
|
25
|
+
|
26
|
+
case
|
27
|
+
when tractor.gear_is_first? then 'forwards'
|
28
|
+
when tractor.gear_is_reverse? then 'backwards'
|
29
|
+
else
|
30
|
+
'stopped'
|
31
|
+
end
|
32
|
+
|
33
|
+
with the more maintainable version
|
34
|
+
|
35
|
+
tractor.direction
|
36
|
+
|
37
|
+
if you define
|
38
|
+
|
39
|
+
class Tractor
|
40
|
+
enum_attr :gear, %w(reverse ^neutral first), allow_nil=>false
|
41
|
+
acts_as_enumerated_state :gear
|
42
|
+
|
43
|
+
module Reverse
|
44
|
+
def direction; 'backwards'; end
|
45
|
+
end
|
46
|
+
module Neutral
|
47
|
+
def direction; 'stopped'; end
|
48
|
+
end
|
49
|
+
module First
|
50
|
+
def direction; 'forwards'; end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
== Dependencies
|
55
|
+
|
56
|
+
* meta_programming
|
57
|
+
* mixology
|
58
|
+
* enumerated_attribute
|
data/Rakefile
ADDED
@@ -0,0 +1,69 @@
|
|
1
|
+
#require 'rake/testtask'
|
2
|
+
require 'rake/rdoctask'
|
3
|
+
require 'rake/gempackagetask'
|
4
|
+
gem 'gem_version', '>= 0.0.1'
|
5
|
+
require 'gem_version'
|
6
|
+
#require 'rake/contrib/sshpublisher'
|
7
|
+
|
8
|
+
spec = Gem::Specification.new do |s|
|
9
|
+
s.name = 'enumerated_state'
|
10
|
+
s.version = GemVersion.next_version
|
11
|
+
s.platform = Gem::Platform::RUBY
|
12
|
+
s.required_ruby_version = '>= 1.8.7'
|
13
|
+
s.description = 'Implement state patterns for your enumerated_attributes'
|
14
|
+
s.summary = 'ASPIUM (Another State Pattern Implementation Using Mixology)'
|
15
|
+
|
16
|
+
s.add_dependency('enumerated_attribute', '>= 0.2.10')
|
17
|
+
s.add_dependency('mixology', '>= 0.2.0')
|
18
|
+
s.add_dependency('meta_programming', '>= 0.2.1')
|
19
|
+
|
20
|
+
exclude_folders = '' # 'spec/rails/{doc,lib,log,nbproject,tmp,vendor,test}'
|
21
|
+
exclude_files = [] # FileList['**/*.log'] + FileList[exclude_folders+'/**/*'] + FileList[exclude_folders]
|
22
|
+
s.files = FileList['{lib,spec}/**/*'] + %w(init.rb LICENSE Rakefile README.rdoc .gitignore) - exclude_files
|
23
|
+
s.require_path = 'lib'
|
24
|
+
s.has_rdoc = true
|
25
|
+
s.test_files = Dir['spec/*_spec.rb']
|
26
|
+
|
27
|
+
s.author = 'Jeff Patmon'
|
28
|
+
s.email = 'jpatmon@gmail.com'
|
29
|
+
s.homepage = 'http://github.com/jeffp/enumerated_state/tree/master'
|
30
|
+
end
|
31
|
+
|
32
|
+
require 'spec/version'
|
33
|
+
require 'spec/rake/spectask'
|
34
|
+
|
35
|
+
desc "Run specs"
|
36
|
+
Spec::Rake::SpecTask.new(:spec) do |t|
|
37
|
+
t.spec_files = FileList['spec/*_spec.rb']
|
38
|
+
t.libs << 'lib' << 'spec'
|
39
|
+
t.rcov = false
|
40
|
+
t.spec_opts = ['--options', 'spec/spec.opts']
|
41
|
+
#t.rcov_dir = 'coverage'
|
42
|
+
#t.rcov_opts = ['--exclude', "kernel,load-diff-lcs\.rb,instance_exec\.rb,lib/spec.rb,lib/spec/runner.rb,^spec/*,bin/spec,examples,/gems,/Library/Ruby,\.autotest,#{ENV['GEM_HOME']}"]
|
43
|
+
end
|
44
|
+
|
45
|
+
desc "Generate documentation for the #{spec.name} gem."
|
46
|
+
Rake::RDocTask.new(:rdoc) do |rdoc|
|
47
|
+
rdoc.rdoc_dir = 'rdoc'
|
48
|
+
rdoc.title = spec.name
|
49
|
+
#rdoc.template = '../rdoc_template.rb'
|
50
|
+
rdoc.options << '--line-numbers' << '--inline-source'
|
51
|
+
rdoc.rdoc_files.include('README.rdoc', 'LICENSE', 'lib/**/*.rb')
|
52
|
+
end
|
53
|
+
|
54
|
+
desc 'Generate a gemspec file.'
|
55
|
+
task :gemspec do
|
56
|
+
File.open("#{spec.name}.gemspec", 'w') do |f|
|
57
|
+
f.write spec.to_ruby
|
58
|
+
end
|
59
|
+
GemVersion.increment_version
|
60
|
+
GemVersion.commit_and_push
|
61
|
+
end
|
62
|
+
|
63
|
+
Rake::GemPackageTask.new(spec) do |p|
|
64
|
+
p.gem_spec = spec
|
65
|
+
p.need_tar = RUBY_PLATFORM =~ /mswin/ ? false : true
|
66
|
+
p.need_zip = true
|
67
|
+
end
|
68
|
+
|
69
|
+
Dir['tasks/**/*.rake'].each {|rake| load rake}
|
data/init.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require 'arspy'
|
@@ -0,0 +1,68 @@
|
|
1
|
+
gem 'mixology', :version=>'>=0.2.0'
|
2
|
+
require 'mixology'
|
3
|
+
gem 'meta_programming', :version=>'>=0.2.1'
|
4
|
+
require 'meta_programming'
|
5
|
+
gem 'enumerated_attribute', :version=>'>=0.2.0'
|
6
|
+
require 'enumerated_attribute'
|
7
|
+
|
8
|
+
module EnumeratedState
|
9
|
+
class RedefinitionError < Exception
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
class Class
|
14
|
+
|
15
|
+
def acts_as_enumerated_state(enum_attr, opts={})
|
16
|
+
enum_attr = enum_attr.to_sym
|
17
|
+
unless (self.respond_to?(:has_enumerated_attribute?) && self.has_enumerated_attribute?(enum_attr))
|
18
|
+
raise ArgumentError, "enumerated attribute :#{enum_attr} not defined"
|
19
|
+
end
|
20
|
+
|
21
|
+
self.extend EnumeratedStateClassMethods
|
22
|
+
self.set_enumerated_state_property(enum_attr, :module_prefix, opts[:module] ? "#{opts[:module]}::" : '')
|
23
|
+
|
24
|
+
if self.method_defined?("write_enumerated_attribute_without_#{enum_attr}")
|
25
|
+
raise EnumeratedState::RedefinitionError, "Enumerated state already defined for :#{enum_attr}"
|
26
|
+
end
|
27
|
+
|
28
|
+
define_chained_method(:write_enumerated_attribute, enum_attr) do |attribute, value|
|
29
|
+
module_prefix = self.class.get_enumerated_state_property(attribute, :module_prefix) || ''
|
30
|
+
if (value != (old_value = self.read_enumerated_attribute(attribute)))
|
31
|
+
unless old_value.nil?
|
32
|
+
_module = self.class.class_eval(module_prefix + old_value.to_s.split(/_/).map(&:capitalize).join)
|
33
|
+
self.unmix _module
|
34
|
+
end
|
35
|
+
end
|
36
|
+
self.__send__("write_enumerated_attribute_without_#{enum_attr}".to_sym, attribute, value)
|
37
|
+
if (enum_attr == attribute.to_sym && !value.nil?)
|
38
|
+
_module = self.class.class_eval(module_prefix + value.to_s.split(/_/).map(&:capitalize).join)
|
39
|
+
self.mixin _module
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
alias_method :enumerated_state_pattern, :acts_as_enumerated_state
|
44
|
+
|
45
|
+
module EnumeratedStateClassMethods
|
46
|
+
def get_enumerated_state_property(enum_attr, prop_name)
|
47
|
+
if @_enumerated_state.has_key?(enum_attr)
|
48
|
+
if @_enumerated_state[enum_attr].has_key?(prop_name)
|
49
|
+
return @_enumerated_state[enum_attr][prop_name]
|
50
|
+
end
|
51
|
+
end
|
52
|
+
klass = self
|
53
|
+
while (subclass = klass.superclass)
|
54
|
+
if subclass.respond_to?(:get_enumerated_state_property)
|
55
|
+
return subclass.get_enumerated_state_property(enum_attr, prop_name)
|
56
|
+
else
|
57
|
+
klass = subclass
|
58
|
+
end
|
59
|
+
end
|
60
|
+
return nil
|
61
|
+
end
|
62
|
+
def set_enumerated_state_property(enum_attr, prop_name, value)
|
63
|
+
@_enumerated_state ||= {}
|
64
|
+
@_enumerated_state[enum_attr] ||= {}
|
65
|
+
@_enumerated_state[enum_attr][prop_name] = value
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
@@ -0,0 +1,396 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe 'Enumerated State' do
|
4
|
+
|
5
|
+
describe "acts_as_enumerated_state macro" do
|
6
|
+
it "should raise ArgumentError if enumerated_attribute method_name is undefined" do
|
7
|
+
lambda {
|
8
|
+
class A1
|
9
|
+
acts_as_enumerated_state :enum1
|
10
|
+
end
|
11
|
+
}.should raise_exception(ArgumentError)
|
12
|
+
end
|
13
|
+
it "should raise ArgumentError if method is not an enumerated_attribute" do
|
14
|
+
lambda {
|
15
|
+
class A2
|
16
|
+
attr_accessor :state
|
17
|
+
acts_as_enumerated_state :state
|
18
|
+
end
|
19
|
+
}.should raise_exception(ArgumentError)
|
20
|
+
end
|
21
|
+
it "should not raise exception for the alternate form of macro" do
|
22
|
+
lambda {
|
23
|
+
class A4
|
24
|
+
enumerated_attribute :enum1, %w(mod1 mod2)
|
25
|
+
enumerated_state_pattern :enum1
|
26
|
+
end
|
27
|
+
}
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
describe "implementation without base methods" do
|
32
|
+
class Impl1
|
33
|
+
enum_attr :enum1, %w(mod1 mod2)
|
34
|
+
acts_as_enumerated_state :enum1
|
35
|
+
module Mod1
|
36
|
+
def hello; 'hello Mod1'; end
|
37
|
+
def goodbye; 'goodbye Mod1'; end
|
38
|
+
end
|
39
|
+
module Mod2
|
40
|
+
def hello; 'hello Mod2'; end
|
41
|
+
def goodbye; 'goodbye Mod2'; end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
it "should call correct method after state is set" do
|
46
|
+
obj = Impl1.new
|
47
|
+
obj.enum1 = :mod1
|
48
|
+
obj.hello.should == 'hello Mod1'
|
49
|
+
obj.goodbye.should == 'goodbye Mod1'
|
50
|
+
obj.enum1 = :mod2
|
51
|
+
obj.goodbye.should == 'goodbye Mod2'
|
52
|
+
obj.hello.should == 'hello Mod2'
|
53
|
+
end
|
54
|
+
it "should raise NoMethodError when method called after initialization" do
|
55
|
+
obj = Impl1.new
|
56
|
+
lambda { obj.hello }.should raise_exception(NoMethodError)
|
57
|
+
end
|
58
|
+
it "should raise NoMethodError when calling method after enum set to nil" do
|
59
|
+
obj = Impl1.new
|
60
|
+
obj.enum1 = :mod1
|
61
|
+
obj.hello.should == 'hello Mod1'
|
62
|
+
lambda { obj.enum1 = nil }.should_not raise_exception
|
63
|
+
lambda { obj.hello }.should raise_exception(NoMethodError)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
describe "implementation with base methods" do
|
68
|
+
class Impl2
|
69
|
+
enum_attr :enum1, %w(mod1 mod2)
|
70
|
+
acts_as_enumerated_state :enum1
|
71
|
+
def hello; 'hello Impl'; end
|
72
|
+
def goodbye; 'goodbye Impl'; end
|
73
|
+
module Mod1
|
74
|
+
def hello; 'hello Mod1'; end
|
75
|
+
def goodbye; 'goodbye Mod1'; end
|
76
|
+
end
|
77
|
+
module Mod2
|
78
|
+
def hello; 'hello Mod2'; end
|
79
|
+
def goodbye; 'goodbye Mod2'; end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
it "should call correct method after state is set" do
|
84
|
+
obj = Impl2.new
|
85
|
+
obj.enum1 = :mod1
|
86
|
+
obj.hello.should == 'hello Mod1'
|
87
|
+
obj.goodbye.should == 'goodbye Mod1'
|
88
|
+
obj.enum1 = :mod2
|
89
|
+
obj.goodbye.should == 'goodbye Mod2'
|
90
|
+
obj.hello.should == 'hello Mod2'
|
91
|
+
end
|
92
|
+
it "should call base methods after initialization to nil" do
|
93
|
+
obj = Impl2.new
|
94
|
+
obj.hello.should == 'hello Impl'
|
95
|
+
obj.goodbye.should == 'goodbye Impl'
|
96
|
+
end
|
97
|
+
it "should call base methods when set to nil" do
|
98
|
+
obj = Impl2.new
|
99
|
+
obj.enum1 = :mod1
|
100
|
+
obj.hello.should == 'hello Mod1'
|
101
|
+
obj.enum1 = nil
|
102
|
+
obj.hello.should == 'hello Impl'
|
103
|
+
obj.goodbye.should == 'goodbye Impl'
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
describe "implementation with auto initialization" do
|
108
|
+
|
109
|
+
class Impl3
|
110
|
+
enum_attr :enum1, %w(mod1 ^mod2)
|
111
|
+
acts_as_enumerated_state :enum1
|
112
|
+
def hello; 'hello Impl'; end
|
113
|
+
def goodbye; 'goodbye Impl'; end
|
114
|
+
module Mod1
|
115
|
+
def hello; 'hello Mod1'; end
|
116
|
+
def goodbye; 'goodbye Mod1'; end
|
117
|
+
end
|
118
|
+
module Mod2
|
119
|
+
def hello; 'hello Mod2'; end
|
120
|
+
def goodbye; 'goodbye Mod2'; end
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
it "should call mod2 hello method after initialization to mod2" do
|
125
|
+
obj = Impl3.new
|
126
|
+
obj.hello.should == 'hello Mod2'
|
127
|
+
end
|
128
|
+
it "should call mod2 goodbye methods after initialization to mod2" do
|
129
|
+
obj = Impl3.new
|
130
|
+
obj.goodbye.should == 'goodbye Mod2'
|
131
|
+
end
|
132
|
+
it "should call base methods when set to nil" do
|
133
|
+
obj = Impl3.new
|
134
|
+
obj.enum1 = :mod1
|
135
|
+
obj.hello.should == 'hello Mod1'
|
136
|
+
obj.enum1 = nil
|
137
|
+
obj.hello.should == 'hello Impl'
|
138
|
+
obj.goodbye.should == 'goodbye Impl'
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
describe "implementation with double state" do
|
143
|
+
class Impl4
|
144
|
+
enum_attr :enum1, %w(mod1 ^mod2)
|
145
|
+
enum_attr :enum2, %w(mod3 mod4)
|
146
|
+
acts_as_enumerated_state :enum1
|
147
|
+
acts_as_enumerated_state :enum2
|
148
|
+
|
149
|
+
def hello; 'hello Impl'; end
|
150
|
+
def goodbye; 'goodbye Impl'; end
|
151
|
+
def hi; 'hi Impl'; end
|
152
|
+
def bye; 'bye Impl'; end
|
153
|
+
module Mod1
|
154
|
+
def hello; 'hello Mod1'; end
|
155
|
+
def goodbye; 'goodbye Mod1'; end
|
156
|
+
end
|
157
|
+
module Mod2
|
158
|
+
def hello; 'hello Mod2'; end
|
159
|
+
def goodbye; 'goodbye Mod2'; end
|
160
|
+
end
|
161
|
+
module Mod3
|
162
|
+
def hi; 'hi Mod3'; end
|
163
|
+
def bye; 'bye Mod3'; end
|
164
|
+
end
|
165
|
+
module Mod4
|
166
|
+
def hi; 'hi Mod4'; end
|
167
|
+
def bye; 'bye Mod4'; end
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
it "should call correct methods with dual enuemrations" do
|
172
|
+
obj = Impl4.new
|
173
|
+
obj.hello.should == 'hello Mod2'
|
174
|
+
obj.hi.should == 'hi Impl'
|
175
|
+
obj.enum1 = :mod1
|
176
|
+
obj.hello.should == 'hello Mod1'
|
177
|
+
obj.bye.should == 'bye Impl'
|
178
|
+
obj.goodbye.should == 'goodbye Mod1'
|
179
|
+
obj.enum2 = :mod3
|
180
|
+
obj.bye.should == 'bye Mod3'
|
181
|
+
obj.goodbye.should == 'goodbye Mod1'
|
182
|
+
obj.hi.should == 'hi Mod3'
|
183
|
+
obj.enum2 = :mod4
|
184
|
+
obj.hi.should == 'hi Mod4'
|
185
|
+
obj.hello.should == 'hello Mod1'
|
186
|
+
obj.enum2 = nil
|
187
|
+
obj.hi.should == 'hi Impl'
|
188
|
+
obj.hello.should == 'hello Mod1'
|
189
|
+
obj.enum1 = :mod2
|
190
|
+
obj.hello.should == 'hello Mod2'
|
191
|
+
end
|
192
|
+
end
|
193
|
+
|
194
|
+
describe "implementation with conflicting enum values and module attribute" do
|
195
|
+
class Impl5
|
196
|
+
enum_attr :enum1, %w(mod1 ^mod2)
|
197
|
+
enum_attr :enum2, %w(mod3 mod2)
|
198
|
+
acts_as_enumerated_state :enum1
|
199
|
+
acts_as_enumerated_state :enum2, :module=>'Enum2'
|
200
|
+
|
201
|
+
def hello; 'hello Impl'; end
|
202
|
+
def goodbye; 'goodbye Impl'; end
|
203
|
+
def hi; 'hi Impl'; end
|
204
|
+
def bye; 'bye Impl'; end
|
205
|
+
|
206
|
+
module Mod1
|
207
|
+
def hello; 'hello Mod1'; end
|
208
|
+
def goodbye; 'goodbye Mod1'; end
|
209
|
+
end
|
210
|
+
module Mod2
|
211
|
+
def hello; 'hello Mod2'; end
|
212
|
+
def goodbye; 'goodbye Mod2'; end
|
213
|
+
end
|
214
|
+
|
215
|
+
module Enum2
|
216
|
+
module Mod3
|
217
|
+
def hi; 'hi Enum2::Mod3'; end
|
218
|
+
def bye; 'bye Enum2::Mod3'; end
|
219
|
+
end
|
220
|
+
module Mod2
|
221
|
+
def hi; 'hi Enum2::Mod2'; end
|
222
|
+
def bye; 'bye Enum2::Mod2'; end
|
223
|
+
end
|
224
|
+
end
|
225
|
+
end
|
226
|
+
|
227
|
+
it "should call correct method on initialization" do
|
228
|
+
obj = Impl5.new
|
229
|
+
obj.hello.should == 'hello Mod2'
|
230
|
+
obj.hi.should == 'hi Impl'
|
231
|
+
end
|
232
|
+
|
233
|
+
it "should call correct methods with dual enumerations" do
|
234
|
+
obj = Impl5.new
|
235
|
+
obj.enum1 = :mod1
|
236
|
+
obj.hello.should == 'hello Mod1'
|
237
|
+
obj.bye.should == 'bye Impl'
|
238
|
+
obj.goodbye.should == 'goodbye Mod1'
|
239
|
+
obj.enum2 = :mod3
|
240
|
+
obj.bye.should == 'bye Enum2::Mod3'
|
241
|
+
obj.goodbye.should == 'goodbye Mod1'
|
242
|
+
obj.hi.should == 'hi Enum2::Mod3'
|
243
|
+
obj.enum2 = :mod2
|
244
|
+
obj.hi.should == 'hi Enum2::Mod2'
|
245
|
+
obj.hello.should == 'hello Mod1'
|
246
|
+
obj.enum2 = nil
|
247
|
+
obj.hi.should == 'hi Impl'
|
248
|
+
obj.hello.should == 'hello Mod1'
|
249
|
+
obj.enum1 = :mod2
|
250
|
+
obj.hello.should == 'hello Mod2'
|
251
|
+
end
|
252
|
+
end
|
253
|
+
|
254
|
+
describe "inherited implementation" do
|
255
|
+
class Impl10
|
256
|
+
enum_attr :enum1, %w(mod1 ^mod2)
|
257
|
+
acts_as_enumerated_state :enum1
|
258
|
+
|
259
|
+
def hello; 'hello Impl'; end
|
260
|
+
def goodbye; 'goodbye Impl'; end
|
261
|
+
|
262
|
+
module Mod1
|
263
|
+
def hello; 'hello Mod1'; end
|
264
|
+
def goodbye; 'goodbye Mod1'; end
|
265
|
+
end
|
266
|
+
module Mod2
|
267
|
+
def hello; 'hello Mod2'; end
|
268
|
+
def goodbye; 'goodbye Mod2'; end
|
269
|
+
end
|
270
|
+
end
|
271
|
+
class Impl11 < Impl10
|
272
|
+
enum_attr :enum2, %w(mod3 mod2)
|
273
|
+
acts_as_enumerated_state :enum2, :module=>'Enum2'
|
274
|
+
def hi; 'hi Impl'; end
|
275
|
+
def bye; 'bye Impl'; end
|
276
|
+
|
277
|
+
module Enum2
|
278
|
+
module Mod3
|
279
|
+
def hi; 'hi Enum2::Mod3'; end
|
280
|
+
def bye; 'bye Enum2::Mod3'; end
|
281
|
+
end
|
282
|
+
module Mod2
|
283
|
+
def hi; 'hi Enum2::Mod2'; end
|
284
|
+
def bye; 'bye Enum2::Mod2'; end
|
285
|
+
end
|
286
|
+
end
|
287
|
+
end
|
288
|
+
|
289
|
+
it "should call correct method on initialization" do
|
290
|
+
obj = Impl11.new
|
291
|
+
obj.hello.should == 'hello Mod2'
|
292
|
+
obj.hi.should == 'hi Impl'
|
293
|
+
end
|
294
|
+
|
295
|
+
it "should call correct methods with dual enumerations" do
|
296
|
+
obj = Impl11.new
|
297
|
+
obj.enum1 = :mod1
|
298
|
+
obj.hello.should == 'hello Mod1'
|
299
|
+
obj.bye.should == 'bye Impl'
|
300
|
+
obj.goodbye.should == 'goodbye Mod1'
|
301
|
+
obj.enum2 = :mod3
|
302
|
+
obj.bye.should == 'bye Enum2::Mod3'
|
303
|
+
obj.goodbye.should == 'goodbye Mod1'
|
304
|
+
obj.hi.should == 'hi Enum2::Mod3'
|
305
|
+
obj.enum2 = :mod2
|
306
|
+
obj.hi.should == 'hi Enum2::Mod2'
|
307
|
+
obj.hello.should == 'hello Mod1'
|
308
|
+
obj.enum2 = nil
|
309
|
+
obj.hi.should == 'hi Impl'
|
310
|
+
obj.hello.should == 'hello Mod1'
|
311
|
+
obj.enum1 = :mod2
|
312
|
+
obj.hello.should == 'hello Mod2'
|
313
|
+
end
|
314
|
+
end
|
315
|
+
|
316
|
+
describe "inherited implementation with nested modules in superclass" do
|
317
|
+
class Impl15
|
318
|
+
enum_attr :enum2, %w(mod3 mod2)
|
319
|
+
acts_as_enumerated_state :enum2, :module=>'Enum2'
|
320
|
+
def hi; 'hi Impl'; end
|
321
|
+
def bye; 'bye Impl'; end
|
322
|
+
|
323
|
+
module Enum2
|
324
|
+
module Mod3
|
325
|
+
def hi; 'hi Enum2::Mod3'; end
|
326
|
+
def bye; 'bye Enum2::Mod3'; end
|
327
|
+
end
|
328
|
+
module Mod2
|
329
|
+
def hi; 'hi Enum2::Mod2'; end
|
330
|
+
def bye; 'bye Enum2::Mod2'; end
|
331
|
+
end
|
332
|
+
end
|
333
|
+
end
|
334
|
+
class Impl16 < Impl15
|
335
|
+
enum_attr :enum1, %w(mod1 ^mod2)
|
336
|
+
acts_as_enumerated_state :enum1
|
337
|
+
|
338
|
+
def hello; 'hello Impl'; end
|
339
|
+
def goodbye; 'goodbye Impl'; end
|
340
|
+
|
341
|
+
module Mod1
|
342
|
+
def hello; 'hello Mod1'; end
|
343
|
+
def goodbye; 'goodbye Mod1'; end
|
344
|
+
end
|
345
|
+
module Mod2
|
346
|
+
def hello; 'hello Mod2'; end
|
347
|
+
def goodbye; 'goodbye Mod2'; end
|
348
|
+
end
|
349
|
+
end
|
350
|
+
|
351
|
+
it "should call correct method on initialization" do
|
352
|
+
obj = Impl16.new
|
353
|
+
obj.hello.should == 'hello Mod2'
|
354
|
+
obj.hi.should == 'hi Impl'
|
355
|
+
end
|
356
|
+
|
357
|
+
it "should call correct methods with dual enumerations" do
|
358
|
+
obj = Impl16.new
|
359
|
+
obj.enum1 = :mod1
|
360
|
+
obj.hello.should == 'hello Mod1'
|
361
|
+
obj.bye.should == 'bye Impl'
|
362
|
+
obj.goodbye.should == 'goodbye Mod1'
|
363
|
+
obj.enum2 = :mod3
|
364
|
+
obj.bye.should == 'bye Enum2::Mod3'
|
365
|
+
obj.goodbye.should == 'goodbye Mod1'
|
366
|
+
obj.hi.should == 'hi Enum2::Mod3'
|
367
|
+
obj.enum2 = :mod2
|
368
|
+
obj.hi.should == 'hi Enum2::Mod2'
|
369
|
+
obj.hello.should == 'hello Mod1'
|
370
|
+
obj.enum2 = nil
|
371
|
+
obj.hi.should == 'hi Impl'
|
372
|
+
obj.hello.should == 'hello Mod1'
|
373
|
+
obj.enum1 = :mod2
|
374
|
+
obj.hello.should == 'hello Mod2'
|
375
|
+
end
|
376
|
+
end
|
377
|
+
|
378
|
+
describe "implementation error checking" do
|
379
|
+
|
380
|
+
it "should raise exception when redeclaring enumerated states in subclass" do
|
381
|
+
lambda {
|
382
|
+
class Err1
|
383
|
+
enum_attr :enum1, %w(e1 e2)
|
384
|
+
acts_as_enumerated_state :enum1
|
385
|
+
end
|
386
|
+
class Err2 < Err1
|
387
|
+
enum_attr :enum2, %w(e3 e4)
|
388
|
+
acts_as_enumerated_state :enum1
|
389
|
+
end
|
390
|
+
obj = Err2.new
|
391
|
+
}.should raise_exception(EnumeratedState::RedefinitionError)
|
392
|
+
end
|
393
|
+
|
394
|
+
end
|
395
|
+
|
396
|
+
end
|
data/spec/spec.opts
ADDED
data/spec/spec_helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,113 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: enumerated_state
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease: false
|
5
|
+
segments:
|
6
|
+
- 0
|
7
|
+
- 0
|
8
|
+
- 2
|
9
|
+
version: 0.0.2
|
10
|
+
platform: ruby
|
11
|
+
authors:
|
12
|
+
- Jeff Patmon
|
13
|
+
autorequire:
|
14
|
+
bindir: bin
|
15
|
+
cert_chain: []
|
16
|
+
|
17
|
+
date: 2010-05-28 00:00:00 -07:00
|
18
|
+
default_executable:
|
19
|
+
dependencies:
|
20
|
+
- !ruby/object:Gem::Dependency
|
21
|
+
name: enumerated_attribute
|
22
|
+
prerelease: false
|
23
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
24
|
+
requirements:
|
25
|
+
- - ">="
|
26
|
+
- !ruby/object:Gem::Version
|
27
|
+
segments:
|
28
|
+
- 0
|
29
|
+
- 2
|
30
|
+
- 10
|
31
|
+
version: 0.2.10
|
32
|
+
type: :runtime
|
33
|
+
version_requirements: *id001
|
34
|
+
- !ruby/object:Gem::Dependency
|
35
|
+
name: mixology
|
36
|
+
prerelease: false
|
37
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
38
|
+
requirements:
|
39
|
+
- - ">="
|
40
|
+
- !ruby/object:Gem::Version
|
41
|
+
segments:
|
42
|
+
- 0
|
43
|
+
- 2
|
44
|
+
- 0
|
45
|
+
version: 0.2.0
|
46
|
+
type: :runtime
|
47
|
+
version_requirements: *id002
|
48
|
+
- !ruby/object:Gem::Dependency
|
49
|
+
name: meta_programming
|
50
|
+
prerelease: false
|
51
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
52
|
+
requirements:
|
53
|
+
- - ">="
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
segments:
|
56
|
+
- 0
|
57
|
+
- 2
|
58
|
+
- 1
|
59
|
+
version: 0.2.1
|
60
|
+
type: :runtime
|
61
|
+
version_requirements: *id003
|
62
|
+
description: Implement state patterns for your enumerated_attributes
|
63
|
+
email: jpatmon@gmail.com
|
64
|
+
executables: []
|
65
|
+
|
66
|
+
extensions: []
|
67
|
+
|
68
|
+
extra_rdoc_files: []
|
69
|
+
|
70
|
+
files:
|
71
|
+
- lib/enumerated_state.rb
|
72
|
+
- spec/spec_helper.rb
|
73
|
+
- spec/spec.opts
|
74
|
+
- spec/enumerated_state_spec.rb
|
75
|
+
- init.rb
|
76
|
+
- LICENSE
|
77
|
+
- Rakefile
|
78
|
+
- README.rdoc
|
79
|
+
- .gitignore
|
80
|
+
has_rdoc: true
|
81
|
+
homepage: http://github.com/jeffp/enumerated_state/tree/master
|
82
|
+
licenses: []
|
83
|
+
|
84
|
+
post_install_message:
|
85
|
+
rdoc_options: []
|
86
|
+
|
87
|
+
require_paths:
|
88
|
+
- lib
|
89
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
90
|
+
requirements:
|
91
|
+
- - ">="
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
segments:
|
94
|
+
- 1
|
95
|
+
- 8
|
96
|
+
- 7
|
97
|
+
version: 1.8.7
|
98
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
99
|
+
requirements:
|
100
|
+
- - ">="
|
101
|
+
- !ruby/object:Gem::Version
|
102
|
+
segments:
|
103
|
+
- 0
|
104
|
+
version: "0"
|
105
|
+
requirements: []
|
106
|
+
|
107
|
+
rubyforge_project:
|
108
|
+
rubygems_version: 1.3.6
|
109
|
+
signing_key:
|
110
|
+
specification_version: 3
|
111
|
+
summary: ASPIUM (Another State Pattern Implementation Using Mixology)
|
112
|
+
test_files:
|
113
|
+
- spec/enumerated_state_spec.rb
|