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
- *
- *
- +
- +
- -
- -
- Comparable
- Comparable
- abstract
- abstract
- all_instance_methods
- all_instance_methods
- ancestor?
- ancestor?
- basename
- basename
- class_def
- class_load
- class_load
- class_require
- class_require
- conflict?
- conflict?
- instance_method_defined?
- instance_method_defined?
- integrate
- integrate
- is
- is
- is?
- is?
- methodize
- methodize
- modspace
- modspace
- module_load
- module_load
- module_method_defined?
- module_method_defined?
- module_require
- module_require
- nesting
- nesting
- pathize
- pathize
- prepend
- prepend
- private_conflict?
- private_conflict?
- protected_conflict?
- protected_conflict?
- public_conflict?
- public_conflict?
- revisal
- revisal
- revise
- revise
- singleton_method_defined?
- singleton_method_defined?
- spacename
- spacename
- wrap
- wrap
- wrap_method
- wrap_method
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
[ show source ]
# File 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
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
[ show source ]
# File 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
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
[ show source ]
# File lib/core/facets/module/op.rb, line 36 def +(other) base = self Module.new do include base include other end end
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
[ show source ]
# File lib/core/facets/module/op.rb, line 36 def +(other) base = self Module.new do include base include other end end
Subtract modules.
TODO: Should this use all instance_methods, not just public? CREDIT: Thomas Sawyer CREDIT: Robert Dober
[ show source ]
# File 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
Subtract modules.
TODO: Should this use all instance_methods, not just public? CREDIT: Thomas Sawyer CREDIT: Robert Dober
[ show source ]
# File 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
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
[ show source ]
# File 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
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
[ show source ]
# File 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
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
[ show source ]
# File lib/core/facets/module/abstract.rb, line 15 def abstract( *sym ) sym.each { |s| define_method( s ) { raise TypeError, "undefined abstraction ##{s}" } } end
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
[ show source ]
# File lib/core/facets/module/abstract.rb, line 15 def abstract( *sym ) sym.each { |s| define_method( s ) { raise TypeError, "undefined abstraction ##{s}" } } end
List all instance methods, equivalent to
public_instance_methods + protected_instance_methods + private_instance_methods
TODO: Better name for all_instance_methods?
CREDIT: Trans
[ show source ]
# File 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
List all instance methods, equivalent to
public_instance_methods + protected_instance_methods + private_instance_methods
TODO: Better name for all_instance_methods?
CREDIT: Trans
[ show source ]
# File 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
Is a given class or module an ancestor of this class or module?
class X ; end class Y < X ; end X.ancestor?(Y)
[ show source ]
# File lib/core/facets/module/ancestor.rb, line 11 def ancestor?( mod ) ancestors.include? mod end
Is a given class or module an ancestor of this class or module?
class X ; end class Y < X ; end X.ancestor?(Y)
[ show source ]
# File lib/core/facets/module/ancestor.rb, line 11 def ancestor?( mod ) ancestors.include? mod end
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
[ show source ]
# 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
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
[ show source ]
# 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
Defines an instance method within a class.
CREDIT: WhyTheLuckyStiff
[ show source ]
# File lib/core/facets/metaid.rb, line 109 def class_def name, &blk class_eval { define_method name, &blk } end
Alias for module_load
Alias for module_load
Alias for module_require
Alias for module_require
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
[ show source ]
# File lib/core/facets/module/conflict.rb, line 21 def conflict?(other) 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.empty? ? false : c end
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
[ show source ]
# File lib/core/facets/module/conflict.rb, line 21 def conflict?(other) 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.empty? ? false : c end
Query whether an instance method is defined for the module.
CREDIT: Gavin Sinclair CREDIT: Noah Gibbs
[ show source ]
# File lib/core/facets/module/instance_methods.rb, line 24 def instance_method_defined?(meth) instance_methods_all(true).find{ |m| m == meth.to_s } end
Query whether an instance method is defined for the module.
CREDIT: Gavin Sinclair CREDIT: Noah Gibbs
[ show source ]
# File lib/core/facets/module/instance_methods.rb, line 24 def instance_method_defined?(meth) instance_methods_all(true).find{ |m| m == meth.to_s } end
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
[ show source ]
# File 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
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
[ show source ]
# File 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
alias_method :is, :include
[ show source ]
# File 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
alias_method :is, :include
[ show source ]
# File 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 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
[ show source ]
# File lib/core/facets/module/is.rb, line 13 def is?(base) ancestors.slice(1..-1).include?(base) end
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
[ show source ]
# File lib/core/facets/module/is.rb, line 13 def is?(base) ancestors.slice(1..-1).include?(base) end
Translate a module name to a suitable method name.
My::CoolClass.methodize => "my__cool_class"
[ show source ]
# File lib/core/facets/module/methodize.rb, line 9 def methodize name.methodize end
Translate a module name to a suitable method name.
My::CoolClass.methodize => "my__cool_class"
[ show source ]
# File lib/core/facets/module/methodize.rb, line 9 def methodize name.methodize end
Returns the module‘s container module.
module Example class Demo end end Example::Demo.modspace #=> Example
See also Module#basename.
CREDIT: Trans
[ show source ]
# File lib/core/facets/module/modspace.rb, line 16 def modspace space = name[ 0...(name.rindex( '::' ) || 0)] space.empty? ? Object : eval(space) end
Returns the module‘s container module.
module Example class Demo end end Example::Demo.modspace #=> Example
See also Module#basename.
CREDIT: Trans
[ show source ]
# File lib/core/facets/module/modspace.rb, line 16 def modspace space = name[ 0...(name.rindex( '::' ) || 0)] space.empty? ? Object : eval(space) end
Load file into module/class namespace.
CREDIT: Trans
[ show source ]
# File 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
Load file into module/class namespace.
CREDIT: Trans
[ show source ]
# File 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
Require file into module/class namespace.
CREDIT: Trans
[ show source ]
# File 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
Require file into module/class namespace.
CREDIT: Trans
[ show source ]
# File 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
Show a modules nesting in module namespaces.
A::B::C.nesting #=> [ A, A::B ] CREDIT: Trans
[ show source ]
# File 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
Show a modules nesting in module namespaces.
A::B::C.nesting #=> [ A, A::B ] CREDIT: Trans
[ show source ]
# File 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
Converts a class name to a unix path
Examples
CoolClass.pathize #=> "cool_class" My::CoolClass.pathize #=> "my/cool_class"
[ show source ]
# File 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
Converts a class name to a unix path
Examples
CoolClass.pathize #=> "cool_class" My::CoolClass.pathize #=> "my/cool_class"
[ show source ]
# File 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 an aspect module to a module.
module X def x; "x"; end end module U def x; '{' + super + '}'; end end X.prepend U X.x # => "{x}" CREDIT Trans
[ show source ]
# File lib/core/facets/module/prepend.rb, line 19 def prepend(aspect) aspect.__send__(:include, self) extend aspect end
Prepend an aspect module to a module.
module X def x; "x"; end end module U def x; '{' + super + '}'; end end X.prepend U X.x # => "{x}" CREDIT Trans
[ show source ]
# File lib/core/facets/module/prepend.rb, line 19 def prepend(aspect) aspect.__send__(:include, self) extend aspect end
Like conflict?, but checks only private methods.
[ show source ]
# File lib/core/facets/module/conflict.rb, line 43 def private_conflict?(other) c = private_instance_methods(true) & other.private_instance_methods(true) c.empty? ? false : c end
Like conflict?, but checks only private methods.
[ show source ]
# File lib/core/facets/module/conflict.rb, line 43 def private_conflict?(other) c = private_instance_methods(true) & other.private_instance_methods(true) c.empty? ? false : c end
Like conflict?, but checks only protected methods.
[ show source ]
# File lib/core/facets/module/conflict.rb, line 50 def protected_conflict?(other) c = protected_instance_methods(true) & other.protected_instance_methods(true) c.empty? ? false : c end
Like conflict?, but checks only protected methods.
[ show source ]
# File lib/core/facets/module/conflict.rb, line 50 def protected_conflict?(other) c = protected_instance_methods(true) & other.protected_instance_methods(true) c.empty? ? false : c end
Like conflict?, but checks only public methods.
[ show source ]
# File lib/core/facets/module/conflict.rb, line 36 def public_conflict?(other) c = public_instance_methods(true) & other.public_instance_methods(true) c.empty? ? false : c end
Like conflict?, but checks only public methods.
[ show source ]
# File lib/core/facets/module/conflict.rb, line 36 def public_conflict?(other) c = public_instance_methods(true) & other.public_instance_methods(true) c.empty? ? false : c end
Alias for revise
Alias for revise
Return a new module based on another. This includes the original module into the new one.
CREDIT: Trans
[ show source ]
# File lib/core/facets/module/revise.rb, line 13 def revise(&blk) base = self nm = Module.new{ include base } nm.class_eval(&blk) nm end
Return a new module based on another. This includes the original module into the new one.
CREDIT: Trans
[ show source ]
# File lib/core/facets/module/revise.rb, line 13 def revise(&blk) base = self nm = Module.new{ include base } nm.class_eval(&blk) nm end
Query whether a normal (singleton) method is defined for the module.
CREDIT: Gavin Sinclair CREDIT: Noah Gibbs
[ show source ]
# File lib/core/facets/module/instance_methods.rb, line 33 def singleton_method_defined?(meth) singleton_methods(true).find{ |m| m == meth.to_s } end
Query whether a normal (singleton) method is defined for the module.
CREDIT: Gavin Sinclair CREDIT: Noah Gibbs
[ show source ]
# File lib/core/facets/module/instance_methods.rb, line 33 def singleton_method_defined?(meth) singleton_methods(true).find{ |m| m == meth.to_s } end
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
[ show source ]
# File lib/core/facets/module/spacename.rb, line 19 def spacename name[0...(name.rindex('::') || 0)] #name.gsub(/::[^:]*$/, '') end
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
[ show source ]
# File lib/core/facets/module/spacename.rb, line 19 def spacename name[0...(name.rindex('::') || 0)] #name.gsub(/::[^:]*$/, '') end
Alias for wrap_method
Alias for wrap_method
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
[ show source ]
# File 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
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
[ show source ]
# File 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