Facets
From WhyNotWiki
Ruby Facets edit (Category edit)
Ruby libraries / Core edit (Category edit)
[edit] General
[edit] Should it go in Kernel or Object??
In particular, I'm curious about why the following are in Kernel:
- Kernel#meta
- Kernel#meta_*
- Kernel#set_with
- Kernel#methods
- Kernel#singleton_class
- ...
But these are in Object...
- Object#metaclass
- ...
[edit] String
http://facets.rubyforge.org/src/doc/rdoc/core/classes/String.html
[edit] bracket
I probably would've called it "enclose"...
http://facets.rubyforge.org/src/doc/rdoc/core/classes/String.html#M000946
bracket(bra, ket=nil)
Return a new string embraced by given brakets. If only one bracket char is given it will be placed on either side.
"wrap me".bracket('{') #=> "{wrap me}" "wrap me".bracket('--','!') #=> "--wrap me!"
[edit] margin
...
[edit] each_char
Iterates through each character.
# File lib/facets/core/string/each_char.rb, line 5
def each_char # :yield:
split(//).each { |c|
yield( c )
}
end
[edit] Array
[edit] last_index
require 'lib/facets/core/array/last_index'
http://facets.rubyforge.org/src/doc/rdoc/core/classes/Array.html#M000157
Returns the last index of the array. Returns nil is [typo?] array has no elements. [1,2,3,4,5].last_index #=> 4
[edit] Enumerable
http://facets.rubyforge.org/src/doc/rdoc/core/classes/Enumerable.html
[edit]
every
http://facets.rubyforge.org/src/doc/rdoc/core/classes/Enumerable.html#M001236
Returns an elementwise Functor. This allows you to map a method on to every element.
[1,2,3].every + 3 #=> [4,5,6]['a','b','c'].every.upcase #=> ['A','B','C']# File lib/facets/core/enumerable/every.rb, line 13 def every @_functor_every ||= Functor.new do |op,*args| self.collect{ |a| a.send(op,*args) } end end
irb -> require 'facets/core/enumerable/every'
irb -> ['dir1/', 'dir2/'].every + '..'
=> ["dir1/..", "dir2/.."]
irb -> ['dir1/', 'dir2/'].every + 'file'
=> ["dir1/file", "dir2/file"]
irb -> ['Smith', 'Reynolds'].every + ' Mr.'
=> ["Smith Mr.", "Reynolds Mr."]
irb -> class String; def prefix(prefix); prefix + self; end; end
=> nil
irb -> ['Smith', 'Reynolds'].every.prefix 'Mr. '
=> ["Mr. Smith", "Mr. Reynolds"]
# But you may as well just use the built-in map for this:
irb -> ['Smith', 'Reynolds'].map {|a| 'Mr. ' + a}
=> ["Mr. Smith", "Mr. Reynolds"]
[edit] ↓map_send(meth, *args) {|e.send(meth, *args)| ...}
# File lib/facets/core/enumerable/map_send.rb, line 3
def map_send(meth, *args)
if block_given?
map{|e| yield(e.send(meth, *args))}
else
map{|e| e.send(meth, *args)}
end
end
I don't really know when I/you would want to use this method...
irb -> require 'facets/core/enumerable/map_send'
irb -> ['dir1/', 'dir2/'].map_send(:+, 'a') {|a| File.expand_path(a)}
=> ["/home/tyler/dir1/a", "/home/tyler/dir2/a"]
# Sure, but you could have the same thing in an even more readable manner simply using map!:
irb -> ['dir1/', 'dir2/'].map {|a| File.expand_path(a + 'a')}
=> ["/home/tyler/dir1/a", "/home/tyler/dir2/a"]
[edit] each_by(step=nil, &yld)
Iterate through slices. If slicing step is not given, the the arity if the block is used.
x = [] [1,2,3,4].each_by{ |a,b| x << [a,b] } x #=> [ [1,2], [3,4] ] x = [] [1,2,3,4,5,6].each_by(3){ |a| x << a } x #=> [ [1,2,3], [4,5,6] ]
[edit] filter_collect( {|| ...}
Collects/Maps and filters items out in one single step. You can use throw(:skip) in the supplied block to indicate that the current item should not end up in the resulting array.
# Return names of all person with an age of at least 18. persons.filter_collect do |person| throw(:skip) if person.age < 18 person.name end
[edit] none?( {|e| ...}
Enumerable#none? is the logical opposite of the builtin method Enumerable#any?. It returns true if and only if none of the elements in the collection satisfy the predicate.
If no predicate is provided, Enumerable#none? returns true if and only if none of the elements have a true value (i.e. not nil or false).
[edit] uniq_by( {|| ...}
Like uniq, but determines uniqueness based on a given block.
(-5..5).to_a.uniq_by {|i| i*i }produces
[-5, -4, -3, -2, -1, 0]
[edit] Kernel
http://facets.rubyforge.org/src/doc/rdoc/core/classes/Kernel.html
[edit] __self__
Returns a Functor that allows one to call any Kernel or Object method bound to self, making it possible to bypass overrides of Kernel and Object methods.
require 'facets/core/kernel/__self__'
class A
def object_id ; "OBTUSE" ; end
end
c = C.new
c.object_id #=> "OBTUSE"
c.__self__.object_id #=> 6664875832
# File lib/facets/core/kernel/__self__.rb, line 24
def __self__
@__self__ ||= Functor.new do |meth, *args| # &blk|
Object.instance_method(meth).bind(self).call(*args) # ,&blk)
end
end
[edit] as( ancestor, &blk )
Returns a As-functor that allows one to call any ancestor’s method directly of the given object.
class A
def x ; 1 ; end
end
class B < A
def x ; 2 ; end
end
class C < B
def x ; as(A).x ; end
end
C.new.x #=> 1
# File lib/facets/core/kernel/as.rb, line 39
def as( ancestor, &blk )
@__as ||= {}
unless r = @__as[ancestor]
r = (@__as[ancestor] = As.new(self, ancestor))
end
r.instance_eval(&blk) if block_given?
#yield(r) if block_given?
r
end
[edit] with / returning
require 'facets/core/kernel/with' # returning
[edit] new()
Synonymous with clone, this is an interesting method in that it promotes prototype-based Ruby. Now Classes aren’t the only things that respond to new.
"ABC".new => "ABC"
[edit] object_send(name,*args,&blk)

Send only to public methods.
[edit] meta()
http://facets.rubyforge.org/src/doc/rdoc/core/classes/Kernel.html#M001160
Provides access to an object’s metaclass (ie. singleton) bypassing [typo] access provisions. So for example:
class X meta.attr_accesser :a end X.a = 1 X.a #=> 1# File lib/facets/core/kernel/meta.rb, line 15 def meta @_meta_functor ||= Functor.new do |op,*args| (class << self; self; end).send(op,*args) end end
This apparently created an instance variable for the class object X (rather than for instances of X).
Hmm, I'm not sure I trust it very much after observing this weirdness...
> irb
irb -> require 'facets/core/kernel/meta'
=> false
irb -> o = Object.new
=> #<Object:0xb7dd2a68>
irb -> o.class.send(:class_variable_set, :@@v, 'value!')
=> "value!"
irb -> o.class
=> Object
irb -> o.class.send(:class_variable_get, :@@v)
=> "value!"
irb -> o.class.meta.class_variable_set(:@@v, 'new value')
=> "new value"
irb -> o.class.meta.class_variable_get(:@@v)
=> "new value"
irb -> o.class.send(:class_variable_get, :@@v)
=> "new value"
> irb
Welcome!
irb -> require 'facets/core/kernel/meta'
=> true
irb -> o = Object.new
=> #<Object:0xb7e71794>
irb -> o.class.meta.class_variable_set(:@@v, 'value')
=> "value"
irb -> o.class.send(:class_variable_get, :@@v)
NameError: uninitialized class variable @@v in Object
from (irb):4:in `class_variable_get'
from (irb):4:in `send'
from (irb):4
from :0
irb -> o.class.meta.class_variable_get(:@@v)
=> "value"
irb -> o.class.send(:class_variable_set, :@@v, 'new value')
=> "new value"
irb -> o.class.meta.class_variable_get(:@@v)
=> "value"
irb -> o.class.send(:class_variable_get, :@@v)
=> "new value"
[edit] pp_exception(ex)
[edit] set_with(*args) {|| ...}
require 'facets/core/kernel/set_with'
Assign via setter methods using a hash, associative array or block.
object.set_with( :a => 1, :b => 2 ) object.set_with( :a, 1, :b, 2 ) object.set_with( [:a, 1], [:b, 2] ) object.set_with( *[[:a, 1], [:b, 2]] ) object.set_with{ |s| s.a = 1; s.b = 2 }These are all the same as doing:
object.a = 1 object.b = 2This method does not check to make sure the object responds [typo] to the setter method [ambiguous!]. For that see populate (which just adds
rescue nil).
populate( data=nil, &yld )
- Similar [typo] to set_with, but ignores missing setters [rescues errors].
[edit] Misc
Why isn't qua_class simply an alias to meta??
[edit] Object
http://facets.rubyforge.org/src/doc/rdoc/core/classes/Object.html
[edit] Module
http://facets.rubyforge.org/src/doc/rdoc/core/classes/Module.html
[edit] class_extension(&block)
http://facets.rubyforge.org/src/doc/rdoc/core/classes/Module.html#M000510
Normally when including modules, class/module methods are not extended. To achieve this behavior requires some clever Ruby Karate. Instead class_extension provides an easy to use and clean solution. Simply place the extending class methods in a block of the special module method class_extension.
module Mix def inst_meth puts 'inst_meth' end class_extension do def class_meth "Class Method!" end end end class X include Mix end X.class_meth #=> "Class Method!"
require 'facets/core/module/class_extension'
[edit] attr_tester(*args)
Create an "tester" attribute. This creates two methods for each given variable name. One (a?) is used to test the attribute and the other (a!) is used to set or toggle it.
Documentation revision: Add underlined.
[edit]
basename() / dirname()
module Example class Demo end end
Example::Demo.name #=> "Example::Demo" Example::Demo.basename #=> "Demo" Example::Demo.dirname #=> "Example"
[documentation incorrect (category)]: Doesn't work unless Example:: is added.
[edit]
by_name(name)
Note: the following documentation uses "class" because it’s more common, but it applies to modules as well.
Given the name of a class, returns the class itself (i.e. instance of Class). [...]
Examples:
Class.by_name("String") # -> String
Class.by_name("::String") # -> String
Class.by_name("Process::Sys") # -> Process::Sys
Class.by_name("GorillaZ") # -> (ArgumentError)
Class.by_name("Enumerable") # -> Enumerable
Module.by_name("Enumerable") # -> Enumerable
[edit] equate_on(*fields)
Generates identity/key methods based on specified attributes.
equate_on :a, :b
_is equivalent to_
def ==(o) self.a == o.a && self.b == o.b end def eql?(o) self.a.eql?(o.a) && self.b.eql?(o.b) end ...
[edit] include_and_extend(*mods)
Both includes and extends a module.
[edit]
include_as( h )
Include a module via a specified namespace.
module T def t ; "HERE" ; end end
class X include_as :test => T def t ; test.t ; end end
X.new.t #=> "HERE"
[edit]
initializer(*attributes, &block)
Automatically create an initializer assigning the given arguments.
class MyClass initializer(:a, "b", :c) end
_is equivalent to_
class MyClass
def initialize(a, b, c)
@a,@b,@c = a,b,c
end
end
Downside: Initializers defined like this can’t take blocks. This can be fixed when Ruby 1.9 is out. [How?? You can pass multiple blocks in 1.9?????]
The initializer will not raise an Exception when the user does not supply a value for each instance variable. In that case it will just set the instance variable to nil. You can assign default values or raise an Exception in the block.
# File lib/facets/core/module/initializer.rb, line 27
def initializer(*attributes, &block)
define_method(:initialize) do |*args|
attributes.zip(args) do |sym, value|
instance_variable_set("@#{sym}", value)
end
instance_eval(&block) if block
end
end
Why would you want to pass in a block? Here's one reason: to initialize those instance variables that aren't passed in to the constructor/initialize.
initializer :name do
@running_total = 0
@internal_counter = 0
@message = ''
...
end
An alternative to using initializer would be to write your own initialize(*args) but then call set_with(args)...
using block...
[edit] wrap_method( sym, &blk )/code>
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.
# File lib/facets/core/module/wrap_method.rb, line 22 def wrap_method( sym, &blk ) old = instance_method(sym) define_method(sym) { |*args| blk.call(old.bind(self), *args) } end
[edit] instance_methods(*args)
Provides an improved method lookup routine. It returns a list of methods according to symbol(s) given.
Recognized symbols are:
- :public include public methods
- :private include private methods
- :protected include protected methods
- :ancestors include all ancestor’s methods
- :inherited (same as above)
- :local include non-ancestor methods
- :all include all of the above
This method also uses the symbol-not system. So you can specify the inverse of all of the above. For instance ~:public would mean :private, :protected (see facets/core/symbol/not).
If no symbol is given then :public, :local is assumed. Unrecognized symbols raise an error.
module Demo
def test
puts("Hello World!")
end
end
Demo.instance_methods(:local) #=> ['test']
To maintain backward compatibility true as an intitial argument is converted to :local, :ancestors (i.e. it includes both).
==is?(base)
Built-in: obj.is_a?(class)
- Returns true if class is the class of obj, or if class is one of the superclasses of obj or modules included in obj.
Only works for instances
irb -> Y.is_a?(X)
=> false
irb -> Y.new.is_a?(X)
=> true
Facets' is? works for modules/classes as well...
irb -> require 'facets/core/module/is'
=> true
irb -> Y.is?(X)
=> true
[edit] memoize(*meths)
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
[edit]
modspace()
Returns the module’s container module.
module Example class Demo end end
Demo.modspace #=> Example
[edit]
namespace( name, mod=nil, &blk )
require 'facets/core/module/namespace'
Define a simple method namespace.
class A
attr_writer :x
namespace :inside do
def x; @x; end
end
end
a = A.new a.x = 10 a.inside.x #=> 10 a.x # no method error
[edit]
new(*args,&blk)
Lets you "instantiate" a module!
Never use class again! ;)
- File lib/facets/core/module/new.rb, line 6
def new(*args,&blk)
mod = self
klass = Class.new{include mod}
klass.new(*args,&blk)
end
[documentation needs cleanup]: "Never you a class agian!"
[edit] on_included(code)
A useful macro for dynamic modules.
- File lib/facets/core/module/on_included.rb, line 11
def on_included(code)
tag = caller[0].split(' ').first.split(/\/|\\/).last.gsub(/:|\.|\(|\)/, '_')
old = "__included_#{tag}"
module_eval %{
class << self
alias_method :#{old}, :included
def included(base)
#{old}(base)
#{code}
end
end
}
end
[edit]
class_extension(&block)
Normally when including modules, class/module methods are not extended. To achieve this behavior requires some clever Ruby Karate. Instead class_extension provides an easy to use and clean solution. Simply place the extending class methods in a block of the special module method class_extension.
module Mix
def inst_meth
puts 'inst_meth'
end
class_extension do
def class_meth
"Class Method!"
end
end
end
class X include Mix end
X.class_meth #=> "Class Method!"
[edit] Method dependencies
http://facets.rubyforge.org/src/doc/rdoc/more/classes/Module.html
This module is included in Object and allows methods to be given prerequisite dependencies, i.e. methods that must be run before they are.
A dependency will only ever be run once per method call.
include MethodDependency def one; @str << '1'; end def two; @str << '2'; end def show; @str ; end depend :show => [ :one, :two ] show #=> '12'
[documentation incorrect (category)]: depend :show => [ :x, :y ] => depend :show => [ :one, :two ]?
[edit] Module: method aliasing, etc.
[edit]
alias_accessor( name, target )
I finally found an answer to this long-standing question of mine...
If you override attribute my_attr, will it also override my_attr= for you?
alias_method :date_placed, :creation_date
I think the answer is no, you'd need to override that separately:
alias_method :date_placed=, :creation_date=
Is there/should there be another method that does both of these for you?
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
[edit]
alias_method_chain(target, feature)
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.
Also works for methods ending in ? or !. The method aliases keep the same punctuation (for instance, :foo_with_feature?).
[documentation incorrect (category)]:
alias_method :foo?, :foo_without_feature?
should be:
alias_method :foo?, :foo_with_feature?
See also: Ruby / Method aliasing
[edit]
redirect_method( method_hash )
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 Example
redirect_method :hi => :hello, :hey => :hello
def hello(name)
puts "Hello, #{name}."
end
end
e = Example.new
e.hello("Bob") #=> "Hello, Bob."
e.hi("Bob") #=> "Hello, Bob."
e.hey("Bob") #=> "Hello, Bob."
So basically a Hash-based equivalent to alias_method ??
[edit] redefine_method( sym, aka=nil, &blk )
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.hi #=> "Hello!" Greeter.new.hello #=> "Hello, friend!"
[edit] ↓ shadow_method( name, old_name=name )
Define a shadow alias for a method.
class X shadow_method( :class ) end # creates __class__ method
X.new.__class__ #=> X
I'm not sure when I'd ever want to use this. Usually when I create a method_alias, I want to give it a unique prefix based on the functionality I'm about to override it with... See on_included, redefine_method...
[documentation incomplete]
[edit] [Aspect-oriented programming (category)]
Module#prepend( aspect )
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}"
[edit] Typos to fix
Anywhere this appears in rendered RDocs: _is equivalent to_ : change to is equivalent to
lib/facets/core/module/attr.rb
- show [should] always have a reader and a writer.
Do a spell-check.
exclimation
/usr/lib/ruby/gems/1.8/gems/facets-1.8.54/lib/facets/more/nackclass.rb: scaler -> scalar
[edit] Documentation problems to fix
The (nil) documentation in "/usr/lib/ruby/gems/1.8/gems/facets-1.8.54/lib/facets/core/kernel/nack.rb" overwrites the (completel documentation for "/usr/lib/ruby/gems/1.8/gems/facets-1.8.54/lib/facets/more/nackclass.rb"
Two versions of attr_tester: /usr/lib/ruby/gems/1.8/gems/facets-1.8.54/lib/facets/core/module/attr_query.rb, /usr/lib/ruby/gems/1.8/gems/facets-1.8.54/lib/facets/core/module/attr_tester.rb
[edit] See also
...
Change log: http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/240173
Aliases: Ruby Facets, Ruby / Facets
