Class: Module

Inherits:
Object show all
Defined in:
lib/gems/facets-2.4.5/lib/more/facets/capsule.rb,
lib/mack-facets/extensions/module.rb,
lib/gems/extlib-0.9.8/lib/extlib/module.rb,
lib/gems/facets-2.4.5/lib/more/facets/attr.rb,
lib/gems/facets-2.4.5/lib/core/facets/metaid.rb,
lib/gems/facets-2.4.5/lib/more/facets/memoize.rb,
lib/gems/facets-2.4.5/lib/more/facets/paramix.rb,
lib/gems/facets-2.4.5/lib/more/facets/overload.rb,
lib/gems/facets-2.4.5/lib/more/facets/settings.rb,
lib/gems/facets-2.4.5/lib/core/facets/module/is.rb,
lib/gems/facets-2.4.5/lib/core/facets/module/op.rb,
lib/gems/facets-2.4.5/lib/more/facets/equatable.rb,
lib/gems/facets-2.4.5/lib/core/facets/module/can.rb,
lib/gems/facets-2.4.5/lib/more/facets/dependency.rb,
lib/gems/facets-2.4.5/lib/more/facets/annotations.rb,
lib/gems/facets-2.4.5/lib/more/facets/annotations.rb,
lib/gems/facets-2.4.5/lib/more/facets/methodspace.rb,
lib/gems/facets-2.4.5/lib/core/facets/module/class.rb,
lib/gems/facets-2.4.5/lib/more/facets/classmethods.rb,
lib/gems/facets-2.4.5/lib/core/facets/module/revise.rb,
lib/gems/facets-2.4.5/lib/core/facets/module/nesting.rb,
lib/gems/facets-2.4.5/lib/core/facets/module/pathize.rb,
lib/gems/facets-2.4.5/lib/core/facets/module/prepend.rb,
lib/gems/facets-2.4.5/lib/more/facets/1stclassmethod.rb,
lib/gems/facets-2.4.5/lib/core/facets/module/abstract.rb,
lib/gems/facets-2.4.5/lib/core/facets/module/ancestor.rb,
lib/gems/facets-2.4.5/lib/core/facets/module/basename.rb,
lib/gems/facets-2.4.5/lib/core/facets/module/conflict.rb,
lib/gems/facets-2.4.5/lib/core/facets/module/modspace.rb,
lib/gems/facets-2.4.5/lib/more/facets/class_extension.rb,
lib/gems/facets-2.4.5/lib/core/facets/module/methodize.rb,
lib/gems/facets-2.4.5/lib/core/facets/module/spacename.rb,
lib/gems/facets-2.4.5/lib/core/facets/module/module_load.rb,
lib/gems/facets-2.4.5/lib/core/facets/module/wrap_method.rb,
lib/gems/facets-2.4.5/lib/core/facets/module/rename_method.rb,
lib/gems/facets-2.4.5/lib/core/facets/comparable/comparable.rb,
lib/gems/facets-2.4.5/lib/core/facets/module/alias_accessor.rb,
lib/gems/facets-2.4.5/lib/core/facets/module/redefine_method.rb,
lib/gems/facets-2.4.5/lib/core/facets/module/redirect_method.rb,
lib/gems/facets-2.4.5/lib/core/facets/module/instance_methods.rb,
lib/gems/facets-2.4.5/lib/core/facets/module/alias_method_chain.rb,
lib/gems/facets-2.4.5/lib/core/facets/module/alias_module_function.rb,
lib/gems/facets-2.4.5/lib/core/facets/module/include_function_module.rb

Overview

It would nice if we could the following. Then the middle portion of the #Comparable method would not be needed. But I fear it might break others code.

 module Comparable

  def <=>(other)
    comparability.each do |field|
      cmp = send(field) <=> other.send(field); return cmp unless cmp == 0
    end
  end

end

Direct Known Subclasses

Capsule, Paramix::Delegator

Instance Method Summary collapse

Instance Method Details

#*(rename_map) ⇒ Object

Rename methods.

module A
  def a; "a"; end
end

B = A * { :a => :b }

class X; include B; end

X.new.b    #=> "a"

CREDIT: Thomas Sawyer
CREDIT: Robert Dober


83
84
85
86
87
88
89
90
91
92
# File 'lib/gems/facets-2.4.5/lib/core/facets/module/op.rb', line 83

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 A
  def a; "a"; end
end

module B
  def b; "b"; end
end

C = A + B

class X; include C; end

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

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

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
CREDIT: Robert Dober


36
37
38
39
40
41
42
# File 'lib/gems/facets-2.4.5/lib/core/facets/module/op.rb', line 36

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

#-(other) ⇒ Object

Subtract modules.

TODO: Should this use all instance_methods, not just public?

CREDIT: Thomas Sawyer
CREDIT: Robert Dober


51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
# File 'lib/gems/facets-2.4.5/lib/core/facets/module/op.rb', line 51

def -(other)
  case other
  when Array
    subtract = instance_methods(true) & other.collect{|m| m.to_s}
  when Module
    subtract = instance_methods(true) & other.instance_methods(true)  # false?
  when String, Symbol
    subtract = instance_methods(true) & [other.to_s]
  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 C
   abstract :a
 end

 c = C.new
 c.a  #=> Error: undefined abstraction #a

CREDIT: Trans


15
16
17
18
19
# File 'lib/gems/facets-2.4.5/lib/core/facets/module/abstract.rb', line 15

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

#alias_accessor!(*args) ⇒ Object Also known as: alias_switcher, alias_toggler

Create aliases for flag accessors.

CREDIT: Trans


117
118
119
120
121
122
123
124
# File 'lib/gems/facets-2.4.5/lib/more/facets/attr.rb', line 117

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_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

And both aliases are set up for you.

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
CREDIT: Rails Team

Yields:

  • (aliased_target, punctuation)


28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
# File 'lib/gems/facets-2.4.5/lib/core/facets/module/alias_method_chain.rb', line 28

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_reader!(*args) ⇒ Object Also known as: alias_reader?, alias_tester

Create aliases for flag reader.

CREDIT: Trans


159
160
161
162
163
164
165
# File 'lib/gems/facets-2.4.5/lib/more/facets/attr.rb', line 159

def alias_reader!(*args)
  orig = args.last
  args = args - [orig]
  args.each do |name|
    alias_method("#{name}?", "#{orig}?")
  end
end

#alias_setter(*args) ⇒ Object

Alias an accessor. This create an alias for both a reader and a writer.

 class X
   attr_accessor :a
   alias_accessor :b, :a
 end

 x = X.new
 x.b = 1
 x.a        #=> 1

CREDIT: Trans


81
82
83
84
85
86
# File 'lib/gems/facets-2.4.5/lib/more/facets/attr.rb', line 81

def alias_setter(*args)
  args = args - [orig]
  args.each do |name|
    alias_method(name, orig)
  end
end

#alias_validator(*args) ⇒ Object

Create aliases for validators.



24
25
26
27
28
29
30
31
# File 'lib/gems/facets-2.4.5/lib/more/facets/attr.rb', line 24

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

Create aliases for flag writer.

CREDIT: Trans


200
201
202
203
204
205
206
# File 'lib/gems/facets-2.4.5/lib/more/facets/attr.rb', line 200

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/gems/facets-2.4.5/lib/core/facets/module/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)

Returns:

  • (Boolean)


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

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

#ann(ref, keys_or_class = nil, keys = nil) ⇒ Object

Set or read annotations.



123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
# File 'lib/gems/facets-2.4.5/lib/more/facets/annotations.rb', line 123

def ann( ref, keys_or_class=nil, keys=nil )
  return heritage(ref) unless keys_or_class or keys

  if Class === keys_or_class
    keys ||= {}
    keys[:class] = keys_or_class
  else
    keys = keys_or_class
  end

  if Hash === keys
    ref = ref.to_sym
    annotations[ref] ||= {}
    annotations[ref].update(keys.rekey)
  else
    key = keys.to_sym
    heritage(ref)[key]
  end
end

#ann!(ref, keys_or_class = nil, keys = nil) ⇒ Object

To change an annotation’s value in place for a given class or module it first must be duplicated, otherwise the change may effect annotations in the class or module’s ancestors.



147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
# File 'lib/gems/facets-2.4.5/lib/more/facets/annotations.rb', line 147

def ann!( ref, keys_or_class=nil, keys=nil )
  #return heritage(ref) unless keys_or_class or keys
  return annotations[ref] unless keys_or_class or keys

  if Class === keys_or_class
    keys ||= {}
    keys[:class] = keys_or_class
  else
    keys = keys_or_class
  end

  if Hash === keys
    ref = ref.to_sym
    annotations[ref] ||= {}
    annotations[ref].update(keys.rekey)
  else
    key = keys.to_sym
    annotations[ref][key] = heritage(ref)[key].dup
  end
end

#annotationsObject



108
109
110
111
# File 'lib/gems/facets-2.4.5/lib/more/facets/annotations.rb', line 108

def annotations
  #$annotations[self]
  @annotations ||= {}
end

#append_features(mod) ⇒ Object



163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
# File 'lib/gems/facets-2.4.5/lib/more/facets/classmethods.rb', line 163

def append_features( base )
  result = append_features_without_classmethods( base )
  if const_defined?( :ClassMethods )
    base.extend( self::ClassMethods )
    unless base.is_a?( Class )
      unless base.const_defined?( :ClassMethods )
        base.const_set( :ClassMethods, Module.new )
      end
      my = self
      base::ClassMethods.class_eval do
        include my::ClassMethods
      end
    end
  end
  result
end

#append_features_without_class_extensionObject



54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
# File 'lib/gems/facets-2.4.5/lib/more/facets/class_extension.rb', line 54

def append_features( base )
  result = append_features_without_classmethods( base )
  if const_defined?( :ClassMethods )
    base.extend( self::ClassMethods )
    unless base.is_a?( Class )
      unless base.const_defined?( :ClassMethods )
        base.const_set( :ClassMethods, Module.new )
      end
      my = self
      base::ClassMethods.class_eval do
        include my::ClassMethods
      end
    end
  end
  result
end

#append_features_without_classmethodsObject



161
# File 'lib/gems/facets-2.4.5/lib/more/facets/classmethods.rb', line 161

alias_method :append_features_without_classmethods, :append_features

#attr(*args) ⇒ Object



222
223
224
225
226
227
228
229
230
231
232
233
234
# File 'lib/gems/facets-2.4.5/lib/more/facets/annotations.rb', line 222

def attr( *args )
  args.flatten!
  case args.last
  when TrueClass
    args.pop
    attr_accessor( *args )
  when FalseClass
    args.pop
    attr_reader( *args )
  else
    attr_reader( *args )
  end
end

#attr_accessor!(*args) ⇒ Object Also known as: attr_switcher, attr_toggler

Create a toggle attribute. This creates two methods for each given name. One is a form of tester and the other is used to toggle the value.

attr_accessor! :a

is equivalent to

 def a?
   @a
 end

 def a!(value=true)
   @a = value
   self
 end

CREDIT: Trans


107
108
109
# File 'lib/gems/facets-2.4.5/lib/more/facets/attr.rb', line 107

def attr_accessor!(*args)
  attr_reader!(*args) + attr_writer!(*args)
end

#attr_reader!(*args) ⇒ Object Also known as: attr_reader?, attr_tester

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

attr_reader! :a

is equivalent to

def a?
  @a ? true : @a
end


139
140
141
142
143
144
145
146
147
148
149
150
151
# File 'lib/gems/facets-2.4.5/lib/more/facets/attr.rb', line 139

def attr_reader!(*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_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


53
54
55
56
57
58
59
60
61
62
63
64
65
# File 'lib/gems/facets-2.4.5/lib/more/facets/attr.rb', line 53

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_validator(*symbols, &validator) ⇒ Object

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

CREDIT: ?


8
9
10
11
12
13
14
15
16
17
18
19
20
# File 'lib/gems/facets-2.4.5/lib/more/facets/attr.rb', line 8

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_writer!(*args) ⇒ Object

Create a flaggable attribute. This creates a single methods used to set an attribute to “true”.

attr_writer! :a

is equivalent to

def a!(value=true)
  @a = value
  self
end


181
182
183
184
185
186
187
188
189
190
191
192
193
194
# File 'lib/gems/facets-2.4.5/lib/more/facets/attr.rb', line 181

def attr_writer!(*args)
  code, made = '', []
  args.each do |a|
    code << %{
      def #{a}!(value=true)
        @#{a} = value
        self
      end
    }
    made << "#{a}!".to_sym
  end
  module_eval code
  made
end

#basenameObject

Returns the root name of the module/class.

module Example
  class Demo
  end
end

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

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


22
23
24
25
26
27
28
# File 'lib/gems/facets-2.4.5/lib/core/facets/module/basename.rb', line 22

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

#class_def(name, &blk) ⇒ Object

Defines an instance method within a class.

CREDIT: WhyTheLuckyStiff


82
83
84
# File 'lib/gems/facets-2.4.5/lib/core/facets/metaid.rb', line 82

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

#class_methods(&yld) ⇒ Object Also known as: class_inherit



180
181
182
183
184
185
186
187
188
# File 'lib/gems/facets-2.4.5/lib/more/facets/classmethods.rb', line 180

def class_methods( &yld )
  if const_defined?( :ClassMethods )
    self::ClassMethods.class_eval( &yld )
  else
    self.const_set( :ClassMethods, Module.new( &yld ) )
  end
  extend( self::ClassMethods )
  self::ClassMethods
end

#classified_attributesObject

Return list of attributes that have a :class annotation.

class MyClass
  attr_accessor :test
  attr_accessor :name, String, :doc => 'Hello'
  attr_accessor :age, Fixnum
end

MyClass.instance_attributes # => [:test, :name, :age, :body]
MyClass.classified_attributes # => [:name, :age]


295
296
297
298
299
# File 'lib/gems/facets-2.4.5/lib/more/facets/annotations.rb', line 295

def classified_attributes
  instance_attributes.find_all do |a|
    self.ann(a, :class)
  end
end

#Comparable(*accessors) ⇒ Object

Automatically generate sorting defintions base on attribute fields.

include SortOn(:a, :b)

is equivalent to including a module containing:

def <=>(other)
  cmp = self.a <=> other.a; return cmp unless cmp == 0
  cmp = self.b <=> other.b; return cmp unless cmp == 0
  0
end


28
29
30
31
32
33
34
35
36
37
38
39
# File 'lib/gems/facets-2.4.5/lib/core/facets/comparable/comparable.rb', line 28

def Comparable(*accessors)
  define_method(:comparability){ accessors }
  code = %{
    def <=>(other)
      comparability.each do |a|
        cmp = (send(a) <=> other.send(a)); return cmp unless cmp == 0
      end
    end
  }
  module_eval code
  return Comparable
end

#conflict?(other) ⇒ Boolean

Detect conflicts.

 module A
   def c; end
 end

 module B
   def c; end
 end

 A.conflict?(B)  #=> ["c"]

 TODO: All instance methods, or just public?

CREDIT: Thomas Sawyer
CREDIT: Robert Dober

Returns:

  • (Boolean)


21
22
23
24
25
26
27
28
29
30
31
# File 'lib/gems/facets-2.4.5/lib/core/facets/module/conflict.rb', line 21

def conflict?(other)
  common_ancestor = (ancestors & other.ancestors).first
  c = []
  c += (public_instance_methods(true) & other.public_instance_methods(true))
  c += (private_instance_methods(true) & other.private_instance_methods(true))
  c += (protected_instance_methods(true) & other.protected_instance_methods(true))
  c -= common_ancestor.public_instance_methods(true)
  c -= common_ancestor.private_instance_methods(true)
  c -= common_ancestor.protected_instance_methods(true)
  c.empty? ? false : c
end

#convert_security_of_methods(old_level = :public, new_level = :protected) ⇒ Object

Bulk converts the security level of methods in this Module from one level to another.



4
5
6
7
# File 'lib/mack-facets/extensions/module.rb', line 4

def convert_security_of_methods(old_level = :public, new_level = :protected)
  eval("#{old_level}_instance_methods").each{ |meth| self.send(new_level, meth) }
  self
end

#define_dependency(name, *deps) ⇒ Object



120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
# File 'lib/gems/facets-2.4.5/lib/more/facets/dependency.rb', line 120

def define_dependency( name, *deps )
  @dependency ||= {}
  if @dependency[name.to_sym]
    @dependency[name.to_sym] = deps
  else
    @dependency[name.to_sym] = deps
    deplist = lambda{ dependencies(name) }
    alias_method("#{name}:execute",name)
    define_method(name) do |*a|
      # run dependencies
      deplist.call.each do |d|
        if respond_to?("#{d}:execute")
          send("#{d}:execute",*a) #,&b)
        else
          send(d,*a) #,&b)
        end
      end
      # run core method
      send("#{name}:execute",*a) #,&b)
    end
  end
end

#depend(name_and_deps = nil) ⇒ Object



90
91
92
93
94
95
96
97
98
99
100
101
102
# File 'lib/gems/facets-2.4.5/lib/more/facets/dependency.rb', line 90

def depend( name_and_deps=nil )
  if Hash === name_and_deps
    name_and_deps.to_h.each do |name, deps|
      deps = [deps].flatten
      define_dependency(name, *deps)
    end
  elsif name_and_deps
    @dependency ||= {}
    @dependency[name_and_deps.to_sym]
  else
    @dependency ||= {}
  end
end

#dependencies(name, build = []) ⇒ Object

Compile list of all unique prerequisite calls.



106
107
108
109
110
111
112
113
114
115
116
# File 'lib/gems/facets-2.4.5/lib/more/facets/dependency.rb', line 106

def dependencies(name, build=[])
  @dependency ||= {}
  deps = @dependency[name.to_sym]
  return build unless deps
  deps.each do |dep|
    build.unshift(dep)
    dependencies(dep,build)
  end
  build.uniq!
  build
end

#Equatable(*accessors) ⇒ Object

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

include Equatable(: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


115
116
117
# File 'lib/gems/facets-2.4.5/lib/more/facets/equatable.rb', line 115

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

#find_const(const_name) ⇒ Object



2
3
4
5
6
7
8
# File 'lib/gems/extlib-0.9.8/lib/extlib/module.rb', line 2

def find_const(const_name)
  if const_name[0..1] == '::'
    Object.find_const(const_name[2..-1])
  else
    nested_const_lookup(const_name)
  end
end

#heritage(ref) ⇒ Object



113
114
115
116
117
118
119
# File 'lib/gems/facets-2.4.5/lib/more/facets/annotations.rb', line 113

def heritage(ref)
  ref = ref.to_sym
  ancestors.inject({}) { |memo, ancestor|
    ancestor.annotations[ref] ||= {}
    ancestor.annotations[ref] + memo
  }
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"


103
104
105
# File 'lib/gems/facets-2.4.5/lib/more/facets/methodspace.rb', line 103

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

#include_safely_into(*args) ⇒ Object

Includes this module into a Class, and changes all public methods to protected.

Examples:

module MyCoolUtils
  def some_meth
    "hi"
  end
  self.include_safely_into(FooController)
end

or:

MyCoolUtils.include_safely_into(FooController, SomeOtherClass)


20
21
22
23
24
25
26
27
# File 'lib/mack-facets/extensions/module.rb', line 20

def include_safely_into(*args)
  [args].flatten.each do |a|
    if a.is_a?(String) || a.is_a?(Symbol)
      a = a.to_s.constantize
    end
    a.send(:include, self.convert_security_of_methods)
  end
end

#instance_method!(s) ⇒ Object

Easy access to method as objects, and they retain state!

module K
  def hello
    puts "Hello World!"
  end
end
p K.instance_method!(:hello)   #=> <UnboundMethod: #hello>

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



134
135
136
137
# File 'lib/gems/facets-2.4.5/lib/more/facets/1stclassmethod.rb', line 134

def instance_method!(s)
  #( @@__instance_methods__ ||= {} )[s] ||= instance_method(s)  # TODO when fixed
  ( @__instance_methods__ ||= {} )[s] ||= instance_method(s)
end

#instance_method_defined?(meth) ⇒ Boolean

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

CREDIT: Gavin Sinclair
CREDIT: Noah Gibbs

Returns:

  • (Boolean)


24
25
26
# File 'lib/gems/facets-2.4.5/lib/core/facets/module/instance_methods.rb', line 24

def instance_method_defined?(meth)
  instance_methods(true).find{ |m| m == meth.to_s }
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 W
  def q ; "q" ; end
  def y ; "y" ; end
end

class X
  integrate W do
    nodef :y
  end
end

x = X.new
x.q  #=> "q"
x.y  #=> missing method error

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

CREDIT: Trans


51
52
53
54
55
56
# File 'lib/gems/facets-2.4.5/lib/core/facets/module/revise.rb', line 51

def integrate(mod, &block)
  #include mod.revisal( &blk )
  m = Module.new{ include mod }
  m.class_eval(&block)
  include m
end

#is(*mods) ⇒ Object

alias_method :is, :include



27
28
29
30
31
32
33
34
35
36
37
38
39
# File 'lib/gems/facets-2.4.5/lib/core/facets/module/is.rb', line 27

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 X ; end
class Y < X ; end

 Y.is?(X)  #=> true

 CREDIT: Trans

Returns:

  • (Boolean)


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

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

#memoize(*meths) ⇒ Object

Directive for making your functions faster by trading space for time. When you “memoize” a method/function its results are cached so that later calls with the same arguments returns results in the cache instead of recalculating them.

class T
  def initialize(a)
    @a = a
  end
  def a
    "#{@a ^ 3 + 4}"
  end
  memoize :a
end

t = T.new
t.a.__id__ == t.a.__id__  #=> true


61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
# File 'lib/gems/facets-2.4.5/lib/more/facets/memoize.rb', line 61

def memoize(*meths)
  @_MEMOIZE_CACHE ||= Hash.new
  meths.each do |meth|
    mc = @_MEMOIZE_CACHE[meth] = Hash.new
    old = instance_method(meth)
    new = proc do |*args|
      if mc.has_key? args
        mc[args]
      else
        mc[args] = old.bind(self).call(*args)
      end
    end
    send(:define_method, meth, &new)
  end
end

#method_overloadsObject



25
26
27
# File 'lib/gems/facets-2.4.5/lib/more/facets/overload.rb', line 25

def method_overloads
  @method_overloads ||= {}
end

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

Define a simple method namespace.

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
a.x  # no method error


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
83
84
85
86
87
88
# File 'lib/gems/facets-2.4.5/lib/more/facets/methodspace.rb', line 48

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.instance_eval do
      define_method(m) do
        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|
      mtab[op].bind(self).call(*args)
    end
  end
end

#methodizeObject

Translate a module name to a suitable method name.

My::CoolClass.methodize => "my__cool_class"


9
10
11
# File 'lib/gems/facets-2.4.5/lib/core/facets/module/methodize.rb', line 9

def methodize
  name.methodize
end

#mixin_parametersObject Also known as: mixin_params

Store for parametric mixin parameters.

Returns a hash, the keys of which are the parametric mixin module and the values are the parameters associacted with this module/class.

class C
  include P(:x=>1)
end

C.mixin_parameters[P]   #=> {:x=>1}


196
197
198
# File 'lib/gems/facets-2.4.5/lib/more/facets/paramix.rb', line 196

def mixin_parameters
  @mixin_parameters ||= {}
end

#modspaceObject

Returns the module’s container module.

module Example
  class Demo
  end
end

Example::Demo.modspace   #=> Example

See also Module#basename.

CREDIT: Trans


16
17
18
19
# File 'lib/gems/facets-2.4.5/lib/core/facets/module/modspace.rb', line 16

def modspace
  space = name[ 0...(name.rindex( '::' ) || 0)]
  space.empty? ? Object : eval(space)
end

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

Load file into module/class namespace.

CREDIT: Trans

Raises:

  • (LoadError)


9
10
11
12
13
14
15
16
17
18
19
20
21
# File 'lib/gems/facets-2.4.5/lib/core/facets/module/module_load.rb', line 9

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.

CREDIT: Trans

Raises:

  • (LoadError)


27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
# File 'lib/gems/facets-2.4.5/lib/core/facets/module/module_load.rb', line 27

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
  @loaded ||= {}
  if @loaded.key?(file)
    false
  else
    @loaded[file] = true
    script = File.read(file)
    module_eval(script)
    true
  end
end

#nestingObject

Show a modules nesting in module namespaces.

 A::B::C.nesting  #=> [ A, A::B ]

CREDIT: Trans


9
10
11
12
13
14
15
# File 'lib/gems/facets-2.4.5/lib/core/facets/module/nesting.rb', line 9

def nesting
  n = []
  name.split(/::/).inject(self) do |mod, name|
    c = mod.const_get(name) ; n << c ; c
  end
  return n
end

#overload(name, *signiture, &block) ⇒ Object

Overload methods.

class X
  def x
    "hello"
  end

  overload :x, Integer do |i|
    i
  end

  overload :x, String, String do |s1, s2|
    [s1, s2]
  end
end

Raises:

  • (ArgumentError)


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
83
84
85
86
87
88
89
90
91
# File 'lib/gems/facets-2.4.5/lib/more/facets/overload.rb', line 45

def overload( name, *signiture, &block )
  raise ArgumentError unless signiture.all?{|s| s.instance_of?(Class)} 

  name = name.to_sym

  if method_overloads.key?( name )
    method_overloads[name][signiture] = block

  else
    method_overloads[name] = {}
    method_overloads[name][signiture] = block

    if method_defined?( name )
      #method_overloads[name][nil] = instance_method( name ) #true
      alias_method( "#{name}Generic", name )
      has_generic = true
    else
      has_generic = false
    end

    define_method( name ) do |*args|
      ovr = self.class.method_overloads["#{name}".to_sym]
      sig = args.collect{ |a| a.class }
      hit = nil
      faces = ovr.keys #.sort { |a,b| b.size <=> a.size }
      faces.each do |cmp|
        next unless cmp.size == sig.size
        if (0...cmp.size).all?{ |i| cmp[i] >= sig[i] }
          break hit = cmp
        end
      end 
      if hit
        ovr[hit].call(*args)
      else
        if has_generic #ovr[nil]
          send( "#{name}Generic", *args )
          #ovr[nil].bind(self).call(*args)
        else
          raise NoMethodError
        end
      end

    end

  end

end

#pathizeObject

Converts a class name to a unix path

Examples

CoolClass.pathize       #=> "cool_class"
My::CoolClass.pathize   #=> "my/cool_class"


11
12
13
14
15
16
17
18
19
# File 'lib/gems/facets-2.4.5/lib/core/facets/module/pathize.rb', line 11

def pathize
  name.pathize
  #to_s.
  #  gsub(/::/, '/').
  #  gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
  #  gsub(/([a-z\d])([A-Z])/,'\1_\2').
  #  tr("-", "_").
  #  downcase
end

#prepend(aspect) ⇒ Object

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

 module X
   def x; "x"; end
 end

 module U
   def x; '{' + super + '}'; end
 end

 X.prepend U

 X.x  # => "{x}"

CREDIT Trans


20
21
22
23
# File 'lib/gems/facets-2.4.5/lib/core/facets/module/prepend.rb', line 20

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

#private_conflict?(other) ⇒ Boolean

Like #conflict?, but checks only private methods.

Returns:

  • (Boolean)


47
48
49
50
51
52
# File 'lib/gems/facets-2.4.5/lib/core/facets/module/conflict.rb', line 47

def private_conflict?(other)
  common_ancestor = (ancestors & other.ancestors).first
  c = private_instance_methods(true) & other.private_instance_methods(true)
  c -= common_ancestor.private_instance_methods(true)
  c.empty? ? false : c
end

#protected_conflict?(other) ⇒ Boolean

Like #conflict?, but checks only protected methods.

Returns:

  • (Boolean)


55
56
57
58
59
60
# File 'lib/gems/facets-2.4.5/lib/core/facets/module/conflict.rb', line 55

def protected_conflict?(other)
  common_ancestor = (ancestors & other.ancestors).first
  c = protected_instance_methods(true) & other.protected_instance_methods(true)
  c -= common_ancestor.protected_instance_methods(true)
  c.empty? ? false : c
end

#public_conflict?(other) ⇒ Boolean

Like #conflict?, but checks only public methods.

Returns:

  • (Boolean)


39
40
41
42
43
44
# File 'lib/gems/facets-2.4.5/lib/core/facets/module/conflict.rb', line 39

def public_conflict?(other)
  common_ancestor = (ancestors & other.ancestors).first
  c = public_instance_methods(true) & other.public_instance_methods(true)
  c -= common_ancestor.public_instance_methods(true)
  c.empty? ? false : c
end

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

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

CREDIT: Trans


13
14
15
16
17
18
# File 'lib/gems/facets-2.4.5/lib/core/facets/module/revise.rb', line 13

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

#setting(sym, options = {}) ⇒ Object

Defines a configuration setting for the enclosing class.

Example

class Compiler

setting :template_root, :default => 'src/template', :doc => 'The template root dir'

end



233
234
235
236
237
238
239
240
241
242
243
244
245
# File 'lib/gems/facets-2.4.5/lib/more/facets/settings.rb', line 233

def setting(sym, options = {})
  Settings.add_setting(self, sym, options)

  module_eval %{
    def self.#{sym}
      Settings[#{self}][:#{sym}].value
    end

    def self.#{sym}=(obj)
      Settings.setting #{self}, :#{sym}, :value => obj
    end
  }
end

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

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

CREDIT: Gavin Sinclair
CREDIT: Noah Gibbs

Returns:

  • (Boolean)


33
34
35
# File 'lib/gems/facets-2.4.5/lib/core/facets/module/instance_methods.rb', line 33

def singleton_method_defined?(meth)
  singleton_methods(true).find{ |m| m == meth.to_s }
end

#spacenameObject

Returns the name of module’s container module.

module Example
  class Demo
  end
end

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

This used to be called dirname.

See also Module#basename.

CREDIT: Trans


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

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

#try_dupObject



10
11
12
# File 'lib/gems/extlib-0.9.8/lib/extlib/module.rb', line 10

def try_dup
  self
end

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

wrap_method( sym ) { |old_meth, *args|
  old_meth.call
  ...
}

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

CREDIT: Trans


20
21
22
23
# File 'lib/gems/facets-2.4.5/lib/core/facets/module/wrap_method.rb', line 20

def wrap_method( sym, &blk )
  old = instance_method(sym)
  define_method(sym) { |*args| blk.call(old.bind(self), *args) }
end