maintain 0.1.6 → 0.1.7
Sign up to get free protection for your applications and to get access to all the features.
- data/VERSION +1 -1
- data/lib/maintain/bitmask_value.rb +1 -0
- data/lib/maintain/integer_value.rb +1 -0
- data/lib/maintain/maintainer.rb +40 -16
- data/lib/maintain/value.rb +1 -0
- data/lib/maintain.rb +11 -28
- data/maintain.gemspec +4 -2
- data/spec/active_record_spec.rb +1 -1
- data/spec/aggregates_spec.rb +1 -1
- data/spec/bitwise_spec.rb +1 -1
- data/spec/comparing_state_spec.rb +15 -12
- data/spec/defining_states_spec.rb +1 -1
- data/spec/hooks_spec.rb +19 -1
- data/spec/integer_spec.rb +1 -1
- data/spec/maintain_spec.rb +1 -1
- data/spec/proxy_spec.rb +1 -1
- data/spec/setting_state_spec.rb +1 -1
- metadata +3 -3
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.1.
|
1
|
+
0.1.7
|
data/lib/maintain/maintainer.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
# encoding: UTF-8
|
1
2
|
module Maintain
|
2
3
|
class Maintainer
|
3
4
|
def aggregate(name, options)
|
@@ -38,7 +39,7 @@ module Maintain
|
|
38
39
|
end
|
39
40
|
|
40
41
|
def bitmask?
|
41
|
-
|
42
|
+
!!@bitmask
|
42
43
|
end
|
43
44
|
|
44
45
|
def default(state)
|
@@ -50,13 +51,11 @@ module Maintain
|
|
50
51
|
end
|
51
52
|
|
52
53
|
def hook(event, state, instance)
|
53
|
-
if state && hooks[state.to_sym] && hooks[state.to_sym][event.to_sym]
|
54
|
-
|
55
|
-
if
|
56
|
-
|
57
|
-
|
58
|
-
instance.send(method)
|
59
|
-
end
|
54
|
+
if state && state.to_s.strip != '' && hooks[state.to_sym] && hook_definitions = hooks[state.to_sym][event.to_sym]
|
55
|
+
hook_definitions.each do |hook_definition|
|
56
|
+
next if hook_definition[:if] && !call_method_or_proc_on_instance(hook_definition[:if], instance)
|
57
|
+
next if hook_definition[:unless] && call_method_or_proc_on_instance(hook_definition[:unless], instance)
|
58
|
+
call_method_or_proc_on_instance(hook_definition[:method], instance)
|
60
59
|
end
|
61
60
|
end
|
62
61
|
end
|
@@ -74,13 +73,25 @@ module Maintain
|
|
74
73
|
@integer = !!value
|
75
74
|
end
|
76
75
|
|
77
|
-
def
|
76
|
+
def integer?
|
77
|
+
!!@integer
|
78
|
+
end
|
79
|
+
|
80
|
+
def on(*args, &block)
|
81
|
+
options = args.last.is_a?(Hash) ? args.pop : {}
|
82
|
+
event, state = args.shift, args.shift
|
83
|
+
method = args.shift
|
78
84
|
if block_given?
|
79
85
|
method = block
|
80
86
|
end
|
81
87
|
hooks[state.to_sym] ||= {}
|
82
88
|
hooks[state.to_sym][event.to_sym] ||= []
|
83
|
-
|
89
|
+
method_hash = {:method => method}.merge(options)
|
90
|
+
if old_definition = hooks[state.to_sym][event.to_sym].find{|hook| hook[:method] == method}
|
91
|
+
old_definition.merge!(method_hash)
|
92
|
+
else
|
93
|
+
hooks[state.to_sym][event.to_sym].push(method_hash)
|
94
|
+
end
|
84
95
|
end
|
85
96
|
|
86
97
|
def state_name_for(value)
|
@@ -98,7 +109,7 @@ module Maintain
|
|
98
109
|
default(name)
|
99
110
|
end
|
100
111
|
@increment ||= 0
|
101
|
-
if
|
112
|
+
if bitmask?
|
102
113
|
unless value.is_a?(Integer)
|
103
114
|
value = @increment
|
104
115
|
end
|
@@ -107,7 +118,7 @@ module Maintain
|
|
107
118
|
integer(true)
|
108
119
|
end
|
109
120
|
value ||= name
|
110
|
-
states[name] = {:compare_value =>
|
121
|
+
states[name] = {:compare_value => !bitmask? && value.is_a?(Integer) ? value : @increment, :value => value}
|
111
122
|
@increment += 1
|
112
123
|
if @active_record && !maintainee.respond_to?(name)
|
113
124
|
conditions = {:conditions => {@attribute => value.is_a?(Symbol) ? value.to_s : value}}
|
@@ -138,9 +149,9 @@ module Maintain
|
|
138
149
|
end
|
139
150
|
|
140
151
|
def value(initial = nil)
|
141
|
-
if
|
152
|
+
if bitmask?
|
142
153
|
BitmaskValue.new(self, initial || @default || 0)
|
143
|
-
elsif
|
154
|
+
elsif integer?
|
144
155
|
IntegerValue.new(self, initial || @default)
|
145
156
|
else
|
146
157
|
Value.new(self, initial || @default)
|
@@ -164,9 +175,13 @@ module Maintain
|
|
164
175
|
methods = maintainee_class.public_methods + maintainee_class.private_methods + maintainee_class.protected_methods
|
165
176
|
else
|
166
177
|
respond_to = false
|
167
|
-
methods = maintainee_class.
|
178
|
+
methods = maintainee_class.instance_methods
|
179
|
+
# methods = %w(instance_methods public_instance_methods private_instance_methods protected_instance_methods).inject([]) do |methods, method|
|
180
|
+
# methods + maintainee_class.send(method)
|
181
|
+
# end.uniq
|
168
182
|
end
|
169
|
-
|
183
|
+
# Ruby 1.8 returns arrays of strings; ruby 1.9 returns arrays of symbols. "Awesome."
|
184
|
+
!respond_to && !methods.include?(method_name) && !methods.include?(method_name.to_sym)
|
170
185
|
end
|
171
186
|
|
172
187
|
def method_missing(method, *args)
|
@@ -176,5 +191,14 @@ module Maintain
|
|
176
191
|
super
|
177
192
|
end
|
178
193
|
end
|
194
|
+
|
195
|
+
private
|
196
|
+
def call_method_or_proc_on_instance(method, instance)
|
197
|
+
if method.is_a?(Proc)
|
198
|
+
instance.instance_eval(&method)
|
199
|
+
else
|
200
|
+
instance.send(method)
|
201
|
+
end
|
202
|
+
end
|
179
203
|
end
|
180
204
|
end
|
data/lib/maintain/value.rb
CHANGED
data/lib/maintain.rb
CHANGED
@@ -1,3 +1,6 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
$LOAD_PATH.unshift File.join(File.dirname(__FILE__))
|
3
|
+
|
1
4
|
module Maintain
|
2
5
|
# We're not really interested in loading anything into memory if we don't need to,
|
3
6
|
# so Maintainer, Value, and the Value subclasses are ignored until they're needed.
|
@@ -49,59 +52,39 @@ module Maintain
|
|
49
52
|
|
50
53
|
# Define our getters and setters - these are the only methods Maintain will stomp
|
51
54
|
# on if you've already defined them. This is because they're how Maintain works.
|
52
|
-
class_eval <<-EOC
|
55
|
+
class_eval <<-EOC, __FILE__
|
53
56
|
def #{attribute}=(value)
|
54
57
|
# If we can find the maintainer on this attribute, we'll use it to set values.
|
55
58
|
if maintainer = self.class.maintainers[#{attribute.to_sym.inspect}]
|
56
|
-
#
|
57
|
-
|
58
|
-
|
59
|
-
# Then run the exit hook if we're changing the value
|
60
|
-
maintainer.hook(:exit, #{attribute}.value, self)
|
59
|
+
# Run the exit hook if we're changing the value
|
60
|
+
maintainer.hook(:exit, #{attribute}.name, self)
|
61
61
|
|
62
62
|
# Then set the value itself. Maintainer::State will return the value you set,
|
63
63
|
# so if we're setting to nil we get rid of the attribute entirely - it's not
|
64
64
|
# needed and we want the getter to return nil in that case.
|
65
65
|
# unless
|
66
|
-
#{attribute}.set_value(value)
|
67
|
-
# @#{attribute} = nil
|
68
|
-
# Nevermind - all of our test methods rely on that attribute existing, no
|
69
|
-
# matter what (e.g. maintain(:state) { state :one } and calling "one?" will
|
70
|
-
# throw an error if we null out our maintainer)
|
71
|
-
# end#{%{
|
66
|
+
#{attribute}.set_value(value)#{%{
|
72
67
|
|
73
68
|
# If this is ActiveRecord::Base or a subclass of it, we'll make sure calling the
|
74
69
|
# setter writes a DB-friendly value.
|
75
|
-
write_attribute(#{attribute.to_s.inspect}, @#{attribute} ? @#{attribute}.value.to_s :
|
70
|
+
write_attribute(#{attribute.to_s.inspect}, @#{attribute} ? @#{attribute}.value.to_s : @#{attribute})
|
76
71
|
} if active_record}
|
77
72
|
|
78
73
|
# Last but not least, run the enter hooks for the new value - cause that's how we
|
79
74
|
# do.
|
80
|
-
maintainer.hook(:enter,
|
75
|
+
maintainer.hook(:enter, #{attribute}.name, self) if @#{attribute}
|
81
76
|
else
|
82
77
|
# If we can't find a maintainer for this attribute, make our best effort to do what
|
83
78
|
# attr_accessor does - set the instance variable.
|
84
79
|
@#{attribute} = value#{%{
|
85
80
|
|
86
81
|
# ... and on ActiveRecord::Base, we'll also write the attribute like a normal setter.
|
87
|
-
if
|
88
|
-
write_attribute(:#{attribute}, @#{attribute})
|
89
|
-
end
|
90
|
-
} if active_record}
|
82
|
+
write_attribute(:#{attribute}, @#{attribute})} if active_record}
|
91
83
|
end
|
92
84
|
end
|
93
85
|
|
94
86
|
def #{attribute}
|
95
|
-
|
96
|
-
return @#{attribute} if @#{attribute}
|
97
|
-
|
98
|
-
# If'n it doesn't already exist AND this maintained attribute has a default value (and
|
99
|
-
# bitmasks must have at least a 0 value), we'll instantiate a Maintainer::State and return
|
100
|
-
# it.
|
101
|
-
# if self.class.maintainers[#{attribute.to_sym.inspect}].default? || self.class.maintainers[#{attribute.to_sym.inspect}].bitmask?#{" || attributes['#{attribute}']" if active_record}
|
102
|
-
# Always return a State, no matter what
|
103
|
-
@#{attribute} = self.class.maintainers[#{attribute.to_sym.inspect}].value#{"(read_attribute(:#{attribute}))" if active_record}
|
104
|
-
# end
|
87
|
+
@#{attribute} ||= self.class.maintainers[#{attribute.to_sym.inspect}].value#{"(read_attribute(:#{attribute}))" if active_record}
|
105
88
|
end
|
106
89
|
EOC
|
107
90
|
|
data/maintain.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{maintain}
|
8
|
-
s.version = "0.1.
|
8
|
+
s.version = "0.1.7"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Flip Sasser"]
|
12
|
-
s.date = %q{2010-04-
|
12
|
+
s.date = %q{2010-04-30}
|
13
13
|
s.description = %q{
|
14
14
|
Maintain is a simple state machine mixin for Ruby objects. It supports comparisons, bitmasks,
|
15
15
|
and hooks that really work. It can be used for multiple attributes and will always do its best to
|
@@ -20,6 +20,7 @@ Gem::Specification.new do |s|
|
|
20
20
|
"README.markdown"
|
21
21
|
]
|
22
22
|
s.files = [
|
23
|
+
".gitignore",
|
23
24
|
"README.markdown",
|
24
25
|
"Rakefile",
|
25
26
|
"VERSION",
|
@@ -28,6 +29,7 @@ Gem::Specification.new do |s|
|
|
28
29
|
"lib/maintain/integer_value.rb",
|
29
30
|
"lib/maintain/maintainer.rb",
|
30
31
|
"lib/maintain/value.rb",
|
32
|
+
"maintain.gemspec",
|
31
33
|
"spec/active_record_spec.rb",
|
32
34
|
"spec/aggregates_spec.rb",
|
33
35
|
"spec/bitwise_spec.rb",
|
data/spec/active_record_spec.rb
CHANGED
@@ -22,7 +22,7 @@ if proceed
|
|
22
22
|
describe "accessors" do
|
23
23
|
before :each do
|
24
24
|
ActiveRecord::Base.establish_connection({:adapter => 'sqlite3', :database => ':memory:', :pool => 5, :timeout => 5000})
|
25
|
-
class ActiveMaintainTest < ActiveRecord::Base; end
|
25
|
+
class ::ActiveMaintainTest < ActiveRecord::Base; end
|
26
26
|
silence_stream(STDOUT) do
|
27
27
|
ActiveRecord::Schema.define do
|
28
28
|
create_table :active_maintain_tests, :force => true do |t|
|
data/spec/aggregates_spec.rb
CHANGED
data/spec/bitwise_spec.rb
CHANGED
@@ -4,10 +4,24 @@ require 'lib/maintain'
|
|
4
4
|
|
5
5
|
describe Maintain do
|
6
6
|
before :each do
|
7
|
-
class MaintainTest
|
7
|
+
class ::MaintainTest
|
8
8
|
attr_accessor :existant_attribute
|
9
9
|
extend Maintain
|
10
10
|
end
|
11
|
+
|
12
|
+
class ::MaintainTestTwo
|
13
|
+
def new?
|
14
|
+
:i_existed_before_you_came_along
|
15
|
+
end
|
16
|
+
|
17
|
+
extend Maintain
|
18
|
+
|
19
|
+
maintains :state, :default => :new do
|
20
|
+
state :new
|
21
|
+
state :overdue
|
22
|
+
state :closed
|
23
|
+
end
|
24
|
+
end
|
11
25
|
end
|
12
26
|
|
13
27
|
describe "testing" do
|
@@ -66,17 +80,6 @@ describe Maintain do
|
|
66
80
|
end
|
67
81
|
|
68
82
|
it "should not override pre-existing methods" do
|
69
|
-
class MaintainTestTwo
|
70
|
-
def new?
|
71
|
-
:i_existed_before_you_came_along
|
72
|
-
end
|
73
|
-
extend Maintain
|
74
|
-
maintains :state, :default => :new do
|
75
|
-
state :new
|
76
|
-
state :overdue
|
77
|
-
state :closed
|
78
|
-
end
|
79
|
-
end
|
80
83
|
MaintainTestTwo.new.new?.should == :i_existed_before_you_came_along
|
81
84
|
end
|
82
85
|
end
|
data/spec/hooks_spec.rb
CHANGED
@@ -4,7 +4,7 @@ require 'lib/maintain'
|
|
4
4
|
|
5
5
|
describe Maintain, "hooks" do
|
6
6
|
before :each do
|
7
|
-
class MaintainTest
|
7
|
+
class ::MaintainTest
|
8
8
|
extend Maintain
|
9
9
|
end
|
10
10
|
end
|
@@ -41,4 +41,22 @@ describe Maintain, "hooks" do
|
|
41
41
|
maintain.state = :old
|
42
42
|
end
|
43
43
|
|
44
|
+
describe "guarding" do
|
45
|
+
it "should prevent hooks from running when they return false" do
|
46
|
+
MaintainTest.maintain :state do
|
47
|
+
state :new
|
48
|
+
state :old
|
49
|
+
on :enter, :new, :new_entered, :if => :run_hook?
|
50
|
+
end
|
51
|
+
|
52
|
+
maintain = MaintainTest.new
|
53
|
+
def maintain.run_hook?
|
54
|
+
false
|
55
|
+
end
|
56
|
+
maintain.should_not_receive(:new_entered)
|
57
|
+
maintain.state = :new
|
58
|
+
maintain.state = :old
|
59
|
+
maintain.state = :old
|
60
|
+
end
|
61
|
+
end
|
44
62
|
end
|
data/spec/integer_spec.rb
CHANGED
data/spec/maintain_spec.rb
CHANGED
data/spec/proxy_spec.rb
CHANGED
data/spec/setting_state_spec.rb
CHANGED
metadata
CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
|
|
5
5
|
segments:
|
6
6
|
- 0
|
7
7
|
- 1
|
8
|
-
-
|
9
|
-
version: 0.1.
|
8
|
+
- 7
|
9
|
+
version: 0.1.7
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- Flip Sasser
|
@@ -14,7 +14,7 @@ autorequire:
|
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
16
|
|
17
|
-
date: 2010-04-
|
17
|
+
date: 2010-04-30 00:00:00 -04:00
|
18
18
|
default_executable:
|
19
19
|
dependencies: []
|
20
20
|
|