lib/woyo/world/attributes.rb in woyo-world-0.0.5 vs lib/woyo/world/attributes.rb in woyo-world-0.0.6

- old
+ new

@@ -1,59 +1,203 @@ +require_relative 'group' +class Hash + alias_method :names, :keys +end + module Woyo module Attributes + def self.included(base) + base.extend(ClassMethods) + end + + def self.prepended(base) + base.singleton_class.prepend(ClassMethods) # base.extend(ClassMethods) also seems to work, what's the diff ? + end + + def initialize *args + initialize_attributes + initialize_groups + initialize_boolean_groups + initialize_is_overrides + #super # we'll need this if we prepend Attributes again + end + module ClassMethods - def create_attribute_methods_with_define_method attr, default = nil + def define_attr_methods attr, default = nil + define_attr_default attr, default + define_attr_equals attr + define_attr attr + if default == true || default == false # boolean convenience methods + define_attr? attr + define_attr! attr + end + end + + def define_attr_default attr, default + define_method "#{attr}_default" do + if default.respond_to? :call + return default.arity == 0 ? default.call : default.call(self) + end + default + end + end + + def define_attr_equals attr define_method "#{attr}=" do |arg| attributes[attr] = arg end + end + + def define_attr attr define_method attr do |arg = nil| - if arg.nil? - unless attributes.has_key? attr - if default.respond_to? :call - if default.arity == 0 - attributes[attr] = default.call # todo: is this the same as ? ... instance_eval &default - else - attributes[attr] = default.call(self) - end - else - attributes[attr] = default - end - end - attributes[attr] - else - attributes[attr] = arg - end + return attributes[attr] = arg unless arg.nil? + return attributes[attr] unless attributes[attr].kind_of? Hash + true_attribute_match = attributes[attr].detect { |name,value| attributes[name] == true } + return true_attribute_match[1] if true_attribute_match + attributes[attr] end end + def define_attr? attr + define_method "#{attr}?" do + ( send attr ) ? true : false + end + end + + def define_attr! attr + define_method "#{attr}!" do + send "#{attr}=", true + end + end + def attributes *attrs @attributes ||= [] return @attributes if attrs.empty? attrs.each do |attr| if attr.kind_of? Hash attr.each do |attr_sym,default_value| - @attributes << attr_sym - create_attribute_methods_with_define_method attr_sym, default_value + @attributes << attr_sym unless @attributes.include? attr_sym + define_attr_methods attr_sym, default_value end else - @attributes << attr - create_attribute_methods_with_define_method attr + unless @attributes.include? attr + @attributes << attr + define_attr_methods attr + end end end end - end + def attribute *attrs + self.attributes *attrs + end - def self.included(base) - base.extend(ClassMethods) + def groups + @groups ||= {} + end + + def group sym, *attrs + @groups ||= {} + group = @groups[sym] ? @groups[sym] : ( @groups[sym] = [] ) + self.attributes *attrs + attrs.each do |attr| + if attr.kind_of? Hash + attr.each do |attr_sym,default_value| + group << attr_sym + end + else + group << attr + end + end + define_method sym do + groups[sym] + end + group + end + + def boolean_groups + @boolean_groups ||={} + end + + def group! sym, *attrs + @boolean_groups ||= {} + group = @boolean_groups[sym] ? @boolean_groups[sym] : ( @boolean_groups[sym] = [] ) + self.attributes *attrs + attrs.each do |attr| + define_attr? attr + define_attr! attr + if attr.kind_of? Hash + attr.each do |attr_sym,default_value| + group << attr_sym + end + else + group << attr + end + end + define_method sym do + boolean_groups[sym] + end + group + end + + def is *attrs + @is_overrides ||= [] + attrs.each do |attr| + @is_overrides << attr unless @is_overrides.include? attr + self.attribute( { attr => true } ) + end + end + + def is_overrides + @is_overrides ||= [] + end + + end # module ClassMethods + + def initialize_attributes + @attributes = self.class.attributes.each_with_object(Woyo::Attributes::AttributesHash.new) do |attr,hash| + hash[attr] = send "#{attr}_default" + end end - + + def initialize_groups + @groups = {} + self.class.groups.each { |sym,members| @groups[sym] = Woyo::Attributes::Group.new @attributes, *members } + @groups + end + + def initialize_boolean_groups + @boolean_groups = {} + self.class.boolean_groups.each { |sym,members| @boolean_groups[sym] = Woyo::Attributes::BooleanGroup.new @attributes, *members } + @boolean_groups + end + + def initialize_is_overrides + self.class.is_overrides.each { |attr| send "#{attr}!" } + end + def attributes - @attributes ||= {} + @attributes + end + + def groups + @groups + end + + def boolean_groups + @boolean_groups + end + + def is? attr + send "#{attr}?" + end + + def is attr + send "#{attr}=", true end end end