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