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