module ModuleCreationHelper
module Extensions #:nodoc:
# Adds helper methods for easily generating new modules/classes
module Module
# Creates a new module with the specified name. This is essentially the
# same as actually defining the module like so:
#
# module NewModule
# end
#
# or as a class:
#
# class NewClass < SuperKlass
# end
#
# Configuration options:
# * :superclass - The class to inherit from. This only applies
# when using Class#create. Default is Object.
# * :parent - The class/module that contains this module.
# Default is Object.
#
# == Examples
#
# Module.create('Foo') # => Foo
# Module.create('Bar', :parent => Foo) # => Foo::Bar
# Class.create('Waddle') # => Waddle
# Class.create('Widdle', :parent => Waddle) # => Waddle::Widdle
# Class.create('Woddle', :superclass => Waddle::Widdle, :parent => Waddle) # => Waddle::Woddle
# Waddle::Woddle.superclass # => Waddle::Widdle
#
# == Setting the parent
#
# Rather than setting the parent directly using the +parent+ configuration
# option, you can specify it in the actual name of the class like so:
#
# Module.create('Foo::Bar') # => Foo::Bar
#
# This has the same effect as the following:
#
# Module.create('Bar', :parent => Foo)
def create(name, options = {}, &block)
# Validate the provided options
invalid_options = options.keys - [:superclass, :parent]
raise ArgumentError, "Unknown key(s): #{invalid_options.join(", ")}" unless invalid_options.empty?
# Validate usage of :superclass option
raise ArgumentError, 'Modules cannot have superclasses' if options[:superclass] && self.to_s == 'Module'
options = {:superclass => Object, :parent => Object}.merge(options)
parent = options[:parent]
superclass = options[:superclass]
if superclass != Object
superclass = " < ::#{superclass}"
else
superclass = ''
end
mod = parent.class_eval <<-end_eval
#{self.to_s.downcase} #{name}#{superclass}
self
end
end_eval
mod.class_eval(&block) if block_given?
mod
end
end
end
end
Module.class_eval do
extend ModuleCreationHelper::Extensions::Module
end