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 CHANGED
@@ -1 +1 @@
1
- 0.1.6
1
+ 0.1.7
@@ -1,3 +1,4 @@
1
+ # encoding: UTF-8
1
2
  module Maintain
2
3
  class BitmaskValue < Value
3
4
  def set_value(value)
@@ -1,3 +1,4 @@
1
+ # encoding: UTF-8
1
2
  module Maintain
2
3
  class IntegerValue < Value
3
4
  def value
@@ -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
- @bitmask
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
- hooks[state.to_sym][event.to_sym].each do |method|
55
- if method.is_a?(Proc)
56
- instance.instance_eval(&method)
57
- else
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 on(event, state, method = nil, &block)
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
- hooks[state.to_sym][event.to_sym].push(method) unless hooks[state.to_sym][event.to_sym].include?(method)
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 @bitmask
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 => !@bitmask && value.is_a?(Integer) ? value : @increment, :value => 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 @bitmask
152
+ if bitmask?
142
153
  BitmaskValue.new(self, initial || @default || 0)
143
- elsif @integer
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.public_instance_methods + maintainee_class.private_instance_methods + maintainee_class.protected_instance_methods
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
- !respond_to && !methods.include?(method_name)
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
@@ -1,3 +1,4 @@
1
+ # encoding: UTF-8
1
2
  module Maintain
2
3
  class Value
3
4
  def >(value)
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
- # First, we instantiate a value on this maintainer if we haven't already
57
- # @#{attribute} ||= maintainer.value#{"(read_attribute(:#{attribute}))" if active_record}
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 : nil)
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, @#{attribute}.value, self) if @#{attribute}
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 respond_to?(:write_attribute)
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
- # Start by returning an already-instantiated Maintainer::State if it exists
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.6"
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-24}
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",
@@ -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|
@@ -4,7 +4,7 @@ require 'lib/maintain'
4
4
 
5
5
  describe Maintain, "aggregates" do
6
6
  before :each do
7
- class MaintainTest
7
+ class ::MaintainTest
8
8
  extend Maintain
9
9
  end
10
10
  end
data/spec/bitwise_spec.rb CHANGED
@@ -4,7 +4,7 @@ require 'lib/maintain'
4
4
 
5
5
  describe Maintain do
6
6
  before :each do
7
- class MaintainTest
7
+ class ::MaintainTest
8
8
  extend Maintain
9
9
  end
10
10
  end
@@ -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
@@ -4,7 +4,7 @@ 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
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
@@ -4,7 +4,7 @@ require 'lib/maintain'
4
4
 
5
5
  describe Maintain do
6
6
  before :each do
7
- class MaintainTest
7
+ class ::MaintainTest
8
8
  extend Maintain
9
9
  end
10
10
  end
@@ -4,7 +4,7 @@ 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
data/spec/proxy_spec.rb CHANGED
@@ -4,7 +4,7 @@ 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
@@ -4,7 +4,7 @@ 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
metadata CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
5
5
  segments:
6
6
  - 0
7
7
  - 1
8
- - 6
9
- version: 0.1.6
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-24 00:00:00 -04:00
17
+ date: 2010-04-30 00:00:00 -04:00
18
18
  default_executable:
19
19
  dependencies: []
20
20