Module: Maintain
- Defined in:
- lib/maintain.rb,
lib/maintain/value.rb,
lib/maintain/backend.rb,
lib/maintain/maintainer.rb,
lib/maintain/backend/base.rb,
lib/maintain/bitmask_value.rb,
lib/maintain/integer_value.rb,
lib/maintain/backend/data_mapper.rb,
lib/maintain/backend/active_record.rb
Defined Under Namespace
Modules: Backend Classes: BitmaskValue, IntegerValue, Maintainer, Value
Constant Summary collapse
- VERSION =
'0.2.0'
Instance Method Summary collapse
-
#maintain(attribute, options = {}, &block) ⇒ Object
(also: #maintains)
The core class method of Maintain.
-
#maintainers ⇒ Object
:nodoc:.
Instance Method Details
#maintain(attribute, options = {}, &block) ⇒ Object Also known as: maintains
The core class method of Maintain. Basic usage is:
maintain :state do
state :new, :default => true
state :expired, :enter => :expire_children
state :reopened, :exit => lambda { children.each(&:reopen) }
aggregate :accessible, :as => [:new, :reopened]
end
It also supports more complex configuration options, like bitmask columns and integer values (for performance and portability)
maintain :permissions, :bitmask => true do
state :edit, 1
state :delete, 2
state :manage, 3
end
This method is aliased as ‘maintains` with the intention of allowing developers to code imperatively (“maintain, damn you!”) or descriptively (“it maintains, man”)
33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 |
# File 'lib/maintain.rb', line 33 def maintain(attribute, = {}, &block) [:back_end] ||= Maintain::Backend.detect(self) # Create an instance of the maintainer class. It handles all of the state # configuration, hooking, aggregation, named_scoping, etc. maintainer = Maintainer.new(self, attribute, ) if block_given? maintainer.instance_eval(&block) end # Define our getters and setters - these are the only methods Maintain will stomp # on if you've already defined them. This is because they're how Maintain works. class_eval <<-EOC, __FILE__ def #{attribute}=(value) # Find the maintainer on this attribute so we can use it to set values. 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) # 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} @#{attribute} ||= self.class.maintainers[:#{attribute}].value(self) end EOC class_eval <<-EOC, __FILE__ class << self def maintain_#{attribute} @#{attribute} ||= maintainers[:#{attribute}].states.sort{|a, b| (a[1][:compare_value] || a[1][:value]) <=> (b[1][:compare_value] || b[1][:value]) }.map{|key, value| key == value[:value] ? key : [key, value[:value]]} end #{"alias :#{attribute} :maintain_#{attribute}" unless respond_to?(attribute)} end EOC # Last! Not least! Save our maintainer directly on this class. We'll use it in our setters (as in above) # and we'll also modify it instead of replacing it outright, so subclasses or mixins can extend functionality # without replacing it. maintainers[attribute.to_sym] = maintainer end |
#maintainers ⇒ Object
:nodoc:
89 90 91 92 93 94 95 96 97 98 99 |
# File 'lib/maintain.rb', line 89 def maintainers #:nodoc: @maintainers ||= begin maintainers = {} superk = superclass while superk.respond_to?(:maintainers) maintainers.merge!(superk.maintainers) superk = superk.superclass end maintainers end end |