Method: Module#create

Defined in:
lib/quality_extensions/module/create.rb

#create(name, options = {}, &block) ⇒ Object

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. namespace/parent - The class/module namespace that contains this module. Default is Object.

You can also include the namespace in the name if you’d prefer. For instance, name = :'Foo::Bar' is the same as specifying name = :Bar, :namespace => Foo. (Note: The namespace module specified must already be defined, just like it would have to be defined if you used the :namespace option.)

Examples:

Module.create(:Foo)                                                      # => Foo
Module.create(:'Foo::Bar', :namespace => Foo)                            # => Foo::Bar
Module.create(:Bar, :namespace => Foo)                                   # => Foo::Bar

Class.create(:Base)                                                      # => Base
Class.create(:'Foo::Klass', :superclass => Base)                         # => Foo::Klass

Unlike the built-in Ruby module/class directive, this actually returns the newly created module/class as the return value. So, for example, you can do things like this:

klass = Class.create(:'Foo::Klass', :superclass => Class.create(:Base))  # => Foo::Klass
klass.name                                                               # => Foo::Klass
klass.superclass                                                         # => Base

You can also pass a block to create. This:

Class.create(:ClassWithBlock, :superclass => BaseClass) do
  def self.say_hello
    'hello'
  end
end

is equivalent to this:

class ClassWithBlock < BaseClass do
  def self.say_hello
    'hello'
  end
end

Raises:

  • (ArgumentError)


85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
# File 'lib/quality_extensions/module/create.rb', line 85

def create(name, options = {}, &block)
  # Validate arguments
  raise ArgumentError unless name.respond_to?(:to_s)
  options[:namespace] = options.delete(:parent) if options.has_key?(:parent)
  options.assert_has_only_keys(
    :superclass,
    :namespace
  )
  module_or_class = self.to_s.downcase
  raise ArgumentError, 'Modules cannot have superclasses' if options[:superclass] && module_or_class == 'module'

  # Set defaults
  namespace_module, superclass =
    options[:namespace]  || ::Object, 
    options[:superclass] || ::Object

  # Determine the namespace to create it in
  nesting = Module.split_name(name)
  if nesting.size > 1
    namespace_module = Module.namespace_of(name) # For example, would be A::B for A::B::C
    base_name = Module.basename(name)            # For example, would be :C   for A::B::C
  else
    base_name = name
  end
  
  # Actually create the new module
  if superclass != ::Object
    superclass = " < ::#{superclass}"
  else
    superclass = ''
  end
  namespace_module.class_eval <<-end_eval, __FILE__, __LINE__
    #{module_or_class} #{base_name}#{superclass}
      # Empty
    end
  end_eval
  our_new_module = namespace_module.const_get(base_name)
  
  our_new_module.class_eval(&block) if block_given?
  our_new_module
end