Traits = Hash.new{|h,k| h[k] = {}} class Object # traits thanks to Michael Fellinger m.fellinger@gmail.com # Adds a method to Object to annotate your objects with certain traits. # It's basically a simple Hash that takes the current object as key # # Example: # # class Foo # trait :instance => false # # def initialize # trait :instance => true # end # end # # Foo.trait[:instance] # # false # # foo = Foo.new # foo.trait[:instance] # # true def trait hash = nil if hash Traits[self].merge! hash else Traits[self] end end # builds a trait from all the ancestors, closer ancestors # overwrite distant ancestors # # class Foo # trait :one => :eins # trait :first => :erstes # end # # class Bar < Foo # trait :two => :zwei # end # # class Foobar < Bar # trait :three => :drei # trait :first => :overwritten # end # # Foobar.ancestral_trait # {:three=>:drei, :two=>:zwei, :one=>:eins, :first=>:overwritten} def ancestral_trait ancs = (ancestors rescue self.class.ancestors) ancs.reverse.inject({}){|s,v| s.merge(v.trait)}.merge(trait) end def returning(value) yield(value) value end def meta_class() class << self; self end end def meta_eval(&blk) meta_class.instance_eval( &blk ) end def meta_def(name, &blk) meta_eval { define_method name, &blk } end def class_def name, &blk self.class.class_eval { define_method name, &blk } end def blank? if respond_to? :empty? then empty? elsif respond_to? :zero? then zero? else !self end end def with_options(options) yield Merb::OptionMerger.new(self, options) end end module Merb class OptionMerger #:nodoc: instance_methods.each do |method| undef_method(method) if method !~ /^(__|instance_eval|class)/ end def initialize(context, options) @context, @options = context, options end private def method_missing(method, *arguments, &block) merge_argument_options! arguments @context.send(method, *arguments, &block) end def merge_argument_options!(arguments) arguments << if arguments.last.respond_to? :to_hash @options.merge(arguments.pop) else @options.dup end end end end