module Attributes

Constants

VERSION

Public Class Methods

version() click to toggle source
# File lib/attributes-5.0.0.rb, line 3
def self.version() Attributes::VERSION end

Public Instance Methods

attributes(*a, &b) click to toggle source
# File lib/attributes-5.0.0.rb, line 26
def attributes *a, &b
  unless a.empty?
    returned = Hash.new

    hashes, names = a.partition{|x| Hash === x}
    names_and_defaults = {}
    hashes.each{|h| names_and_defaults.update h}
    names.flatten.compact.each{|name| names_and_defaults.update name => nil}

    initializers = __attributes__.initializers

    names_and_defaults.each do |name, default|
      raise NameError, "bad instance variable name '@#{ name }'" if "@#{ name }" =~ /[!?=]$/o
      name = name.to_s

      initialize = b || lambda { default }
      initializer = lambda do |this|
        Object.instance_method('instance_eval').bind(this).call &initialize
      end
      initializer_id = initializer.object_id
      __attributes__.initializers[name] = initializer

      module_eval <<-code
        def #{ name }=(*value, &block)
          value.unshift block if block
          @#{ name } = value.first
        end
      code

      module_eval <<-code
        def #{ name }(*value, &block)
          value.unshift block if block
          return self.send('#{ name }=', value.first) unless value.empty?
          #{ name }! unless defined? @#{ name }
          @#{ name }
        end
      code

      module_eval <<-code
        def #{ name }!
          initializer = ObjectSpace._id2ref #{ initializer_id }
          self.#{ name } = initializer.call(self)
          @#{ name }
        end
      code

      module_eval <<-code
        def #{ name }?
          #{ name }
        end
      code

      attributes << name
      returned[name] = initializer 
    end

    returned
  else
    begin
      __attribute_list__
    rescue NameError
      singleton_class =
        class << self
          self
        end
      klass = self
      singleton_class.module_eval do
        attribute_list = List.new 
        define_method('attribute_list'){ klass == self ? attribute_list : raise(NameError) }
        alias_method '__attribute_list__', 'attribute_list'
      end
      __attribute_list__
    end
  end
end