Rename methods.
module AStar def a; "a"; end end BStar = AStar * { :a => :b } class XStar; include BStar; end XStar.new.b #=> "a"
CREDIT: Thomas Sawyer, Robert Dober
# File lib/facets/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
Combine modules.
module APlus def a; "a"; end end module BPlus def b; "b"; end end CPlus = APlus + BPlus class XPlus; include CPlus; end XPlus.new.a #=> "a" XPlus.new.b #=> "b"
Note that in the old version of traits.rb we cloned modules and altered their copies...
def +(other) mod1 = other.clone mod2 = clone mod1.module_eval{ include mod2 } end
Later it was realized that this thwarted the main benefit that Ruby's concept of modules has over traditional traits, inheritance.
CREDIT: Thomas Sawyer, Robert Dober
# File lib/facets/core/facets/module/op.rb, line 35 def +(other) base = self Module.new do include base include other end end
Subtract modules.
module AMinus def a; "a"; end def b; "b"; end end CMinus = AMinus - [:a] class XMinus; include CMinus; end expect NameError do XMinus.new.a #=> "a" end XMinus.new.b #=> "b"
TODO: Should this use all instance methods, not just public?
CREDIT: Thomas Sawyer, Robert Dober
# File lib/facets/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
Create an abstract method. If it is not overridden, it will raise a TypeError when called.
class AbstractExample abstract :a end c = AbstractExample.new expect TypeError do c.a end
CREDIT: Trans
# File lib/facets/core/facets/module/abstract.rb, line 18 def abstract(*sym) sym.each do |s| define_method(s){ raise TypeError, "undefined abstraction ##{s}" } end end
Encapsulates the common pattern of ...
alias_method :foo_without_feature, :foo alias_method :foo, :foo_with_feature
With this, you simply do ...
alias_method_chain :foo, :feature
For example
class AliasMethodChainExample def foo "foo" end def foo_with_feature "foo!" end alias_method_chain :foo, :feature end
And both aliases are set up for you.
example = AliasMethodChainExample.new example.foo #=> "foo!" example.foo_without_feature #=> "foo"
Query and bang methods (foo?, foo!) keep the same punctuation ...
alias_method_chain :foo?, :feature
is equivalent to ...
alias_method :foo_without_feature?, :foo? alias_method :foo?, :foo_with_feature?
so you can safely chain foo, foo?, and foo! with the same feature.
CREDIT: Bitsweat, Rails Team
# File lib/facets/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
List all instance methods, equivalent to
public_instance_methods + protected_instance_methods + private_instance_methods
TODO: Better name for all_instance_methods?
CREDIT: Trans
# File lib/facets/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
Is a given class or module an ancestor of this class or module?
class X ; end class Y < X ; end X.ancestor?(Y)
# File lib/facets/core/facets/module/ancestor.rb, line 11 def ancestor?( mod ) ancestors.include?(mod) end
A module may or may not have a name.
module M; end M.name # => "M"
m = Module.new m.name # => ""
A module gets a name when it is first assigned to a constant. Either via the module or class keyword or by an explicit assignment:
m = Module.new # creates an anonymous module M = m # => m gets a name here as a side-effect m.name # => "M"
# File lib/facets/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
Create an attribute method for both getting and setting an instance variable:
attr_setter :a
is equivalent to:
def a(*args) if args.size > 0 @a = args[0] self else @a end end
CREDIT: Trans
# File lib/facets/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
Returns the root name of the module/class.
module ::BaseName class Example end end BaseName::Example.name #=> "BaseName::Example" BaseName::Example.basename #=> "Example"
For anonymous modules this will provide a basename based on Module#inspect.
m = Module.new m.inspect # "#<Module:0xb7bb0434>" m.basename # "Module_0xb7bb0434"
CREDIT: Trans
# File lib/facets/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/module.
CREDIT: WhyTheLuckyStiff
# File lib/facets/core/facets/module/module_def.rb, line 7 def class_def name, &blk class_eval { define_method name, &blk } end
Returns the module or class containing the receiver.
module ::HomeExample module M module N end end end HomeExample::M::N.home #=> HomeExample::M
The home of a top-level module/class is Object.
HomeExample.home #=> Object
This method is called home because techinally a module or class is just a constant reference, and as such can reside with multiple namespaces, like any variable. For example:
module OtherPlace M = ::HomeExample::M end
In this example, you might think that +OtherPlace::M+'s home would be OtherPlace, but +OtherPlace::M+ is the same object as +HomeExample::M+, and it can have only one "home" --the original location of it's definition.
# File lib/facets/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
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.
# File lib/facets/core/facets/module/home.rb, line 57 def homename /::[^:]+\Z/ =~ name ? $` : nil end
Returns all the namespaces of this module according ordered from nearest and moving outwards. The receiver is not contained within the result.
module ::HouseExample module M module N end end end HouseExample.housing #=> [Object] HouseExample::M.housing #=> [HouseExample, Object] HouseExample::M::N.housing #=> [HouseExample::M, HouseExample, Object]
Compare this to Module.nesting.
# File lib/facets/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
Access method as a singleton object and retain state.
module ::K def hello puts "Hello World!" end end K.instance_method!(:hello).inspect #=> "#<UnboundMethod: K#hello>"
NOTE: This is limited to the scope of the current module/class.
# File lib/facets/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
Query whether a public instance method is defined for the module.
CREDIT: Gavin Sinclair, Noah Gibbs
# File lib/facets/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
Using integrate is just like using include except the module included is a reconstruction of the one given altered by the commands given in the block.
Convenient commands available are: rename, redef, remove, nodef and wrap. But any module method can be used.
module IntegrateExampleModule def q ; "q" ; end def y ; "y" ; end end class InegrateExampleClass integrate IntegrateExampleModule do undef_method :y end end x = InegrateExampleClass.new x.q #=> "q" expect NameError do x.y end
This is like revisal, but revisal only returns the reconstructred module. It does not include it.
CREDIT: Trans
# File lib/facets/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
An alias for include.
class IsExample is Enumerable end
CREDIT: Trans
# File lib/facets/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 a given class or module an ancestor of this class or module?
class IsX ; end class IsY < IsX ; end IsY.is?(IsX) #=> true
CREDIT: Trans
# File lib/facets/core/facets/module/is.rb, line 13 def is?(base) Module===base && ancestors.slice(1..-1).include?(base) end
Translate a module name to a suitable method name.
module ::EgMethodize module Eg end end EgMethodize.methodize #=> "eg_methodize" EgMethodize::Eg.methodize #=> "eg_methodize__eg"
# File lib/facets/core/facets/module/methodize.rb, line 15 def methodize name.methodize end
Defines an instance method within a class/module.
CREDIT: WhyTheLuckyStiff
# File lib/facets/core/facets/module/module_def.rb, line 15 def module_def name, &blk module_eval { define_method name, &blk } end
Converts a class name to a unix path.
module ::ExamplePathize module Example end end ExamplePathize.pathize #=> "example_pathize" ExamplePathize::Example.pathize #=> "example_pathize/example"
# File lib/facets/core/facets/module/pathize.rb, line 15 def pathize name.pathize end
Return a new module based on another. This includes the original module into the new revised module.
module ReviseExample def foo; "foo"; end end ReviseExample2 = ReviseExample.revise do alias_method :bar, :foo end object = Object.new object.extend ReviseExample2 object.bar #=> 'foo'
CREDIT: Trans
# File lib/facets/core/facets/module/revise.rb, line 26 def revise(&blk) base = self nm = Module.new{ include base } nm.class_eval(&blk) nm end
Sets an option to the given value. If the value is a proc, the proc will be called every time the option is accessed.
CREDIT: Blake Mizerany (Sinatra)
# File lib/facets/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
Query whether a normal (singleton) method is defined for the module.
CREDIT: Gavin Sinclair, Noah Gibbs
# File lib/facets/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
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
# File lib/facets/core/facets/module/spacename.rb, line 19 def spacename name[0...(name.rindex('::') || 0)] #name.gsub(/::[^:]*$/, '') end
Create an instance of Object and extend it with self.
mod = Module.new do def foo; "foo"; end end obj = mod.to_obj obj.foo #=> "foo"
# File lib/facets/core/facets/module/to_obj.rb, line 13 def to_obj o = Object.new o.extend self o 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.
class WrapExample def foo "foo" end wrap_method(:foo) do |old_meth, *args| old_meth.call + '!' end end example = WrapExample.new example.foo #=> 'foo!'
Keep in mind that this cannot be used to wrap methods that take a block.
CREDIT: Trans
# File lib/facets/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
As with alias_method, but alias both reader and writer.
attr_accessor :x self.x = 1 alias_accessor :y, :x y #=> 1 self.y = 2 x #=> 2
# File lib/facets/core/facets/module/alias_accessor.rb, line 14 def alias_accessor(*args) orig = args.last args = args - [orig] args.each do |name| alias_method(name, orig) alias_method("#{name}=", "#{orig}=") end end
Alias a module function so that the alias is also a module function. The typical alias_method does not do this.
module AliasExample module_function def hello "Hello" end end AliasExample.hello #=> 'Hello' module AliasExample alias_module_function( :hi , :hello ) end AliasExample.hi #=> 'Hello'
# File lib/facets/core/facets/module/alias_module_function.rb, line 24 def alias_module_function(new, old) alias_method(new, old) module_function(new) end
As with alias_accessor, but just for the reader. This is basically the same as alias_method.
# File lib/facets/core/facets/module/alias_accessor.rb, line 26 def alias_reader(*args) orig = args.last args = args - [orig] args.each do |name| alias_method(name, orig) end end
As with alias_method but does the writer instead.
# File lib/facets/core/facets/module/alias_accessor.rb, line 36 def alias_writer(*args) orig = args.last args = args - [orig] args.each do |name| alias_method("#{name}=", "#{orig}=") end end
Include module and apply module_fuction to the included methods.
module Utils module_function def foo; "foo"; end end module UtilsPlus include_function_module Utils end
CREDIT: Trans
# File lib/facets/core/facets/module/include_function_module.rb, line 19 def include_function_module *mod include(*mod) module_function(*mod.collect{|m| m.private_instance_methods & m.methods(false)}.flatten) end
Creates a new method for a pre-existing method.
If aka is given, then the method being redefined will first be aliased to this name.
class Greeter def hello ; "Hello" ; end end Greeter.new.hello #=> "Hello" class Greeter redefine_method( :hello, :hi ) do hi + ", friend!" end end Greeter.new.hello #=> "Hello, friend!"
CREDIT: Trans
# File lib/facets/core/facets/module/redefine_method.rb, line 26 def redefine_method(sym, aka=nil, &blk) alias_method(aka, sym) if aka ## prevent warning about method overwrite begin remove_method(sym) rescue NameError end ## define replacelemt method define_method(sym, &blk) end
Redirect methods to other methods. This simply defines methods by the name of a hash key which calls the method with the name of the hash's value.
class RedirectExample redirect_method :hi => :hello, :hey => :hello def hello(name) "Hello, #{name}." end end e = RedirectExample.new e.hello("Bob") #=> "Hello, Bob." e.hi("Bob") #=> "Hello, Bob." e.hey("Bob") #=> "Hello, Bob."
The above class definition is equivalent to ...
class RedirectExample def hi(*args) hello(*args) end def hey(*args) hello(*args) end def hello puts "Hello" end end
CREDIT: Trans
# File lib/facets/core/facets/module/redirect_method.rb, line 37 def redirect_method( method_hash ) method_hash.each do |targ,adv| define_method(targ) { |*args| send(adv,*args) } end end
Aliases a method and undefines the original.
class RenameExample def foo; "foo"; end rename_method(:bar, :foo) end example = RenameExample.new example.bar #=> 'foo' expect NoMethodError do example.foo end
CREDIT: Trans
# File lib/facets/core/facets/module/rename_method.rb, line 21 def rename_method( to_sym, from_sym ) raise ArgumentError, "method #{from_sym} does not exist" unless method_defined?( from_sym ) alias_method( to_sym, from_sym ) undef_method( from_sym ) end
Generated with the Darkfish Rdoc Generator 2.