Class: Module

Inherits:
Object show all
Defined in:
lib/core/facets/module/is.rb,
lib/core/facets/module/op.rb,
lib/core/facets/module/let.rb,
lib/core/facets/module/set.rb,
lib/core/facets/module/can.rb,
lib/core/facets/module/home.rb,
lib/core/facets/module/class.rb,
lib/core/facets/module/nodef.rb,
lib/core/facets/module/mattr.rb,
lib/core/facets/module/revise.rb,
lib/core/facets/module/to_obj.rb,
lib/core/facets/module/pathize.rb,
lib/core/facets/module/memoize.rb,
lib/core/facets/module/abstract.rb,
lib/core/facets/module/lastname.rb,
lib/core/facets/module/ancestor.rb,
lib/core/facets/module/integrate.rb,
lib/core/facets/module/spacename.rb,
lib/core/facets/module/anonymous.rb,
lib/core/facets/module/methodize.rb,
lib/core/facets/module/enclosure.rb,
lib/core/facets/module/preextend.rb,
lib/core/facets/module/module_def.rb,
lib/core/facets/module/module_load.rb,
lib/core/facets/module/attr_setter.rb,
lib/core/facets/module/attr_tester.rb,
lib/core/facets/module/wrap_method.rb,
lib/core/facets/module/method_space.rb,
lib/core/facets/module/class_extend.rb,
lib/core/facets/module/method_clash.rb,
lib/core/facets/module/rename_method.rb,
lib/core/facets/module/copy_inheritor.rb,
lib/core/facets/module/attr_validator.rb,
lib/core/facets/module/class_accessor.rb,
lib/core/facets/module/alias_accessor.rb,
lib/core/facets/module/class_inheritor.rb,
lib/core/facets/module/redefine_method.rb,
lib/core/facets/module/instance_method.rb,
lib/core/facets/module/redirect_method.rb,
lib/core/facets/module/instance_function.rb,
lib/core/facets/module/alias_method_chain.rb,
lib/core/facets/module/alias_class_method.rb,
lib/core/facets/module/attr_class_accessor.rb,
lib/core/facets/module/all_instance_methods.rb,
lib/core/facets/module/alias_module_function.rb,
lib/core/facets/module/include_function_module.rb,
lib/core/facets/module/instance_method_defined.rb,
lib/standard/facets/equitable.rb

Defined Under Namespace

Modules: InstanceFunction

Instance Method Summary collapse

Instance Method Details

#*(rename_map) ⇒ Object

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


95
96
97
98
99
100
101
102
103
104
# File 'lib/core/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) ⇒ Object

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


35
36
37
38
39
40
41
# File 'lib/core/facets/module/op.rb', line 35

def +(other)
  base = self
  Module.new do
    include base
    include other
  end
end

#-(other) ⇒ Object

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


64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
# File 'lib/core/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) ⇒ Object

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


18
19
20
21
22
# File 'lib/core/facets/module/abstract.rb', line 18

def abstract(*sym)
  sym.each do |s|
    define_method(s){ raise TypeError, "undefined abstraction ##{s}" }
  end
end

#alias_accessor(*args) ⇒ Object (private)

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

14
15
16
17
18
19
20
21
# File 'lib/core/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_class_method(name, target) ⇒ Object

Alias a class method.


5
6
7
8
9
# File 'lib/core/facets/module/alias_class_method.rb', line 5

def alias_class_method(name, target)
  class << self
    alias_method(name, target)
  end
end

#alias_method_chain(target, feature) {|aliased_target, punctuation| ... } ⇒ Object

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

Yields:

  • (aliased_target, punctuation)

45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
# File 'lib/core/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_module_function(new, old) ⇒ Object (private)

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'

24
25
26
27
# File 'lib/core/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) ⇒ Object (private)

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


26
27
28
29
30
31
32
# File 'lib/core/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_tester(*args) ⇒ Object

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'


48
49
50
51
52
53
54
# File 'lib/core/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) ⇒ Object

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'


36
37
38
39
40
41
42
43
# File 'lib/core/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

#alias_writer(*args) ⇒ Object (private)

As with alias_method but does the writer instead.


36
37
38
39
40
41
42
# File 'lib/core/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

#all_instance_methods(include_super = true) ⇒ Object

List all instance methods, equivalent to

public_instance_methods +
protected_instance_methods +
private_instance_methods

TODO: Better name for #all_instance_methods?

CREDIT: Trans


13
14
15
16
17
# File 'lib/core/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) ⇒ Boolean

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

class X ; end
class Y < X ; end

 X.ancestor?(Y)

11
12
13
# File 'lib/core/facets/module/ancestor.rb', line 11

def ancestor?( mod )
  ancestors.include?(mod)
end

#anonymous?Boolean

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”


18
19
20
21
22
# File 'lib/core/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

#attrObject (protected)

#attr_accessorObject (protected)

#attr_class_accessor(name) ⇒ Object

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'


10
11
12
13
# File 'lib/core/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) ⇒ Object

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'


22
23
24
25
26
27
28
29
30
31
# File 'lib/core/facets/module/attr_class_accessor.rb', line 22

def attr_class_reader(name)
  module_eval("def self.\#{name}\[email protected]\#{name}\nend\ndef \#{name}\nself.class.\#{name}\nend\n", __FILE__, __LINE__)
end

#attr_class_writer(name) ⇒ Object

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'


40
41
42
43
44
45
46
47
48
49
# File 'lib/core/facets/module/attr_class_accessor.rb', line 40

def attr_class_writer(name)
  module_eval("def self.\#{name}=(x)\[email protected]\#{name} = x\nend\ndef \#{name}=(x)\nself.class.\#{name} = x\nend\n", __FILE__, __LINE__)
end

#attr_readerObject (protected)

#attr_setter(*args) ⇒ Object

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


21
22
23
24
25
26
27
28
29
30
31
32
33
# File 'lib/core/facets/module/attr_setter.rb', line 21

def attr_setter(*args)
  code, made = '', []
  args.each do |a|
    code << %{
      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) ⇒ Object

TODO:

This method will probably be deprecated.

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

Uncommon:

  • require 'facets/module/attr_tester'


24
25
26
27
28
29
30
31
32
33
34
35
36
# File 'lib/core/facets/module/attr_tester.rb', line 24

def attr_tester(*args)
  code, made = '', []
  args.each do |a|
    code << %{
      def #{a}?(truth=nil)
        @#{a} ? truth || @#{a} : @#{a}
      end
    }
    made << "#{a}?".to_sym
  end
  module_eval code
  made
end

#attr_validator(*symbols, &validator) ⇒ Object

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'


14
15
16
17
18
19
20
21
22
23
24
25
26
# File 'lib/core/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

#attr_writerObject (protected)

#cattr(*syms) ⇒ Object

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'


22
23
24
25
26
27
28
29
30
31
# File 'lib/core/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) ⇒ Object

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'


133
134
135
# File 'lib/core/facets/module/mattr.rb', line 133

def cattr_accessor(*syms)
  cattr_reader(*syms) + cattr_writer(*syms)
end

#cattr_reader(*syms) ⇒ Object

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'


52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
# File 'lib/core/facets/module/mattr.rb', line 52

def cattr_reader(*syms)
  syms.flatten.each do |sym|
    module_eval("unless defined? @@\#{sym}\[email protected]@\#{sym} = nil\nend\n\ndef self.\#{sym}\[email protected]@\#{sym}\nend\n\ndef \#{sym}\[email protected]@\#{sym}\nend\n", __FILE__, __LINE__)
  end
  return syms
end

#cattr_writer(*syms) ⇒ Object

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'


94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
# File 'lib/core/facets/module/mattr.rb', line 94

def cattr_writer(*syms)
  syms.flatten.each do |sym|
    module_eval("unless defined? @@\#{sym}\[email protected]@\#{sym} = nil\nend\n\ndef self.\#{sym}=(obj)\[email protected]@\#{sym} = obj\nend\n\ndef \#{sym}=(obj)\[email protected]@\#{sym}=(obj)\nend\n", __FILE__, __LINE__)
  end
  return syms
end

#class_accessor(name) ⇒ Object

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

Uncommon:

  • require 'facets/module/class_accessor'


10
11
12
13
# File 'lib/core/facets/module/class_accessor.rb', line 10

def class_accessor(name)
  class_reader(name)
  class_writer(name)
end

#class_def(name, &blk) ⇒ Object

Defines an instance method within a class/module.

CREDIT: WhyTheLuckyStiff


7
8
9
# File 'lib/core/facets/module/module_def.rb', line 7

def class_def name, &blk
  class_eval { define_method name, &blk }
end

#class_extend(*mods, &block) ⇒ Object

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'


42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
# File 'lib/core/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_extensionsObject


68
69
70
# File 'lib/core/facets/module/class_extend.rb', line 68

def class_extensions
  @class_extensions ||= []
end

#class_inheritor(key, obj, op = nil, &fop) ⇒ Object

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

Raises:

  • (ArgumentError)

Uncommon:

  • require 'facets/module/class_inheritor'


48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
# File 'lib/core/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_reader(name) ⇒ Object

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

Uncommon:

  • require 'facets/module/class_reader'


22
23
24
25
26
27
28
# File 'lib/core/facets/module/class_accessor.rb', line 22

def class_reader(name)
  module_eval("def self.\#{name}\[email protected]\#{name}\nend\n", __FILE__, __LINE__)
end

#class_writer(name) ⇒ Object

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

Uncommon:

  • require 'facets/module/class_writer'


37
38
39
40
41
42
43
# File 'lib/core/facets/module/class_accessor.rb', line 37

def class_writer(name)
  module_eval("def self.\#{name}=(x)\[email protected]\#{name} = x\nend\n", __FILE__, __LINE__)
end

#copy_inheritor(name, default = {}) ⇒ Object

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'


26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
# File 'lib/core/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

#enclosureObject

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'


25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
# File 'lib/core/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

#enclosuresObject

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'


63
64
65
66
67
68
69
70
71
# File 'lib/core/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

#encnameObject

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'


90
91
92
# File 'lib/core/facets/module/enclosure.rb', line 90

def encname
  /::[^:]+\Z/ =~ self.name ? $` : nil
end

#Equitable(*accessors) ⇒ Object

This function provided a “shortcut” for creating the #identity method based on given accessors and returns the Equitable module for inclusion.

include Equitable(:a, :b)

is equivalent to including a module containing:

def ==(other)
  self.a == other.a && self.b == other.b
end

def eql?(other)
  self.a.eql?(other.a) && self.b.eql?(other.b)
end

def hash()
  self.a.hash ^ self.b.hash
end

71
72
73
# File 'lib/standard/facets/equitable.rb', line 71

def Equitable(*accessors)
  Equitable.identify(self, *accessors)
end

#homeObject

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.


29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
# File 'lib/core/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

#homenameObject Also known as: modname

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 Module#basename.


57
58
59
# File 'lib/core/facets/module/home.rb', line 57

def homename
  /::[^:]+\Z/ =~ name ? $` : nil
end

#housingObject

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.


80
81
82
83
84
85
86
87
88
# File 'lib/core/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) ⇒ Object

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'


103
104
105
# File 'lib/core/facets/module/method_space.rb', line 103

def include_as(h)
  h.each{ |name, mod| method_space(name, mod) }
end

#include_function_module(*mod) ⇒ Object (private)

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


19
20
21
22
# File 'lib/core/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

#instance_function(*meths) ⇒ Object

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'


34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
# File 'lib/core/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) ⇒ Object

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.


18
19
20
21
22
# File 'lib/core/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) ⇒ Boolean

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

CREDIT: Gavin Sinclair, Noah Gibbs


7
8
9
# File 'lib/core/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) ⇒ Object

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


41
42
43
44
45
46
# File 'lib/core/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) ⇒ Object

An alias for #include.

class IsExample
  is Enumerable
end

CREDIT: Trans


25
26
27
28
29
30
31
32
33
34
35
36
37
# File 'lib/core/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) ⇒ Boolean

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


13
14
15
# File 'lib/core/facets/module/is.rb', line 13

def is?(base)
  Module===base && ancestors.slice(1..-1).include?(base)
end

#lastnameObject Also known as: basename

Returns the root name of the module/class.

module ::BaseName
  class Example
  end
end

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

Returns nil when module is anonymous.

CREDIT: Trans


17
18
19
20
21
22
23
# File 'lib/core/facets/module/lastname.rb', line 17

def lastname
  if name and not name.empty?
    name.gsub(/^.*::/, '')
  else
    nil #inspect.gsub('#<','').gsub('>','').sub(':', '_')
  end
end

#let(var, &block) ⇒ Object

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'


17
18
19
20
21
22
23
24
25
26
27
28
29
# File 'lib/core/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) ⇒ Object

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/mattr'


162
163
164
165
166
167
168
169
170
171
# File 'lib/core/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) ⇒ Object

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/mattr'


275
276
277
# File 'lib/core/facets/module/mattr.rb', line 275

def mattr_accessor(*syms)
  mattr_reader(*syms) + mattr_writer(*syms)
end

#mattr_reader(*syms) ⇒ Object

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/mattr'


192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
# File 'lib/core/facets/module/mattr.rb', line 192

def mattr_reader( *syms )
  syms.flatten.each do |sym|
    module_eval("unless defined? @@\#{sym}\[email protected]@\#{sym} = nil\nend\n\ndef self.\#{sym}\[email protected]@\#{sym}\nend\n\ndef \#{sym}\[email protected]@\#{sym}\nend\n", __FILE__, __LINE__)
  end
  return syms
end

#mattr_writer(*syms) ⇒ Object

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/mattr'


235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
# File 'lib/core/facets/module/mattr.rb', line 235

def mattr_writer(*syms)
  syms.flatten.each do |sym|
    module_eval("unless defined? @@\#{sym}\[email protected]@\#{sym} = nil\nend\n\ndef self.\#{sym}=(obj)\[email protected]@\#{sym} = obj\nend\n\ndef \#{sym}=(obj)\[email protected]@\#{sym}=(obj)\nend\n", __FILE__, __LINE__)
  end
  return syms
end

#memoize(*args) ⇒ Object

This is here for backward compatibility.

Uncommon:

  • require 'facets/module/memoize'


10
11
12
13
14
# File 'lib/core/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) ⇒ Object

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'


30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
# File 'lib/core/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) ⇒ Boolean

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

Uncommon:

  • require 'facets/module/method_clash'


60
61
62
63
# File 'lib/core/facets/module/method_clash.rb', line 60

def method_clash?(other) 
  c = method_clash(other) 
  !c.empty?
end

#method_space(name, mod = nil, &blk) ⇒ Object

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'


32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
# File 'lib/core/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 %{
      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

#methodizeObject

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"

15
16
17
# File 'lib/core/facets/module/methodize.rb', line 15

def methodize
  name.methodize
end

#module_def(name, &blk) ⇒ Object

Defines an instance method within a class/module.

CREDIT: WhyTheLuckyStiff


15
16
17
# File 'lib/core/facets/module/module_def.rb', line 15

def module_def name, &blk
  module_eval { define_method name, &blk }
end

#module_load(path) ⇒ Object Also known as: class_load

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

Raises:

  • (LoadError)

Uncommon:

  • require 'facets/module/module_load'


18
19
20
21
22
23
24
25
26
27
28
29
30
# File 'lib/core/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

#module_require(path) ⇒ Object Also known as: class_require

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

Raises:

  • (LoadError)

Uncommon:

  • require 'facets/module/module_load'


53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
# File 'lib/core/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

#pathizeObject

Converts a class name to a unix path.

module ::ExamplePathize
  module Example
  end
end

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

15
16
17
# File 'lib/core/facets/module/pathize.rb', line 15

def pathize
  name.pathize
end

#preextend(aspect) ⇒ Object

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'


26
27
28
29
# File 'lib/core/facets/module/preextend.rb', line 26

def preextend(aspect)
  aspect.__send__(:include, self)
  extend aspect
end

#redefine_method(sym, aka = nil, &blk) ⇒ Object (private) Also known as: redef

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


26
27
28
29
30
31
32
# File 'lib/core/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

#redirect_method(method_hash) ⇒ Object (private) Also known as: redirect

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


37
38
39
40
41
# File 'lib/core/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

#remove_methodObject (protected) Also known as: remove

#rename_method(to_sym, from_sym) ⇒ Object (private) Also known as: rename

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

Raises:

  • (ArgumentError)

21
22
23
24
25
# File 'lib/core/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

#revise(&blk) ⇒ Object Also known as: revisal

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


26
27
28
29
30
31
# File 'lib/core/facets/module/revise.rb', line 26

def revise(&blk)
  base = self
  nm = Module.new{ include base }
  nm.class_eval(&blk)
  nm
end

#set(option, value = self, &block) ⇒ Object

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)

Raises:

  • (ArgumentError)

10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
# File 'lib/core/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

#singleton_method_defined?(meth) ⇒ Boolean Also known as: module_method_defined?, class_method_defined?

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

CREDIT: Gavin Sinclair, Noah Gibbs


15
16
17
# File 'lib/core/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

#spacenameObject

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 Module#basename.

CREDIT: Trans


19
20
21
22
# File 'lib/core/facets/module/spacename.rb', line 19

def spacename
  name[0...(name.rindex('::') || 0)]
  #name.gsub(/::[^:]*$/, '')
end

#to_objObject

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"

13
14
15
16
17
# File 'lib/core/facets/module/to_obj.rb', line 13

def to_obj
  o = Object.new
  o.extend self
  o
end

#undef_methodObject (protected) Also known as: nodef

#wrap_method(sym, &blk) ⇒ Object Also known as: wrap

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


27
28
29
30
# File 'lib/core/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