lib/characterizable.rb in characterizable-0.0.2 vs lib/characterizable.rb in characterizable-0.0.3

- old
+ new

@@ -20,15 +20,16 @@ def characteristics @_characteristics ||= Snapshot.new self end - def dirty_characteristics! + def expire_snapshot! @_characteristics = nil end # hashes that survive as such when you select/reject/slice them + # they also keep arguments passed to them class SurvivorHash < Hash attr_reader :survivor_args def initialize(*survivor_args) @survivor_args = survivor_args end @@ -61,40 +62,30 @@ class Snapshot < SurvivorHash def initialize(*survivor_args) super take_snapshot end - def snapshotted_obj + def target survivor_args.first end def []=(key, value) - snapshotted_obj.dirty_characteristics! + target.expire_snapshot! super end def take_snapshot - snapshotted_obj.characterizable_base.characteristics.each do |k, c| - if c.known?(snapshotted_obj) and c.requited?(snapshotted_obj) and not c.trumped?(snapshotted_obj) - self[k] = snapshotted_obj.send c.name + target.characterizable_base.characteristics.each do |_, c| + if c.relevant?(target) + self[c.name] = c.value(target) end end end - def known - snapshotted_obj.characterizable_base.characteristics.select do |_, c| - c.known?(self) and c.requited?(self) and not c.trumped?(self) - end + def relevant + target.characterizable_base.characteristics.select { |_, c| c.relevant?(self) } end - def unknown - snapshotted_obj.characterizable_base.characteristics.select do |_, c| - c.unknown?(self) and c.requited?(self) and not c.trumped?(self) - end + def irrelevant + target.characterizable_base.characteristics.select { |_, c| c.irrelevant?(self) } end - def visible_known - known.reject { |_, c| c.hidden? } - end - def visible_unknown - unknown.reject { |_, c| c.hidden? } - end end module ClassMethods def characterize(&block) self.characterizable_base = Characterizable::Base.new self @@ -113,60 +104,58 @@ end include Blockenspiel::DSL def has(name, options = {}, &block) characteristics[name] = Characteristic.new(self, name, options, &block) klass.module_eval(%{ - def #{name}_with_dirty_characteristics=(new_#{name}) - dirty_characteristics! - self.#{name}_without_dirty_characteristics = new_#{name} + def #{name}_with_expire_snapshot=(new_#{name}) + expire_snapshot! + self.#{name}_without_expire_snapshot = new_#{name} end - alias_method_chain :#{name}=, :dirty_characteristics + alias_method_chain :#{name}=, :expire_snapshot }, __FILE__, __LINE__) if klass.instance_methods.include?("#{name}=") end end - class Characteristic attr_reader :base attr_reader :name attr_reader :trumps attr_reader :prerequisite - attr_reader :hidden attr_reader :options def initialize(base, name, options = {}, &block) @base = base @name = name - @trumps = Array.wrap(options.delete(:trumps)) - @prerequisite = options.delete :prerequisite - @hidden = options.delete :hidden + @trumps = Array.wrap options.delete(:trumps) + @prerequisite = options.delete(:prerequisite) @options = options Blockenspiel.invoke block, self if block_given? end + def trumped_by + @_trumped_by ||= characteristics.select { |_, c| c.trumps.include? name } + end delegate :characteristics, :to => :base - def value(obj) - case obj + def value(target) + case target when Hash - obj[name] + target[name] else - obj.send name + target.send name if target.respond_to?(name) end end - def unknown?(obj) - value(obj).nil? + def irrelevant?(target) + value(target).nil? and revealed? target and untrumped? target end - def known?(obj) - not unknown?(obj) + def relevant?(target) + !value(target).nil? and revealed? target and untrumped? target end - def trumped?(obj) - characteristics.any? do |_, c| - c.known?(obj) and c.trumps.include?(name) + def untrumped?(target) + return true if trumped_by.empty? + trumped_by.none? do |_, c| + c.relevant? target end end - def requited?(obj) + def revealed?(target) return true if prerequisite.nil? - characteristics[prerequisite].known? obj - end - def hidden? - hidden + characteristics[prerequisite].relevant? target end include Blockenspiel::DSL def reveals(other_name, other_options = {}, &block) base.has other_name, other_options.merge(:prerequisite => name), &block end