Class: Module
- Defined in:
- lib/core/facets/module/is.rb,
lib/core/facets/module/op.rb,
lib/core/facets/module/can.rb,
lib/core/facets/module/set.rb,
lib/core/facets/module/home.rb,
lib/core/facets/module/class.rb,
lib/core/facets/module/nodef.rb,
lib/core/facets/module/revise.rb,
lib/core/facets/module/to_obj.rb,
lib/core/facets/module/pathize.rb,
lib/core/facets/module/abstract.rb,
lib/core/facets/module/ancestor.rb,
lib/core/facets/module/basename.rb,
lib/core/facets/module/anonymous.rb,
lib/core/facets/module/integrate.rb,
lib/core/facets/module/methodize.rb,
lib/core/facets/module/spacename.rb,
lib/core/facets/module/module_def.rb,
lib/core/facets/module/attr_setter.rb,
lib/core/facets/module/wrap_method.rb,
lib/core-uncommon/facets/module/let.rb,
lib/core/facets/module/rename_method.rb,
lib/core-uncommon/facets/module/cattr.rb,
lib/core/facets/module/alias_accessor.rb,
lib/core/facets/module/instance_method.rb,
lib/core/facets/module/redefine_method.rb,
lib/core/facets/module/redirect_method.rb,
lib/core-uncommon/facets/module/memoize.rb,
lib/core-uncommon/facets/module/prepend.rb,
lib/core-uncommon/facets/module/enclosure.rb,
lib/core-uncommon/facets/module/preextend.rb,
lib/core/facets/module/alias_method_chain.rb,
lib/core-uncommon/facets/module/attr_tester.rb,
lib/core-uncommon/facets/module/module_load.rb,
lib/core/facets/module/all_instance_methods.rb,
lib/core-uncommon/facets/module/class_extend.rb,
lib/core-uncommon/facets/module/method_clash.rb,
lib/core-uncommon/facets/module/method_space.rb,
lib/core/facets/module/alias_module_function.rb,
lib/core-uncommon/facets/module/attr_inheritor.rb,
lib/core-uncommon/facets/module/attr_validator.rb,
lib/core-uncommon/facets/module/class_accessor.rb,
lib/core-uncommon/facets/module/copy_inheritor.rb,
lib/core/facets/module/include_function_module.rb,
lib/core/facets/module/instance_method_defined.rb,
lib/core-uncommon/facets/module/class_inheritor.rb,
lib/core-uncommon/facets/module/instance_function.rb,
lib/core-uncommon/facets/module/attr_class_accessor.rb
Defined Under Namespace
Modules: InstanceFunction
Instance Method Summary collapse
-
#*(rename_map) ⇒ Object
Rename methods.
-
#+(other) ⇒ Object
Combine modules.
-
#-(other) ⇒ Object
Subtract modules.
-
#abstract(*sym) ⇒ Object
Create an abstract method.
-
#alias_method_chain(target, feature) {|aliased_target, punctuation| ... } ⇒ Object
Encapsulates the common pattern of …
-
#alias_tester(*args) ⇒ Object
Create aliases for flag reader.
-
#alias_validator(*args) ⇒ Object
Create aliases for validators.
-
#all_instance_methods(include_super = true) ⇒ Object
List all instance methods, equivalent to.
-
#ancestor?(mod) ⇒ Boolean
Is a given class or module an ancestor of this class or module?.
-
#anonymous? ⇒ Boolean
A module may or may not have a name.
-
#attr_class_accessor(name) ⇒ Object
NOTE: This is not (presently) a common core extension and is not loaded automatically when using
require 'facets'
. -
#attr_class_reader(name) ⇒ Object
NOTE: This is not (presently) a common core extension and is not loaded automatically when using
require 'facets'
. -
#attr_class_writer(name) ⇒ Object
NOTE: This is not (presently) a common core extension and is not loaded automatically when using
require 'facets'
. -
#attr_inheritable_reader(name, default) ⇒ Object
NOTE: This is not (presently) a common core extension and is not loaded automatically when using
require 'facets'
. -
#attr_setter(*args) ⇒ Object
Create an attribute method for both getting and setting an instance variable:.
-
#attr_tester(*args) ⇒ Object
Create an tester attribute.
-
#attr_validator(*symbols, &validator) ⇒ Object
Like attr_writer, but the writer method validates the setting against the given block.
-
#basename ⇒ Object
Returns the root name of the module/class.
-
#cattr(*syms) ⇒ Object
Creates a class-variable attribute that can be accessed both on an instance and class level.
-
#cattr_accessor(*syms) ⇒ Object
Creates a class-variable attr_accessor that can be accessed both on an instance and class level.
-
#cattr_reader(*syms) ⇒ Object
Creates a class-variable attr_reader that can be accessed both on an instance and class level.
-
#cattr_writer(*syms) ⇒ Object
Creates a class-variable attr_writer that can be accessed both on an instance and class level.
-
#class_accessor(name) ⇒ Object
NOTE: This is not (presently) a common core extension and is not loaded automatically when using
require 'facets'
. -
#class_def(name, &blk) ⇒ Object
Defines an instance method within a class/module.
-
#class_extend(*mods, &block) ⇒ Object
Normally when including modules, class/module methods are not extended.
- #class_extensions ⇒ Object
-
#class_inheritor(key, obj, op = nil, &fop) ⇒ Object
Class Inheritor.
-
#class_reader(name) ⇒ Object
NOTE: This is not (presently) a common core extension and is not loaded automatically when using
require 'facets'
. -
#class_writer(name) ⇒ Object
NOTE: This is not (presently) a common core extension and is not loaded automatically when using
require 'facets'
. -
#copy_inheritor(name, default = {}) ⇒ Object
Like #class_inheritor but non-dynamic.
-
#enclosure ⇒ Object
Returns the module which contains this one according to its name.
-
#enclosures ⇒ Object
Returns all the namespaces of this module according ordered from nearest and moving outwards.
-
#encname ⇒ Object
Eclosure name.
-
#home ⇒ Object
Returns the module or class containing the receiver.
-
#homename ⇒ Object
(also: #modname)
Returns the name of module or class containing the receiver.
-
#housing ⇒ Object
Returns all the namespaces of this module according ordered from nearest and moving outwards.
-
#include_as(h) ⇒ Object
Include a module via a specified space.
-
#instance_function(*meths) ⇒ Object
Converts module methods into instance methods such that the first parameter is passed
self
. -
#instance_method!(s) ⇒ Object
Access method as a singleton object and retain state.
-
#instance_method_defined?(meth) ⇒ Boolean
Query whether a public instance method is defined for the module.
-
#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.
-
#is(*mods) ⇒ Object
An alias for #include.
-
#is?(base) ⇒ Boolean
Is a given class or module an ancestor of this class or module?.
-
#let(var, &block) ⇒ Object
Create a memoized method.
-
#mattr(*syms) ⇒ Object
Creates a class-variable attribute that can be accessed both on an instance and class level.
-
#mattr_accessor(*syms) ⇒ Object
Creates a class-variable attr_accessor that can be accessed both on an instance and class level.
-
#mattr_reader(*syms) ⇒ Object
Creates a class-variable attr_reader that can be accessed both on an instance and class level.
-
#mattr_writer(*syms) ⇒ Object
Creates a class-variable attr_writer that can be accessed both on an instance and class level.
-
#memoize(*args) ⇒ Object
This is here for backward compatibility.
-
#method_clash(other) ⇒ Object
Detect method name clash between modules and/or classes, regardless of method visibility:.
-
#method_clash?(other) ⇒ Boolean
Uses #method_clash to return
true
orfalse
if there are method name clashes. -
#method_space(name, mod = nil, &blk) ⇒ Object
Create method namespaces, allowing for method chains but still accessing the object’s instance.
-
#methodize ⇒ Object
Translate a module name to a suitable method name.
-
#module_def(name, &blk) ⇒ Object
Defines an instance method within a class/module.
-
#module_load(path) ⇒ Object
(also: #class_load)
Load file directly into module/class namespace.
-
#module_require(path) ⇒ Object
(also: #class_require)
Require file into module/class namespace.
-
#pathize ⇒ Object
Converts a class name to a unix path.
-
#preextend(aspect) ⇒ Object
Prepend an
aspect
module to a module. -
#prepend(mod) ⇒ Object
Prepend module.
-
#revise(&blk) ⇒ Object
(also: #revisal)
Return a new module based on another.
-
#set(option, value = self, &block) ⇒ Object
Sets an option to the given value.
-
#singleton_method_defined?(meth) ⇒ Boolean
(also: #module_method_defined?, #class_method_defined?)
Query whether a normal (singleton) method is defined for the module.
-
#spacename ⇒ Object
Returns the name of module’s container module.
-
#to_obj ⇒ Object
Create an instance of Object and extend it with
self
. -
#wrap_method(sym, &blk) ⇒ Object
(also: #wrap)
Creates a new method wrapping the previous of the same name.
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_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
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_tester(*args) ⇒ Object
Create aliases for flag reader.
NOTE: This is not (presently) a common core extension and is not loaded automatically when using require 'facets'
.
CREDIT: Trans
40 41 42 43 44 45 46 |
# File 'lib/core-uncommon/facets/module/attr_tester.rb', line 40 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 validators.
NOTE: This is not (presently) a common core extension and is not loaded automatically when using require 'facets'
.
30 31 32 33 34 35 36 37 |
# File 'lib/core-uncommon/facets/module/attr_validator.rb', line 30 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) ⇒ 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 |
#attr_class_accessor(name) ⇒ Object
NOTE: This is not (presently) a common core extension and is not loaded automatically when using require 'facets'
.
6 7 8 9 |
# File 'lib/core-uncommon/facets/module/attr_class_accessor.rb', line 6 def attr_class_accessor(name) attr_class_reader(name) attr_class_writer(name) end |
#attr_class_reader(name) ⇒ Object
NOTE: This is not (presently) a common core extension and is not loaded automatically when using require 'facets'
.
14 15 16 17 18 19 20 21 22 23 |
# File 'lib/core-uncommon/facets/module/attr_class_accessor.rb', line 14 def attr_class_reader(name) module_eval(<<-EOS, __FILE__, __LINE__) def self.#{name} @#{name} end def #{name} self.class.#{name} end EOS end |
#attr_class_writer(name) ⇒ Object
NOTE: This is not (presently) a common core extension and is not loaded automatically when using require 'facets'
.
28 29 30 31 32 33 34 35 36 37 |
# File 'lib/core-uncommon/facets/module/attr_class_accessor.rb', line 28 def attr_class_writer(name) module_eval(<<-EOS, __FILE__, __LINE__) def self.#{name}=(x) @#{name} = x end def #{name}=(x) self.class.#{name} = x end EOS end |
#attr_inheritable_reader(name, default) ⇒ Object
NOTE: This is not (presently) a common core extension and is not loaded automatically when using require 'facets'
.
6 7 8 9 10 11 12 13 |
# File 'lib/core-uncommon/facets/module/attr_inheritor.rb', line 6 def attr_inheritable_reader(name, default) copy_inheritor(name, default) module_eval(<<-EOS, __FILE__, __LINE__) def #{name} self.class.#{name} end EOS 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
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
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: This is not (presently) a common core extension and is not loaded automatically when using require 'facets'
.
CREDIT: Trans
19 20 21 22 23 24 25 26 27 28 29 30 31 |
# File 'lib/core-uncommon/facets/module/attr_tester.rb', line 19 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 is not (presently) a common core extension and is not loaded automatically when using require 'facets'
.
CREDIT: ?
11 12 13 14 15 16 17 18 19 20 21 22 23 |
# File 'lib/core-uncommon/facets/module/attr_validator.rb', line 11 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 ⇒ Object
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
22 23 24 25 26 27 28 |
# File '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 |
#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 is not (presently) a common core extension and is not loaded automatically when using require 'facets'
.
CREDIT: David Heinemeier Hansson
18 19 20 21 22 23 24 25 26 27 |
# File 'lib/core-uncommon/facets/module/cattr.rb', line 18 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 is not (presently) a common core extension and is not loaded automatically when using require 'facets'
.
CREDIT: David Heinemeier Hansson
117 118 119 |
# File 'lib/core-uncommon/facets/module/cattr.rb', line 117 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 is not (presently) a common core extension and is not loaded automatically when using require 'facets'
.
CREDIT: David Heinemeier Hansson
44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 |
# File 'lib/core-uncommon/facets/module/cattr.rb', line 44 def cattr_reader(*syms) syms.flatten.each do |sym| module_eval(<<-EOS, __FILE__, __LINE__) unless defined? @@#{sym} @@#{sym} = nil end def self.#{sym} @@#{sym} end def #{sym} @@#{sym} end EOS 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 is not (presently) a common core extension and is not loaded automatically when using require 'facets'
.
CREDIT: David Heinemeier Hansson
82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 |
# File 'lib/core-uncommon/facets/module/cattr.rb', line 82 def cattr_writer(*syms) syms.flatten.each do |sym| module_eval(<<-EOS, __FILE__, __LINE__) unless defined? @@#{sym} @@#{sym} = nil end def self.#{sym}=(obj) @@#{sym} = obj end def #{sym}=(obj) @@#{sym}=(obj) end EOS end return syms end |
#class_accessor(name) ⇒ Object
NOTE: This is not (presently) a common core extension and is not loaded automatically when using require 'facets'
.
6 7 8 9 |
# File 'lib/core-uncommon/facets/module/class_accessor.rb', line 6 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 is not (presently) a common core extension and is not loaded automatically when using require 'facets'
.
CREDIT: Daniel Schierbeck, Thomas Sawyer
THANKS: Nobu Nakada, Ulysses
39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 |
# File 'lib/core-uncommon/facets/module/class_extend.rb', line 39 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 ⇒ Object
65 66 67 |
# File 'lib/core-uncommon/facets/module/class_extend.rb', line 65 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 is not (presently) a common core extension and is not loaded automatically when using require 'facets'
.
CREDIT: Thomas Sawyer
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 |
# File 'lib/core-uncommon/facets/module/class_inheritor.rb', line 45 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 is not (presently) a common core extension and is not loaded automatically when using require 'facets'
.
14 15 16 17 18 19 20 |
# File 'lib/core-uncommon/facets/module/class_accessor.rb', line 14 def class_reader(name) module_eval(<<-EOS, __FILE__, __LINE__) def self.#{name} @#{name} end EOS end |
#class_writer(name) ⇒ Object
NOTE: This is not (presently) a common core extension and is not loaded automatically when using require 'facets'
.
25 26 27 28 29 30 31 |
# File 'lib/core-uncommon/facets/module/class_accessor.rb', line 25 def class_writer(name) module_eval(<<-EOS, __FILE__, __LINE__) def self.#{name}=(x) @#{name} = x end EOS 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 is not (presently) a common core extension and is not loaded automatically when using require 'facets'
.
CREDIT: Thomas Sawyer
23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
# File 'lib/core-uncommon/facets/module/copy_inheritor.rb', line 23 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 ⇒ Object
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 is not (presently) a common core extension and is not loaded automatically when using require 'facets'
.
21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
# File 'lib/core-uncommon/facets/module/enclosure.rb', line 21 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 ⇒ Object
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 is not (presently) a common core extension and is not loaded automatically when using require 'facets'
.
55 56 57 58 59 60 61 62 63 |
# File 'lib/core-uncommon/facets/module/enclosure.rb', line 55 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 ⇒ Object
Eclosure name.
module ::EncExample
module M
module N
end
end
end
EncExample::M::N.encname #=> "EncExample::M"
NOTE: This is not (presently) a common core extension and is not loaded automatically when using require 'facets'
.
78 79 80 |
# File 'lib/core-uncommon/facets/module/enclosure.rb', line 78 def encname /::[^:]+\Z/ =~ self.name ? $` : nil end |
#home ⇒ Object
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 |
#homename ⇒ Object 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 |
#housing ⇒ Object
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 is not (presently) a common core extension and is not loaded automatically when using require 'facets'
.
95 96 97 |
# File 'lib/core-uncommon/facets/module/method_space.rb', line 95 def include_as(h) h.each{ |name, mod| method_space(name, mod) } 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 is not (presently) a common core extension and is not loaded automatically when using require 'facets'
.
30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 |
# File 'lib/core-uncommon/facets/module/instance_function.rb', line 30 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
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 |
#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
13 14 15 16 17 18 19 20 21 22 23 24 25 |
# File 'lib/core-uncommon/facets/module/let.rb', line 13 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 is not (presently) a common core extension and is not loaded automatically when using require 'facets'
.
CREDIT: David Heinemeier Hansson
142 143 144 145 146 147 148 149 150 151 |
# File 'lib/core-uncommon/facets/module/cattr.rb', line 142 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 is not (presently) a common core extension and is not loaded automatically when using require 'facets'
.
CREDIT: David Heinemeier Hansson
243 244 245 |
# File 'lib/core-uncommon/facets/module/cattr.rb', line 243 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 is not (presently) a common core extension and is not loaded automatically when using require 'facets'
.
CREDIT: David Heinemeier Hansson
168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 |
# File 'lib/core-uncommon/facets/module/cattr.rb', line 168 def mattr_reader( *syms ) syms.flatten.each do |sym| module_eval(<<-EOS, __FILE__, __LINE__) unless defined? @@#{sym} @@#{sym} = nil end def self.#{sym} @@#{sym} end def #{sym} @@#{sym} end EOS 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 is not (presently) a common core extension and is not loaded automatically when using require 'facets'
.
CREDIT: David Heinemeier Hansson
207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 |
# File 'lib/core-uncommon/facets/module/cattr.rb', line 207 def mattr_writer(*syms) syms.flatten.each do |sym| module_eval(<<-EOS, __FILE__, __LINE__) unless defined? @@#{sym} @@#{sym} = nil end def self.#{sym}=(obj) @@#{sym} = obj end def #{sym}=(obj) @@#{sym}=(obj) end EOS end return syms end |
#memoize(*args) ⇒ Object
This is here for backward compatibility.
6 7 8 9 10 |
# File 'lib/core-uncommon/facets/module/memoize.rb', line 6 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
– TODO: Should method_clash just be public methods? TODO: Provide an option to select visiblity. ++
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/core-uncommon/facets/module/method_clash.rb', line 27 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.
53 54 55 56 |
# File 'lib/core-uncommon/facets/module/method_clash.rb', line 53 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 is not (presently) a common core extension and is not loaded automatically when using require 'facets'
.
CREDIT: Pit Captain
28 29 30 31 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 |
# File 'lib/core-uncommon/facets/module/method_space.rb', line 28 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 |
#methodize ⇒ Object
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 is not (presently) a common core extension and is not loaded automatically when using require 'facets'
.
CREDIT: Trans
15 16 17 18 19 20 21 22 23 24 25 26 27 |
# File 'lib/core-uncommon/facets/module/module_load.rb', line 15 def module_load( path ) if path =~ /^[\/~.]/ file = File.(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 is not a common core extension and is not loaded automatically when using require 'facets'
.
CREDIT: Trans
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 |
# File 'lib/core-uncommon/facets/module/module_load.rb', line 47 def module_require( path ) if path =~ /^[\/~.]/ file = File.(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 |
#pathize ⇒ Object
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
23 24 25 26 |
# File 'lib/core-uncommon/facets/module/preextend.rb', line 23 def preextend(aspect) aspect.__send__(:include, self) extend aspect end |
#prepend(mod) ⇒ Object
Prepend module.
class X
def a; "Xa"; end
end
module M
def a; "M" + super ; end
end
class X
prepend M
end
X.new.a #=> MXa
IMPORTANT! #prepend is not dynamic, rather it copies all methods when included on a class or module. For this reason one must be careful to invoke #prepend AFTER any method definitions that are to be effected. Ideally this would not be necessary, but it would require support in Ruby’s C+ source to make it possible.
NOTE: This is not a common core extension and is not loaded automatically when using require 'facets'
.
55 56 57 58 |
# File 'lib/core-uncommon/facets/module/prepend.rb', line 55 def prepend(mod) include Prependable include mod 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. #=> '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)
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 |
#spacename ⇒ Object
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_obj ⇒ Object
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 |
#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 |