# class Module

### Public Instance Methods

*(rename_map) click to toggle source

Rename methods.

    module AStar
      def a; "a"; end
    end

    BStar = AStar * { :a => :b }

    class XStar; include BStar; end

    XStar.new.b    #=> "a"

CREDIT: Thomas Sawyer, Robert Dober

    # File lib/facets/module/op.rb, line 95
    def *(rename_map)
      base = self
      Module.new do
        include base
        rename_map.each do |from, to|
          alias_method to, from
          undef_method from
        end
      end
    end

+(other) click to toggle source

Combine modules.

    module APlus
      def a; "a"; end
    end

    module BPlus
      def b; "b"; end
    end

    CPlus = APlus + BPlus

    class XPlus; include CPlus; end

    XPlus.new.a    #=> "a"
    XPlus.new.b    #=> "b"

Note that in the old version of traits.rb we cloned modules and altered their copies…

    def +(other)
      mod1 = other.clone
      mod2 = clone
      mod1.module_eval{ include mod2 }
    end

Later it was realized that this thwarted the main benefit that Ruby's concept of modules has over traditional traits, inheritance.

CREDIT: Thomas Sawyer, Robert Dober

    # File lib/facets/module/op.rb, line 35
    def +(other)
      base = self
      Module.new do
        include base
        include other
      end
    end

-(other) click to toggle source

Subtract modules.

    module AMinus
      def a; "a"; end
      def b; "b"; end
    end

    CMinus = AMinus - [:a]

    class XMinus; include CMinus; end

    expect NameError do
      XMinus.new.a  #=> "a"
    end

    XMinus.new.b    #=> "b"

TODO: Should this use all instance methods, not just public?

CREDIT: Thomas Sawyer, Robert Dober

    # File lib/facets/module/op.rb, line 64
    def -(other)
      instance_methods = instance_methods(true).map{|m| m.to_sym}
      case other
      when Array
        subtract = instance_methods & other.map{|m| m.to_sym}
      when Module
        subtract = instance_methods & other.instance_methods(true).map{|m| m.to_sym}  # false?
      when String, Symbol
        subtract = instance_methods & [other.to_sym]
      end
      base = self
      Module.new do
        include base
        subtract.each{ |x| undef_method x }
      end
    end

abstract(*sym) click to toggle source

Create an abstract method. If it is not overridden, it will raise a TypeError when called.

    class AbstractExample
      abstract :a
    end

    c = AbstractExample.new

    expect TypeError do
      c.a
    end

CREDIT: Trans

    # File lib/facets/module/abstract.rb, line 18
    def abstract(*sym)
      sym.each do |s|
        define_method(s){ raise TypeError, "undefined abstraction ##{s}" }
      end
    end

alias_method_chain(target, feature) { |aliased_target, punctuation| ... } click to toggle source

Encapsulates the common pattern of …

    alias_method :foo_without_feature, :foo
    alias_method :foo, :foo_with_feature

With this, you simply do …

    alias_method_chain :foo, :feature

For example

    class AliasMethodChainExample
      def foo
        "foo"
      end

      def foo_with_feature
        "foo!"
      end

      alias_method_chain :foo, :feature
    end

And both aliases are set up for you.

    example = AliasMethodChainExample.new
    example.foo #=> "foo!"
    example.foo_without_feature #=> "foo"

Query and bang methods (foo?, foo!) keep the same punctuation …

    alias_method_chain :foo?, :feature

is equivalent to …

    alias_method :foo_without_feature?, :foo?
    alias_method :foo?, :foo_with_feature?

so you can safely chain foo, foo?, and foo! with the same feature.

CREDIT: Bitsweat, Rails Team

    # File lib/facets/module/alias_method_chain.rb, line 45
    def alias_method_chain(target, feature)
      # Strip out punctuation on predicates or bang methods since
      # e.g. target?_without_feature is not a valid method name.
      aliased_target, punctuation = target.to_s.sub(/([?!=])$/, ''), $1
      yield(aliased_target, punctuation) if block_given?

      with_method, without_method = "#{aliased_target}_with_#{feature}#{punctuation}", "#{aliased_target}_without_#{feature}#{punctuation}"

      alias_method without_method, target
      alias_method target, with_method

      case
        when public_method_defined?(without_method)
          public target
        when protected_method_defined?(without_method)
          protected target
        when private_method_defined?(without_method)
          private target
      end
    end

alias_tester(*args) click to toggle source

Create aliases for flag reader.

Note that this method is not a common core extension and is not loaded automatically when using `require 'facets'`.

CREDIT: Trans

@uncommon

    require 'facets/module/attr_tester'

    # File lib/facets/module/attr_tester.rb, line 48
    def alias_tester(*args)
      orig = args.last
      args = args - [orig]
      args.each do |name|
        alias_method("#{name}?", "#{orig}?")
      end
    end

alias_validator(*args) click to toggle source

Create aliases for validator attribute methods.

NOTE: This method is not a common core extension and is not loaded automatically when using `require 'facets'`.

@uncommon

    require 'facets/module/attr_validator'

    # File lib/facets/module/attr_validator.rb, line 36
    def alias_validator(*args)
      orig = args.last
      args = args - [orig]
      args.each do |name|
        #alias_method(name, orig)
        alias_method("#{name}=", "#{orig}=")
      end
    end

all_instance_methods(include_super=true) click to toggle source

List all instance methods, equivalent to

    public_instance_methods +
    protected_instance_methods +
    private_instance_methods

TODO: Better name for all_instance_methods?

CREDIT: Trans

    # File lib/facets/module/all_instance_methods.rb, line 13
    def all_instance_methods(include_super=true)
      public_instance_methods(include_super) +
      protected_instance_methods(include_super) +
      private_instance_methods(include_super)
    end

ancestor?( mod ) click to toggle source

Is a given class or module an ancestor of this class or module?

    class X ; end
    class Y < X ; end

     X.ancestor?(Y)

    # File lib/facets/module/ancestor.rb, line 11
    def ancestor?( mod )
      ancestors.include?(mod)
    end

anonymous?() click to toggle source

A module may or may not have a name.

module M; end M.name # => “M”

m = Module.new m.name # => “”

A module gets a name when it is first assigned to a constant. Either via the `module` or `class` keyword or by an explicit assignment:

m = Module.new # creates an anonymous module M = m # => m gets a name here as a side-effect m.name # => “M”

    # File lib/facets/module/anonymous.rb, line 18
    def anonymous?
      # The name of an anonymous class is an empty
      # string in 1.8, and nil in 1.9.
      name.nil? || name.empty?
    end

attr_class_accessor(name) click to toggle source

NOTE: This method is not a common core extension and is not loaded automatically when using `require 'facets'`.

@uncommon

    require 'facets/module/attr_class_accessor'

    # File lib/facets/module/attr_class_accessor.rb, line 10
    def attr_class_accessor(name)
      attr_class_reader(name)
      attr_class_writer(name)
    end

attr_class_reader(name) click to toggle source

NOTE: This method is not a common core extension and is not loaded automatically when using `require 'facets'`.

@uncommon

    require 'facets/module/attr_class_reader'

    # File lib/facets/module/attr_class_accessor.rb, line 22
      def attr_class_reader(name)
        module_eval("      def self.#{name}
            @#{name}
          end
          def #{name}
            self.class.#{name}
          end
    ", __FILE__, __LINE__)
      end

attr_class_writer(name) click to toggle source

NOTE: This method is not a common core extension and is not loaded automatically when using `require 'facets'`.

@uncommon

    require 'facets/module/attr_class_writer'

    # File lib/facets/module/attr_class_accessor.rb, line 40
      def attr_class_writer(name)
        module_eval("      def self.#{name}=(x)
            @#{name} = x
          end
          def #{name}=(x)
            self.class.#{name} = x
          end
    ", __FILE__, __LINE__)
      end

attr_setter(*args) click to toggle source

Create an attribute method for both getting and setting an instance variable:

    attr_setter :a

is equivalent to:

    def a(*args)
      if args.size > 0
        @a = args[0]
        self
      else
        @a
      end
    end

CREDIT: Trans

    # File lib/facets/module/attr_setter.rb, line 21
    def attr_setter(*args)
      code, made = '', []
      args.each do |a|
        code << %Q{
          def #{a}(*args)
            args.size > 0 ? ( @#{a}=args[0] ; self ) : @#{a}
          end
        }
        made << "#{a}".to_sym
      end
      module_eval code
      made
    end

attr_tester(*args) click to toggle source

Create an tester attribute. This creates a single method used to test the attribute for truth.

    attr_tester :a

is equivalent to

    def a?
      @a ? true : @a
    end

Note that this method is not a common core extension and is not loaded automatically when using `require 'facets'`.

CREDIT: Trans

@todo This method will probably be deprecated.

@uncommon

    require 'facets/module/attr_tester'

    # File lib/facets/module/attr_tester.rb, line 24
    def attr_tester(*args)
      code, made = '', []
      args.each do |a|
        code << %Q{
          def #{a}?(truth=nil)
            @#{a} ? truth || @#{a} : @#{a}
          end
        }
        made << "#{a}?".to_sym
      end
      module_eval code
      made
    end

attr_validator(*symbols, &validator) click to toggle source

Like attr_writer, but the writer method validates the setting against the given block.

NOTE: This method is not a common core extension and is not loaded automatically when using `require 'facets'`.

CREDIT: ?

@uncommon

    require 'facets/module/attr_validator'

    # File lib/facets/module/attr_validator.rb, line 14
    def attr_validator(*symbols, &validator)
      made = []
      symbols.each do |symbol|
        define_method "#{symbol}=" do |val|
          unless validator.call(val)
            raise ArgumentError, "Invalid value provided for #{symbol}"
          end
          instance_variable_set("@#{symbol}", val)
        end
        made << "#{symbol}=".to_sym
      end
      made
    end

basename() click to toggle source

Returns the root name of the module/class.

    module ::BaseName
      class Example
      end
    end

    BaseName::Example.name       #=> "BaseName::Example"
    BaseName::Example.basename   #=> "Example"

For anonymous modules this will provide a basename based on Module#inspect.

    m = Module.new
    m.inspect       # "#<Module:0xb7bb0434>"
    m.basename      # "Module_0xb7bb0434"

CREDIT: Trans

    # File lib/facets/module/basename.rb, line 22
    def basename
      if name and not name.empty?
        name.gsub(/^.*::/, '')
      else
        nil #inspect.gsub('#<','').gsub('>','').sub(':', '_')
      end
    end

cattr(*syms) click to toggle source

Creates a class-variable attribute that can be accessed both on an instance and class level.

    class CARExample
      @@a = 10
      cattr :a
    end

    CARExample.a           #=> 10
    CARExample.new.a       #=> 10

NOTE: This method is not a common core extension and is not loaded automatically when using `require 'facets'`.

CREDIT: David Heinemeier Hansson

@uncommon

    require 'facets/module/cattr'

    # File lib/facets/module/mattr.rb, line 22
    def cattr(*syms)
      writers, readers = syms.flatten.partition{ |a| a.to_s =~ /=$/ }
      writers = writers.map{ |e| e.to_s.chomp('=').to_sym }
      ##readers.concat( writers ) # writers also get readers

      cattr_reader(*readers)
      cattr_writer(*writers)

      return readers + writers
    end

cattr_accessor(*syms) click to toggle source

Creates a class-variable attr_accessor that can be accessed both on an instance and class level.

    class CAAExample
      cattr_accessor :a
    end

    CAAExample.a = 10
    CAAExample.a           #=> 10
    mc = CAAExample.new
    mc.a                   #=> 10

NOTE: This method is not a common core extension and is not loaded automatically when using `require 'facets'`.

CREDIT: David Heinemeier Hansson

@uncommon

    require 'facets/module/cattr'

    # File lib/facets/module/mattr.rb, line 133
    def cattr_accessor(*syms)
      cattr_reader(*syms) + cattr_writer(*syms)
    end

cattr_reader(*syms) click to toggle source

Creates a class-variable attr_reader that can be accessed both on an instance and class level.

    class CARExample
      @@a = 10
      cattr_reader :a
    end

    CARExample.a           #=> 10
    CARExample.new.a       #=> 10

NOTE: This method is not a common core extension and is not loaded automatically when using `require 'facets'`.

CREDIT: David Heinemeier Hansson

@uncommon

    require 'facets/module/cattr'

    # File lib/facets/module/mattr.rb, line 52
      def cattr_reader(*syms)
        syms.flatten.each do |sym|
          module_eval("        unless defined? @@#{sym}
              @@#{sym} = nil
            end

            def self.#{sym}
              @@#{sym}
            end

            def #{sym}
              @@#{sym}
            end
    ", __FILE__, __LINE__)
        end
        return syms
      end

cattr_writer(*syms) click to toggle source

Creates a class-variable attr_writer that can be accessed both on an instance and class level.

    class CAWExample
      cattr_writer :a
      def self.a
        @@a
      end
    end

    CAWExample.a = 10
    CAWExample.a            #=> 10
    CAWExample.new.a = 29
    CAWExample.a            #=> 29

NOTE: This method is not a common core extension and is not loaded automatically when using `require 'facets'`.

CREDIT: David Heinemeier Hansson

@uncommon

    require 'facets/module/cattr'

    # File lib/facets/module/mattr.rb, line 94
      def cattr_writer(*syms)
        syms.flatten.each do |sym|
          module_eval("        unless defined? @@#{sym}
              @@#{sym} = nil
            end

            def self.#{sym}=(obj)
              @@#{sym} = obj
            end

            def #{sym}=(obj)
              @@#{sym}=(obj)
            end
    ", __FILE__, __LINE__)
        end
        return syms
      end

class_accessor(name) click to toggle source

NOTE: This method is not a common core extension and is not loaded automatically when using `require 'facets'`.

@uncommon

    require 'facets/module/class_accessor'

    # File lib/facets/module/class_accessor.rb, line 10
    def class_accessor(name)
      class_reader(name)
      class_writer(name)
    end

class_def(name, &blk) click to toggle source

Defines an instance method within a class/module.

CREDIT: WhyTheLuckyStiff

    # File lib/facets/module/module_def.rb, line 7
    def class_def name, &blk
      class_eval { define_method name, &blk }
    end

class_extend(*mods, &block) click to toggle source

Normally when including modules, class/module methods are not extended. To achieve this behavior requires some clever Ruby Karate. Instead class_extend provides an easy to use and clean solution. Simply place the extending class methods in a block of the special module method class_extend.

    module Mix
      def inst_meth
        puts 'inst_meth'
      end

      class_extend do
        def class_meth
          "Class Method!"
        end
      end
    end

    class X
      include Mix
    end

    X.class_meth  #=> "Class Method!"

NOTE: This old class_extension version of this method did not extend the containing class automatically –it had to be done by hand. With class_extend, that is no longer the case.

NOTE: This method is not a common core extension and is not loaded automatically when using `require 'facets'`.

CREDIT: Daniel Schierbeck, Thomas Sawyer

THANKS: Nobu Nakada, Ulysses

@uncommon

    require 'facets/module/class_extend'

    # File lib/facets/module/class_extend.rb, line 42
    def class_extend(*mods, &block)
      class_extension = Module.new

      class_extension.__send__(:include, *mods)
      class_extension.module_eval(&block) if block_given?

      extend(class_extension)  # extend this module too

      append_method = method(:append_features)

      (class << self; self; end).class_eval do
        define_method(:append_features) do |mod|
          append_method.call(mod)
          mod.extend(class_extension)
          if mod.instance_of?(Module)
            mod.__send__(:class_extend, class_extension)
          end
        end
      end

      class_extensions << class_extension
    end

class_extensions() click to toggle source

    # File lib/facets/module/class_extend.rb, line 68
    def class_extensions
      @class_extensions ||= []
    end

class_inheritor(key, obj, op=nil, &fop) click to toggle source

# Class Inheritor¶ ↑

Create an dynamic class inheritable attribute.

Inheritor providse a means to store and inherit data via the class heirarchy. An inheritor creates two methods one named after the key that provides a reader. And one named after key! which provides the writer. (Because of the unique nature of inheritor the reader and writer can't be the same method.)

The first argument is the inheritor's name. The second argument is the archtype object. This object must be duplicable (via dup). The last argument is either the symbolic operator/method or a block that specifies how one hierarchical level “integrates” with the next.

    class X
      class_inheritor :x, [], :+
    end

    class Y < X
    end

    X.x! << :a
    X.x  #=> [:a]
    Y.x  #=> [:a]

    Y.x! << :b
    X.x  #=> [:a]
    Y.x  #=> [:a, :b]

NOTE: Adding an inheritor directly to Module or Class will probably not do what is expected. Thankfully that usecase is likely a YAGNI, but in anycase it is even more likely that it is not possible with this code.

NOTE: This method is not a common core extension and is not loaded automatically when using `require 'facets'`.

CREDIT: Thomas Sawyer

@uncommon

    require 'facets/module/class_inheritor'

    # File lib/facets/module/class_inheritor.rb, line 48
    def class_inheritor(key, obj, op=nil, &fop)
      raise ArgumentError if op && fop

      if !fop
        op  = op ? op.to_sym : :+
        fop = lambda{ |o, x| o.__send__(op, x) }
      end

      #(class << self; self; end).module_eval do
      class_extend do

        define_method(key) do
          ancestors.reverse.inject(obj.dup) do |o, a|
            if a.respond_to?("#{key}!")
              fop.call(o, a.__send__("#{key}!"))
            else
              o
            end
          end
        end

        define_method("#{key}!") do
          if instance_variable_defined?("@#{key}")
            instance_variable_get("@#{key}")
          else
            instance_variable_set("@#{key}", obj.dup)
          end
        end

      end
    end

class_load( path )
Alias for: module_load
class_method_defined?(meth)
Alias for: singleton_method_defined?
class_reader(name) click to toggle source

NOTE: This method is not a common core extension and is not loaded automatically when using `require 'facets'`.

@uncommon

    require 'facets/module/class_reader'

    # File lib/facets/module/class_accessor.rb, line 22
      def class_reader(name)
        module_eval("      def self.#{name}
            @#{name}
          end
    ", __FILE__, __LINE__)
      end

class_require( path )
Alias for: module_require
class_writer(name) click to toggle source

NOTE: This method is not a common core extension and is not loaded automatically when using `require 'facets'`.

@uncommon

    require 'facets/module/class_writer'

    # File lib/facets/module/class_accessor.rb, line 37
      def class_writer(name)
        module_eval("      def self.#{name}=(x)
            @#{name} = x
          end
    ", __FILE__, __LINE__)
      end

copy_inheritor(name, default={}) click to toggle source

Like class_inheritor but non-dynamic. The value of the inheritor is copied from the ancestor on first read.

    c = Class.new do
      def self.x; ['x']; end
    end

    d = Class.new(c) do
      copy_inheritor :x
    end

    d.x  #=> ['x']

NOTE: This method is not a common core extension and is not loaded automatically when using `require 'facets'`.

CREDIT: Thomas Sawyer

@uncommon

    require 'facets/module/copy_inheritor'

    # File lib/facets/module/copy_inheritor.rb, line 26
    def copy_inheritor(name, default={})
      class_extend do
        define_method(name) do
          if instance_variable_defined?("@#{name}")
            instance_variable_get("@#{name}")
          else
            if anc = ancestors[1..-1].find{ |a| a.respond_to?(name) }
              value = anc.__send__(name)
              value = value.dup rescue value
              instance_variable_set("@#{name}", value)
            else
              instance_variable_set("@#{name}", default)
            end
          end
        end
      end
    end

enclosure() click to toggle source

Returns the module which contains this one according to its name.

    module ::EncExample
      module M
        module N
        end
      end
    end

    EncExample::M::N.enclosure  #=> EncExample::M

The enclosure of top-level and anonymous modules is Object.

    EncExample.enclosure   #=> Object
    Module.new.enclosure   #=> Object

NOTE: This method is not a common core extension and is not loaded automatically when using `require 'facets'`.

@uncommon

    require 'facets/module/enclosure'

    # File lib/facets/module/enclosure.rb, line 25
    def enclosure
      name = /::[^:]+\Z/ =~ self.name ? $` : nil
      if name
        #base = name.sub!(/^::/, '') ? Object : self
        name.split(/::/).inject(self) do |mod, cref|
          if /\:(0x.*?)\>$/ =~ cref   # TODO: does this ever happen?
            #p $1.to_i(16)
            ObjectSpace._idref($1.to_i(16))
          else
            mod.const_get(cref)
          end
        end
      else
        Object
      end
    end

enclosures() click to toggle source

Returns all the namespaces of this module according ordered from nearest and moving outwards. The receiver is not contained within the result.

    module ::EncExample
      module M
        module N
        end
      end
    end

    EncExample.enclosures        #=> [Object]
    EncExample::M.enclosures     #=> [EncExample, Object]
    EncExample::M::N.enclosures  #=> [EncExample::M, EncExample, Object]

NOTE: This method is not a common core extension and is not loaded automatically when using `require 'facets'`.

@uncommon

    require 'facets/module/enclosures'

    # File lib/facets/module/enclosure.rb, line 63
    def enclosures
      n = []
      name.split(/::/).inject(self) do |mod, cref|
        c = mod.const_get(cref) ; n.unshift(c) ; c
      end
      n << Object # ?
      n.shift # we really don't need +self+ too.
      n
    end

encname() click to toggle source

Enclosure name.

    module ::EncExample
      module M
        module N
        end
      end
    end

    EncExample::M::N.encname  #=> "EncExample::M"

NOTE: This method is not a common core extension and is not loaded automatically when using `require 'facets'`.

@uncommon

    require 'facets/module/enclosure'

    # File lib/facets/module/enclosure.rb, line 90
    def encname
      /::[^:]+\Z/ =~ self.name ? $` : nil
    end

home() click to toggle source

Returns the module or class containing the receiver.

    module ::HomeExample
      module M
        module N
        end
      end
    end

    HomeExample::M::N.home  #=> HomeExample::M

The home of a top-level module/class is Object.

    HomeExample.home   #=> Object

This method is called home because techinally a module or class is just a constant reference, and as such can reside with multiple namespaces, like any variable. For example:

    module OtherPlace
      M = ::HomeExample::M
    end

In this example, you might think that +OtherPlace::M+'s home would be `OtherPlace`, but +OtherPlace::M+ is the same object as +HomeExample::M+, and it can have only one “home” –the original location of it's definition.

    # File lib/facets/module/home.rb, line 29
    def home
      #homename = /::[^:]+\Z/ =~ name ? $` : nil
      if homename
        homename.split(/::/).inject(self) do |mod, cref|
          if /\:(0x.*?)\>$/ =~ cref   # TODO: does this ever happen?
            #p $1.to_i(16)
            ObjectSpace._idref($1.to_i(16))
          else
            mod.const_get(cref)
          end
        end
      else
        Object
      end
    end

homename() click to toggle source

Returns the name of module or class containing the receiver.

    module ::HomeExample
      module M
        module N
        end
      end
    end

    HomeExample::M::N.homename  #=> "HomeExample::M"

See also #basename.

    # File lib/facets/module/home.rb, line 57
    def homename
      /::[^:]+\Z/ =~ name ? $` : nil
    end

Also aliased as: modname
housing() click to toggle source

Returns all the namespaces of this module according ordered from nearest and moving outwards. The receiver is not contained within the result.

    module ::HouseExample
      module M
        module N
        end
      end
    end

    HouseExample.housing        #=> [Object]
    HouseExample::M.housing     #=> [HouseExample, Object]
    HouseExample::M::N.housing  #=> [HouseExample::M, HouseExample, Object]

Compare this to `Module.nesting`.

    # File lib/facets/module/home.rb, line 80
    def housing
      n = []
      name.split(/::/).inject(self) do |mod, cref|
        c = mod.const_get(cref) ; n.unshift(c) ; c
      end
      n << Object # ?
      n.shift # we really don't need +self+ too.
      n
    end

include_as(h) click to toggle source

Include a module via a specified space.

    module T
      def t ; "HERE" ; end
    end

    class X
      include_as :test => T
      def t ; test.t ; end
    end

    X.new.t  #=> "HERE"

NOTE: This method is not a common core extension and is not loaded automatically when using `require 'facets'`.

@uncommon

    require 'facets/module/method_space'

    # File lib/facets/module/method_space.rb, line 103
    def include_as(h)
      h.each{ |name, mod| method_space(name, mod) }
    end

instance_function(*meths) click to toggle source

Converts module methods into instance methods such that the first parameter is passed `self`. This promotes DRY programming when wishing to offer both inheritable and module callable procedures.

This method is modeled after `module_function` which essentially has the the opposite effect. Due to implementation limitations, this must use the callback singleton_method_added to emulate `module_function` when no method names are given.

    module MyModule
      instance_function

      def self.jumble(obj, arg)
        obj + arg
      end
    end

    MyModule.jumble("Try", "Me")  #=> "TryMe"

    s = "Try"
    s.extend MyModule
    s.jumble("Me")                #=> "TryMe"

Note: This used to be a module called PromoteSelf and later Instantize, before becoming a method.

NOTE: This method is not a common core extension and is not loaded automatically when using `require 'facets'`.

@uncommon

    require 'facets/module/instance_function'

    # File lib/facets/module/instance_function.rb, line 34
    def instance_function(*meths)
      this = self
      if meths.empty?
        extend InstanceFunction
      else
        meths.each do |meth|
          module_eval do
            define_method(meth) do |*args|
              this.__send__(meth, self, *args)
            end
          end
          ##class_eval %{
          ##  def #{meth}(*args)
          ##    #{self.name}.#{meth}(self,*args)
          ##  end
          ##}
        end
      end
    end

instance_method!(s) click to toggle source

Access method as a singleton object and retain state.

    module ::K
      def hello
        puts "Hello World!"
      end
    end

    K.instance_method!(:hello).inspect   #=> "#<UnboundMethod: K#hello>"

NOTE: This is limited to the scope of the current module/class.

    # File lib/facets/module/instance_method.rb, line 18
    def instance_method!(s)
      #( @@__instance_methods__ ||= {} )[s] ||= instance_method(s)  # TODO: use class vars for 1.9+ ?
      #( @__instance_methods__ ||= {} )[s.to_sym] ||= instance_method(s.to_sym)
      $FIRST_CLASS_INSTANCE_METHODS[self][s.to_sym] ||= instance_method(s.to_sym)
    end

instance_method_defined?(meth) click to toggle source

Query whether a public instance method is defined for the module.

CREDIT: Gavin Sinclair, Noah Gibbs

    # File lib/facets/module/instance_method_defined.rb, line 7
    def instance_method_defined?(meth)
      instance_methods(true).find{ |m| m.to_sym == meth.to_sym }
    end

integrate(mod, &block) click to toggle source

Using integrate is just like using include except the module included is a reconstruction of the one given altered by the commands given in the block.

Convenient commands available are: rename, redef, remove, nodef and wrap. But any module method can be used.

    module IntegrateExampleModule
      def q ; "q" ; end
      def y ; "y" ; end
    end

    class InegrateExampleClass
      integrate IntegrateExampleModule do
        undef_method :y
      end
    end

    x = InegrateExampleClass.new
    x.q  #=> "q"

    expect NameError do
      x.y
    end

This is like revisal, but revisal only returns the reconstructred module. It does not include it.

CREDIT: Trans

    # File lib/facets/module/integrate.rb, line 41
    def integrate(mod, &block)
      #include mod.revisal( &blk )
      m = Module.new{ include mod }
      m.class_eval(&block)
      include m
    end

is(*mods) click to toggle source

An alias for include.

    class IsExample
      is Enumerable
    end

CREDIT: Trans

    # File lib/facets/module/is.rb, line 25
    def is(*mods)
      mods.each do |mod|
        if mod.const_defined?(:Self)
          extend mod::Self
          # pass it along if module
          if instance_of?(Module)
            const_set(:Self, Module.new) unless const_defined?(:Self)
            const_get(:Self).send(:include, mod::Self)
          end
        end
      end
      include(*mods)
    end

is?(base) click to toggle source

Is a given class or module an ancestor of this class or module?

    class IsX ; end
    class IsY < IsX ; end

    IsY.is?(IsX)  #=> true

CREDIT: Trans

    # File lib/facets/module/is.rb, line 13
    def is?(base)
      Module===base && ancestors.slice(1..-1).include?(base)
    end

let(var,&block) click to toggle source

Create a memoized method. This method has been popularized by RSpec.

    class LetExample
      let(:seed) { rand }
    end

    eg = LetExample.new
    eg.seed == eg.seed

CREDIT: Howard Yeh

@uncommon

    require 'facets/module/let'

    # File lib/facets/module/let.rb, line 17
    def let(var,&block)
      name = "@#{var}"
      self.class_eval do
        define_method(var) do
          if instance_variable_defined?(name)
            instance_variable_get(name)
          else
            val = self.instance_eval(&block)
            instance_variable_set(name,val)
          end
        end
      end
    end

mattr(*syms) click to toggle source

Creates a class-variable attribute that can be accessed both on an instance and class level.

    c = Class.new do
      mattr :a
      def initialize
        @@a = 10
      end
    end

    c.new.a       #=> 10
    c.a           #=> 10

NOTE: The mattr methods may not be as useful for modules as the cattr methods are for classes, becuase class-level methods are not “inherited” across the metaclass for included modules.

NOTE: This methiod is not a common core extension and is not loaded automatically when using `require 'facets'`.

CREDIT: David Heinemeier Hansson

@uncommon

    require 'facets/module/cattr'

    # File lib/facets/module/mattr.rb, line 162
    def mattr(*syms)
      writers, readers = syms.flatten.partition{ |a| a.to_s =~ /=$/ }
      writers = writers.collect{ |e| e.to_s.chomp('=').to_sym }
      ##readers.concat( writers ) # writers also get readers

      mattr_writer( *writers )
      mattr_reader( *readers )

      return readers + writers
    end

mattr_accessor(*syms) click to toggle source

Creates a class-variable attr_accessor that can be accessed both on an instance and class level.

    c = Class.new do
      mattr_accessor :a
    end

    c.a = 10
    c.a           #=> 10

    x = c.new
    x.a           #=> 10

NOTE: This methiod is not a common core extension and is not loaded automatically when using `require 'facets'`.

CREDIT: David Heinemeier Hansson

@uncommon

    require 'facets/module/cattr'

    # File lib/facets/module/mattr.rb, line 275
    def mattr_accessor(*syms)
      mattr_reader(*syms) + mattr_writer(*syms)
    end

mattr_reader( *syms ) click to toggle source

Creates a class-variable attr_reader that can be accessed both on an instance and class level.

    c = Class.new do
      @@a = 10
      mattr_reader :a
    end

    c.a           #=> 10
    c.new.a       #=> 10

NOTE: This methiod is not a common core extension and is not loaded automatically when using `require 'facets'`.

CREDIT: David Heinemeier Hansson

@uncommon

    require 'facets/module/cattr'

    # File lib/facets/module/mattr.rb, line 192
      def mattr_reader( *syms )
        syms.flatten.each do |sym|
          module_eval("        unless defined? @@#{sym}
              @@#{sym} = nil
            end

            def self.#{sym}
              @@#{sym}
            end

            def #{sym}
              @@#{sym}
            end
    ", __FILE__, __LINE__)
        end
        return syms
      end

mattr_writer(*syms) click to toggle source

Creates a class-variable attr_writer that can be accessed both on an instance and class level.

    c = Class.new do
      mattr_writer :a
      def self.a
        @@a
      end
    end

    c.a = 10
    c.a            #=> 10

    c.new.a = 29
    c.a            #=> 29

NOTE: This methiod is not a common core extension and is not loaded automatically when using `require 'facets'`.

CREDIT: David Heinemeier Hansson

@uncommon

    require 'facets/module/cattr'

    # File lib/facets/module/mattr.rb, line 235
      def mattr_writer(*syms)
        syms.flatten.each do |sym|
          module_eval("        unless defined? @@#{sym}
              @@#{sym} = nil
            end

            def self.#{sym}=(obj)
              @@#{sym} = obj
            end

            def #{sym}=(obj)
              @@#{sym}=(obj)
            end
    ", __FILE__, __LINE__)
        end
        return syms
      end

memoize(*args) click to toggle source

This is here for backward compatibility.

@uncommon

    require 'facets/module/memoize'

    # File lib/facets/module/memoize.rb, line 10
    def memoize(*args)
      include Memoizable
      Memoizable.instance_method(:memoize).bind(self).call(*args)
      #super(*args)  # TODO: why is super not working here?
    end

method_clash(other) click to toggle source

Detect method name clash between modules and/or classes, regardless of method visibility:

    module MethodClashExample

      module A
        def c; end
      end

      module B
        private
        def c; end
      end

      A.method_clash(B)  #=> [:c]

    end

CREDIT: Thomas Sawyer, Robert Dober

@uncommon

    require 'facets/module/method_clash'

    # File lib/facets/module/method_clash.rb, line 30
    def method_clash(other)
      common_ancestor = (ancestors & other.ancestors).first

      s = []
      s += public_instance_methods(true)
      s += private_instance_methods(true)
      s += protected_instance_methods(true)

      o = []
      o += other.public_instance_methods(true)
      o += other.private_instance_methods(true)
      o += other.protected_instance_methods(true)

      c = s & o

      if common_ancestor
        c -= common_ancestor.public_instance_methods(true)
        c -= common_ancestor.private_instance_methods(true)
        c -= common_ancestor.protected_instance_methods(true)
      end

      return c
    end

method_clash?(other) click to toggle source

Uses method_clash to return `true` or `false` if there are method name clashes.

@uncommon

    require 'facets/module/method_clash'

    # File lib/facets/module/method_clash.rb, line 60
    def method_clash?(other)
      c = method_clash(other)
      !c.empty?
    end

method_space(name, mod=nil, &blk) click to toggle source

Create method namespaces, allowing for method chains but still accessing the object's instance.

    class A
      attr_writer :x
      method_space :inside do
        def x; @x; end
      end
    end

    a = A.new
    a.x = 10
    a.inside.x  #=> 10

    expect NoMethodError do
      a.x
    end

NOTE: This method is not a common core extension and is not loaded automatically when using `require 'facets'`.

CREDIT: Pit Captain

@uncommon

    require 'facets/module/method_space'

    # File lib/facets/module/method_space.rb, line 32
    def method_space(name, mod=nil, &blk)

      ## If block is given then create a module, otherwise
      ## get the name of the module.
      if block_given?
        name = name.to_s
        raise ArgumentError if mod
        mod  = Module.new(&blk)
      else
        if Module === name
          mod = name
          name = mod.basename.downcase
        end
        mod  = mod.dup
      end

      ## Include the module. This is neccessary, otherwise
      ## Ruby won't let us bind the instance methods.
      include mod

      ## Save the instance methods of the module and
      ## replace them with a "transparent" version.
      methods = {}
      mod.instance_methods(false).each do |m|
        methods[m.to_sym] = mod.instance_method(m)
        mod.module_eval %Q{
          def #{m}(*a,&b)
            super(*a,&b)
          end
        }
        ##mod.instance_eval do
        ##  define_method(m)
        ##    super
        ##  end
        ##end
      end

      ## Add a method for the namespace that delegates
      ## via the Functor to the saved instance methods.
      define_method(name) do
        mtab = methods
        Functor.new do |op, *args|
          if meth = mtab[op.to_sym]
            meth.bind(self).call(*args)
          else
            #self.__send__(op, *args)
            raise NoMethodError, "undefined method `#{m}'"
          end
        end
      end
    end

methodize() click to toggle source

Translate a module name to a suitable method name.

    module ::EgMethodize
      module Eg
      end
    end

    EgMethodize.methodize      #=> "eg_methodize"
    EgMethodize::Eg.methodize  #=> "eg_methodize__eg"

    # File lib/facets/module/methodize.rb, line 15
    def methodize
      name.methodize
    end

modname()

Original name for homename.

Alias for: homename
module_def(name, &blk) click to toggle source

Defines an instance method within a class/module.

CREDIT: WhyTheLuckyStiff

    # File lib/facets/module/module_def.rb, line 15
    def module_def name, &blk
      module_eval { define_method name, &blk }
    end

module_load( path ) click to toggle source

Load file directly into module/class namespace.

Please use this with careful consideration. It is best suited to loading plugin-type scripts, and should generally not be used as a substitue for Ruby's standard load system.

NOTE: This method is not a common core extension and is not loaded automatically when using `require 'facets'`.

CREDIT: Trans

@uncommon

    require 'facets/module/module_load'

    # File lib/facets/module/module_load.rb, line 18
    def module_load( path )
      if path =~ /^[\/~.]/
        file = File.expand_path(path)
      else
        $LOAD_PATH.each do |lp|
          file = File.join(lp,path)
          break if File.exist?(file)
          file = nil
        end
      end
      raise LoadError, "no such file to load -- #{path}" unless file
      module_eval(File.read(file))
    end

Also aliased as: class_load
module_method_defined?(meth)
Alias for: singleton_method_defined?
module_require( path ) click to toggle source

Require file into module/class namespace.

Unlike load this keeps a per-module cache and will not load the same file into the same module more than once despite repeated attempts.

The cache is kept in a global var called +$module_require+.

Please use this with careful consideration. It is best suited to loading plugin-type scripts, and should generally not be used as a substitue for Ruby's standard load system.

NOTE: This method is not a common core extension and is not loaded automatically when using `require 'facets'`.

CREDIT: Trans

@uncommon

    require 'facets/module/module_load'

    # File lib/facets/module/module_load.rb, line 53
    def module_require( path )
      if path =~ /^[\/~.]/
        file = File.expand_path(path)
      else
        $LOAD_PATH.each do |lp|
          file = File.join(lp,path)
          break if File.exist?(file)
          file += '.rb'
          break if File.exist?(file)
          file = nil
        end
      end
      raise LoadError, "no such file to load -- #{path}" unless file
      # per-module load cache
      $module_require ||= {}
      $module_require[self] ||= {}
      loaded = $module_require[self]
      if loaded.key?(file)
        false
      else
        loaded[file] = true
        script = File.read(file)
        module_eval(script)
        true
      end
    end

Also aliased as: class_require
pathize() click to toggle source

Converts a class name to a unix path.

    module ::ExamplePathize
      module Example
      end
    end

    ExamplePathize.pathize           #=> "example_pathize"
    ExamplePathize::Example.pathize  #=> "example_pathize/example"

    # File lib/facets/module/pathize.rb, line 15
    def pathize
      name.pathize
    end

preextend(aspect) click to toggle source

Prepend an `aspect` module to a module. This only works at the module level.

    module ::PreX
      def x; "x"; end
    end

    module ::PreU
      def x; '{' + super + '}'; end
    end

    PreX.preextend(PreU)

    PreX.x  # => "{x}"

NOTE: This is not a common core extension and is not loaded automatically when using `require 'facets'`.

CREDIT Trans

@uncommon

    require 'facets/module/preextend'

    # File lib/facets/module/preextend.rb, line 26
    def preextend(aspect)
      aspect.__send__(:include, self)
      extend aspect
    end

singleton_method_defined?(meth) click to toggle source

Query whether a normal (singleton) method is defined for the module.

CREDIT: Gavin Sinclair, Noah Gibbs

    # File lib/facets/module/instance_method_defined.rb, line 15
    def singleton_method_defined?(meth)
      singleton_methods(true).find{ |m| m.to_sym == meth.to_sym }
    end

Also aliased as: module_method_defined?, class_method_defined?

### Private Instance Methods

alias_accessor(*args) click to toggle source

As with alias_method, but alias both reader and writer.

    attr_accessor :x
    self.x = 1
    alias_accessor :y, :x
    y #=> 1
    self.y = 2
    x #=> 2

    # File lib/facets/module/alias_accessor.rb, line 14
    def alias_accessor(*args)
      orig = args.last
      args = args - [orig]
      args.each do |name|
        alias_method(name, orig)
        alias_method("#{name}=", "#{orig}=")
      end
    end

alias_module_function(new, old) click to toggle source

Alias a module function so that the alias is also a module function. The typical alias_method does not do this.

    module AliasExample
      module_function
      def hello
        "Hello"
      end
    end

    AliasExample.hello  #=> 'Hello'

    module AliasExample
      alias_module_function( :hi , :hello )
    end

    AliasExample.hi     #=> 'Hello'

    # File lib/facets/module/alias_module_function.rb, line 24
    def alias_module_function(new, old)
      alias_method(new, old)
      module_function(new)
    end

alias_reader(*args) click to toggle source

As with #alias_accessor, but just for the reader. This is basically the same as alias_method.

    # File lib/facets/module/alias_accessor.rb, line 26
    def alias_reader(*args)
      orig = args.last
      args = args - [orig]
      args.each do |name|
        alias_method(name, orig)
      end
    end

alias_writer(*args) click to toggle source

As with alias_method but does the writer instead.

    # File lib/facets/module/alias_accessor.rb, line 36
    def alias_writer(*args)
      orig = args.last
      args = args - [orig]
      args.each do |name|
        alias_method("#{name}=", "#{orig}=")
      end
    end

include_function_module(*mod) click to toggle source

Include module and apply module_fuction to the included methods.

    module Utils
      module_function
      def foo; "foo"; end
    end

    module UtilsPlus
      include_function_module Utils
    end

CREDIT: Trans

    # File lib/facets/module/include_function_module.rb, line 19
    def include_function_module *mod
      include(*mod)
      module_function(*mod.collect{|m| m.private_instance_methods & m.methods(false)}.flatten)
    end

redefine_method(sym, aka=nil, &blk) click to toggle source

Creates a new method for a pre-existing method.

If aka is given, then the method being redefined will first be aliased to this name.

    class Greeter
      def hello ; "Hello" ; end
    end

    Greeter.new.hello   #=> "Hello"

    class Greeter
      redefine_method( :hello, :hi ) do
        hi + ", friend!"
      end
    end

    Greeter.new.hello   #=> "Hello, friend!"

CREDIT: Trans

    # File lib/facets/module/redefine_method.rb, line 26
      def redefine_method(sym, aka=nil, &blk)
        alias_method(aka, sym) if aka
        ## prevent warning about method overwrite
        begin remove_method(sym) rescue NameError end
        ## define replacelemt method
        define_method(sym, &blk)
      end

      #
      alias_method :redef, :redefine_method

    end

redirect( method_hash )
Alias for: redirect_method
redirect_method( method_hash ) click to toggle source

Redirect methods to other methods. This simply defines methods by the name of a hash key which calls the method with the name of the hash's value.

    class RedirectExample
      redirect_method :hi => :hello, :hey => :hello
      def hello(name)
        "Hello, #{name}."
      end
    end

    e = RedirectExample.new
    e.hello("Bob")    #=> "Hello, Bob."
    e.hi("Bob")       #=> "Hello, Bob."
    e.hey("Bob")      #=> "Hello, Bob."

The above class definition is equivalent to …

    class RedirectExample
      def hi(*args)
        hello(*args)
      end
      def hey(*args)
        hello(*args)
      end
      def hello
        puts "Hello"
      end
    end

CREDIT: Trans

    # File lib/facets/module/redirect_method.rb, line 37
    def redirect_method( method_hash )
      method_hash.each do |targ,adv|
        define_method(targ) { |*args| send(adv,*args) }
      end
    end

Also aliased as: redirect
rename( to_sym, from_sym )
Alias for: rename_method
rename_method( to_sym, from_sym ) click to toggle source

Aliases a method and undefines the original.

    class RenameExample
      def foo; "foo"; end
      rename_method(:bar, :foo)
    end

    example = RenameExample.new
    example.bar  #=> 'foo'

    expect NoMethodError do
      example.foo
    end

CREDIT: Trans

    # File lib/facets/module/rename_method.rb, line 21
    def rename_method( to_sym, from_sym )
      raise ArgumentError, "method #{from_sym} does not exist" unless method_defined?( from_sym )
      alias_method( to_sym, from_sym )
      undef_method( from_sym )
    end

Also aliased as: rename
revisal(&blk)
Alias for: revise
revise(&blk) click to toggle source

Return a new module based on another. This includes the original module into the new revised module.

    module ReviseExample
      def foo; "foo"; end
    end

    ReviseExample2 = ReviseExample.revise do
      alias_method :bar, :foo
    end

    object = Object.new
    object.extend ReviseExample2
    object.bar  #=> 'foo'

CREDIT: Trans

    # File lib/facets/module/revise.rb, line 26
    def revise(&blk)
      base = self
      nm = Module.new{ include base }
      nm.class_eval(&blk)
      nm
    end

Also aliased as: revisal
set(option, value=self) { |self| ... } click to toggle source

Sets an option to the given value. If the value is a proc, the proc will be called every time the option is accessed.

CREDIT: Blake Mizerany (Sinatra)

    # File lib/facets/module/set.rb, line 10
    def set(option, value=self, &block)
      raise ArgumentError if block && value != self
      value = block if block
      if value.kind_of?(Proc)
        if value.arity == 1
          yield self
        else
          (class << self; self; end).module_eval do
            define_method(option, &value)
            define_method("#{option}?"){ !!__send__(option) }
            define_method("#{option}="){ |val| set(option, Proc.new{val}) }
          end
        end
      elsif value == self
        option.each{ |k,v| set(k, v) }
      elsif respond_to?("#{option}=")
        __send__("#{option}=", value)
      else
        set(option, Proc.new{value})
      end
      self
    end

spacename() click to toggle source

Returns the name of module's container module.

    module ::SpaceName
      class Example
      end
    end

    SpaceName::Example.name         #=> "SpaceName::Example"
    SpaceName::Example.spacename    #=> "SpaceName"

This used to be called `dirname`.

See also #basename.

CREDIT: Trans

    # File lib/facets/module/spacename.rb, line 19
    def spacename
      name[0...(name.rindex('::') || 0)]
      #name.gsub(/::[^:]*$/, '')
    end

to_obj() click to toggle source

Create an instance of Object and extend it with `self`.

    mod = Module.new do
      def foo; "foo"; end
    end

    obj = mod.to_obj

    obj.foo #=> "foo"

    # File lib/facets/module/to_obj.rb, line 13
    def to_obj
      o = Object.new
      o.extend self
      o
    end

wrap( sym, &blk )
Alias for: wrap_method
wrap_method( sym, &blk ) click to toggle source

Creates a new method wrapping the previous of the same name. Reference to the old method is passed into the new definition block as the first parameter.

    class WrapExample
      def foo
        "foo"
      end

      wrap_method(:foo) do |old_meth, *args|
        old_meth.call + '!'
      end
    end

    example = WrapExample.new
    example.foo #=> 'foo!'

Keep in mind that this cannot be used to wrap methods that take a block.

CREDIT: Trans

    # File lib/facets/module/wrap_method.rb, line 27
    def wrap_method( sym, &blk )
      old = instance_method(sym)
      define_method(sym) { |*args| blk.call(old.bind(self), *args) }
    end

Also aliased as: wrap