class Module
  
  private
  
  # In a module definition you can include a call to
  # included_in_class_callbacks(base) at the end of the
  # self.included(base) callback. Any modules that your module includes
  # will receive an included_in_class callback when your module is
  # included in a class. Useful if the sub-module wants to do something
  # like alias_method_chain on the class.
  def included_in_class_callbacks(base)
    if base.is_a?(Class)
      included_modules.each { |m| m.included_in_class(base) if m.respond_to?(:included_in_class) }
    end
  end
  
  # Creates a class attribute reader that will delegate to the superclass
  # if not defined on self
  def inheriting_cattr_reader(*names)
    names_with_defaults = (names.pop if names.last.is_a?(Hash)) || {}
    
    names_with_defaults.each do |name, default|
      instance_variable_set("@#{name}", default) unless instance_variable_get("@#{name}") != nil || superclass.respond_to?(name)
    end
    
    (names + names_with_defaults.keys).each do |name|
      class_eval %{
        def self.#{name}
          if defined? @#{name}
            @#{name}
          elsif superclass.respond_to?('#{name}')
            superclass.#{name}
          end
        end
      }
    end
  end
  
  # creates a #foo= and #foo? pair, with optional default values, e.g.
  # bool_attr_accessor :happy => true
  def bool_attr_accessor(*args)
    options = (args.pop if args.last.is_a?(Hash)) || {}
    
    (args + options.keys).each {|n| class_eval "def #{n}=(x); @#{n} = x; end" }
    
    args.each {|n| class_eval "def #{n}?; @#{n}; end" }

    options.keys.each do |n|
      class_eval %(def #{n}?
                     if !defined? @#{n}
                       @#{n} = #{options[n] ? 'true' : 'false'}
                     else
                       @#{n}
                     end
                   end)
      set_field_type(n => TrueClass) if respond_to?(:set_field_type)
    end
  end
  
  def alias_class_method_chain(method, feature)
    meta_eval do
      alias_method_chain method, feature
    end
  end

end


# classy_module lets you extract code from classes into modules, but
# still write it the same way
module Kernel
  
  def classy_module(&b)
    m = Module.new
    m.meta_def :included do |base|
      base.class_eval &b
    end
    m
  end
  
end