lib/innate/traited.rb in manveru-innate-2009.02.21 vs lib/innate/traited.rb in manveru-innate-2009.02.25

- old
+ new

@@ -1,6 +1,31 @@ module Innate + # Traited helps you doing configuration similar to class variables. + # + # It's built on a simple Hash, where keys are objects and the values the + # configuration. + # By using {Traited#ancestral_trait} you will get nicely inherited + # configuration, where keys later in the ancestors will take precedence. + # + # @usage + # class Foo + # include Innate::Traited + # trait :hello => 'Hello' + # + # def initialize + # trait :hello => 'World!' + # end + # + # def show + # [class_trait[:hello], trait[:hello], ancestral_trait[:hello]] + # end + # end + # + # Foo.trait[:hello] # => "Hello" + # foo = Foo.new + # foo.trait[:hello] # => "World!" + # foo.show # => ["Hello", "World!", "World!"] module Traited TRAITS = {} def self.included(into) into.extend(self) @@ -13,13 +38,40 @@ else TRAITS[self] || {} end end + # Builds a trait from all the ancestors, closer ancestors overwrite distant + # ancestors + # + # class Foo + # include Innate::Traited + # trait :one => :eins, :first => :erstes + # end + # + # class Bar < Foo + # trait :two => :zwei + # end + # + # class Foobar < Bar + # trait :three => :drei, :first => :overwritten + # end + # + # Foobar.ancestral_trait + # # => {:three => :drei, :two => :zwei, :one => :eins, :first => :overwritten} def ancestral_trait + result = {} + ancs = respond_to?(:ancestors) ? ancestors : self.class.ancestors - ancs.reverse.inject({}){|s,v| - v.respond_to?(:trait) ? s.update(v.trait) : s - }.merge(trait) + ancs.reverse_each do |anc| + result.update(anc.trait) if anc.respond_to?(:trait) + end + + result.merge!(trait) + end + + # trait for self.class if we are an instance + def class_trait + respond_to?(:ancestors) ? trait : self.class.trait end end end