Skip to content

Commit

Permalink
Fixed a bug with subclasses not inheriting parents' maintainers
Browse files Browse the repository at this point in the history
  • Loading branch information
Flip Sasser committed Feb 28, 2011
1 parent f0912f0 commit 64dbdae
Show file tree
Hide file tree
Showing 3 changed files with 67 additions and 25 deletions.
49 changes: 25 additions & 24 deletions lib/maintain.rb
Expand Up @@ -45,35 +45,28 @@ def maintain(attribute, options = {}, &block)
class_eval <<-EOC, __FILE__
def #{attribute}=(value)
# Find the maintainer on this attribute so we can use it to set values.
if maintainer = self.class.maintainers[:#{attribute}]
changed = #{attribute} != value
# Run the exit hook if we're changing the value
maintainer.hook(:exit, #{attribute}.name, self) if changed
maintainer = self.class.maintainers[:#{attribute}]
changed = #{attribute} != value
# Run the exit hook if we're changing the value
maintainer.hook(:exit, #{attribute}.name, self) if changed
# Then set the value itself. Maintainer::State will return the value you set,
# so if we're setting to nil we get rid of the attribute entirely - it's not
# needed and we want the getter to return nil in that case.
#{attribute}.set_value(value)
# Then set the value itself. Maintainer::State will return the value you set,
# so if we're setting to nil we get rid of the attribute entirely - it's not
# needed and we want the getter to return nil in that case.
#{attribute}.set_value(value)
# Allow the back end to write values in an ORM-specific way
if maintainer.back_end
maintainer.back_end.write(self, :#{attribute}, #{attribute}.value)
end
# Last but not least, run the enter hooks for the new value - cause that's how
# we do.
maintainer.hook(:enter, #{attribute}.name, self) if changed
else
@#{attribute} = value
# Allow the back end to write values in an ORM-specific way
if maintainer.back_end
maintainer.back_end.write(self, :#{attribute}, #{attribute}.value)
end
# Last but not least, run the enter hooks for the new value - cause that's how
# we do.
maintainer.hook(:enter, #{attribute}.name, self) if changed
end
def #{attribute}
if maintainer = self.class.maintainers[:#{attribute}]
@#{attribute} ||= maintainer.value(self)
else
@#{attribute}
end
@#{attribute} ||= self.class.maintainers[:#{attribute}].value(self)
end
EOC

Expand All @@ -85,7 +78,15 @@ def #{attribute}
alias :maintains :maintain

def maintainers #:nodoc:
@maintainers ||= {}
@maintainers ||= begin
maintainers = {}
superk = superclass
while superk.respond_to?(:maintainers)
maintainers.merge!(superk.maintainers)
superk = superk.superclass
end
maintainers
end
end

if File.file?(version_path = File.join(File.dirname(__FILE__), '..', 'VERSION'))
Expand Down
6 changes: 5 additions & 1 deletion spec/integer_spec.rb
Expand Up @@ -13,7 +13,7 @@ class ::MaintainTest
before :each do
MaintainTest.maintain :kind, :integer => true do
state :man, 1
state :woman, 2
state :woman, 2, :default => true
state :none, 3
end
@maintainer = MaintainTest.new
Expand All @@ -24,6 +24,10 @@ class ::MaintainTest
@maintainer.none?.should be_true
end

it "should handle defaults just fine" do
@maintainer.woman?.should be_true
end

it "should return valid names, too" do
@maintainer.kind = :woman
@maintainer.kind.should == 2
Expand Down
37 changes: 37 additions & 0 deletions spec/subclass_spec.rb
@@ -0,0 +1,37 @@
# Basic class method specs

require 'lib/maintain'

describe Maintain do
before :each do
class ::MaintainTest
attr_accessor :existant_attribute
extend Maintain
end

class ::MaintainTestSubclass < ::MaintainTest; end
end

it "should inherit maintainers from parent classes" do
MaintainTest.maintain :status do
state :new
state :old
end
MaintainTestSubclass.maintainers[:status].should_not be_nil
end

it "should not propagate maintainers up the class system" do
MaintainTest.maintain :status do
state :new
state :old
end
MaintainTestSubclass.maintain :foo do
state :bar
state :baz
end
MaintainTest.maintainers[:foo].should be_nil
MaintainTestSubclass.maintainers[:status].should_not be_nil
end


end

0 comments on commit 64dbdae

Please sign in to comment.