The Ruby Standard Library

By Tristan Hume

June 24, 2014

Follow Along

http://thume.ca/rubytour

Best Library

Looking it Up

Demo

Part 1: Basic Classes

>> [].methods.length
=> 171
>> ''.methods.length
=> 166
>> 42.methods.length
=> 132
>> [].methods.shuffle.take(7)
=> [:all?, :transpose, :uniq!, :sort!, :shift, :*, :slice]

Symbol#to_proc

>> ['HeLLO', 'oTTAWA', 'RuBy'].map(&:capitalize).join(' ')
=> "Hello Ottawa Ruby"
>> ['HeLLO', 'oTTAWA', 'RuBy'].map {|s| s.capitalize}.join(' ')
=> "Hello Ottawa Ruby"

Loops

>> 4.times {|i| 3.downto(i) {|j| print j, ' '}}
3 2 1 0 3 2 1 3 2 3
>> "Hello World!".split.each do |w|
?>     puts w
>>  end
Hello
World!
=> ["Hello", "World!"]
>> loop { puts "again!" }
again!
...

Benefits

// C for loop
for(int i = 0; i < 3; ++i)
  printf("how many times?");
# Ruby makes the intent clear
3.times { puts "3 times!" }

# Does the same thing but conveys
# the intent to iterate certain numbers
(0..2).each {|i| puts "3 times!"}

The Best Break Around

def twice
  yield
  yield
end

twice do
  puts "hi"
  break
end
#=> hi

Integer.times

int.times {|i| block }  ->  self
int.times               ->  an_enumerator

Iterates the given block int times, passing in values from zero to int - 1.

If no block is given, an Enumerator is returned instead.

5.times do |i|
  print i, " "
end
#=> 0 1 2 3 4
5.times.select {|n| n.even?}.each {|i| print i, ' '}
#=> 0 2 4

Enumerator#with_index

e.with_index(offset = 0) {|(*args), idx| ... }
e.with_index(offset = 0)

Iterates the given block for each element with an index, which starts from offset. If no block is given, returns a new Enumerator that includes the index, starting from offset

offset
the starting index to use
['zero', 'next', 'five!'].each.with_index do |e, i|
  print "#{i}:#{e} "
end
#=> 0:zero 1:next 2:five!

String Manipulation

>> "hello there\n".chomp.capitalize.gsub('there', 'World')
#=> "Hello World"
>> "rofl" * 20
=> "roflroflroflroflroflroflroflroflroflroflroflroflroflroflroflroflroflroflroflrofl"
>> 500.to_s(16)
=> "1f4"
>> "1f4".to_i(16)
=> 500

String#gsub

str.gsub(pattern, replacement)       -> new_str
str.gsub(pattern, hash)              -> new_str
str.gsub(pattern) {|match| block }   -> new_str
str.gsub(pattern)                    -> enumerator

Returns a copy of str with the all occurrences of pattern substituted for the second argument. The pattern is typically a Regexp; if given as a String, any regular expression metacharacters it contains will be interpreted literally, e.g. '\\\d' will match a backlash followed by 'd', instead of a digit.

If replacement is a String it will be substituted for the matched text. It may contain back-references to the pattern's capture groups of the form \\\d, where d is a group number, or \\\k<n>, where n is a group name. If it is a double-quoted string, both back-references must be preceded by an additional backslash. However, within replacement the special match variables, such as $&, will not refer to the current match.

If the second argument is a Hash, and the matched text is one of its keys, the corresponding value is the replacement string.

In the block form, the current match string is passed in as a parameter, and variables such as $1, $2, $``,$&`, and `$'` will be set appropriately. The value returned by the block will be substituted for the match on each call.

The result inherits any tainting in the original string or any supplied replacement string.

When neither a block nor a second argument is supplied, an Enumerator is returned.

"hello".gsub(/[aeiou]/, '*')                  #=> "h*ll*"
"hello".gsub(/([aeiou])/, '<\1>')             #=> "h<e>ll<o>"
"hello".gsub(/./) {|s| s.ord.to_s + ' '}      #=> "104 101 108 108 111 "
"hello".gsub(/(?<foo>[aeiou])/, '{\k<foo>}')  #=> "h{e}ll{o}"
'hello'.gsub(/[eo]/, 'e' => 3, 'o' => '*')    #=> "h3ll*"

=== (Case Equality)

case obj
when /.*/; print "Check if string matches regex"
when Numeric; print "Check if obj inherits from a class"
when 5; print "Defaults to being the same as == for direct comparison."
end

String#scrub

str.scrub -> new_str
str.scrub(repl) -> new_str
str.scrub{|bytes|} -> new_str

If the string is invalid byte sequence then replace invalid bytes with given replacement character, else returns self. If block is given, replace invalid bytes with returned value of the block.

"abc\u3042\x81".scrub #=> "abc\u3042\uFFFD"
"abc\u3042\x81".scrub("*") #=> "abc\u3042*"
"abc\u3042\xE3\x80".scrub{|bytes| '<'+bytes.unpack('H*')[0]+'>' } #=> "abc\u3042<e380>"

String#ljust

str.ljust(integer, padstr=' ')   -> new_str

If integer is greater than the length of str, returns a new String of length integer with str left justified and padded with padstr; otherwise, returns str.

"hello".ljust(4)            #=> "hello"
"hello".ljust(20)           #=> "hello               "
"hello".ljust(20, '1234')   #=> "hello123412341234123"
# More fancy padding methods
"hello".rjust(20)           #=> "               hello"
"hello".center(20)          #=> "       hello        "

IO.read

IO.read(name, [length [, offset]] )   -> string
IO.read(name, [length [, offset]], open_args)   -> string

Opens the file, optionally seeks to the given offset, then returns length bytes (defaulting to the rest of the file). read ensures the file is closed before returning.

If the last argument is a hash, it specifies option for internal open(). The key would be the following. open_args: is exclusive to others.

encoding
string or encoding
specifies encoding of the read string.  `encoding` will be ignored if
length is specified.
mode
string
specifies mode argument for open().  It should start with "r" otherwise it
will cause an error.
open_args
array of strings
specifies arguments for open() as an array.

Examples:

IO.read("testfile")           #=> "This is line one\nThis is line two\nThis is line three\nAnd so on...\n"
IO.read("testfile", 20)       #=> "This is line one\nThi"
IO.read("testfile", 20, 10)   #=> "ne one\nThis is line "
ios.read([length [, outbuf]])    -> string, outbuf, or nil

Reads length bytes from the I/O stream.

length must be a non-negative integer or nil.

If length is a positive integer, it try to read length bytes without any conversion (binary mode). It returns nil or a string whose length is 1 to length bytes. nil means it met EOF at beginning. The 1 to length-1 bytes string means it met EOF after reading the result. The length bytes string means it doesn't meet EOF. The resulted string is always ASCII-8BIT encoding.

If length is omitted or is nil, it reads until EOF and the encoding conversion is applied. It returns a string even if EOF is met at beginning.

If length is zero, it returns "".

If the optional outbuf argument is present, it must reference a String, which will receive the data. The outbuf will contain only the received data after the method call even if it is not empty at the beginning.

At end of file, it returns nil or "" depend on length. ios*.read() and ios*.read(nil) returns "". *ios*.read(*positive-integer*) returns nil.

f = File.new("testfile")
f.read(16)   #=> "This is line one"
# reads whole file
open("file") {|f|
  data = f.read # This returns a string even if the file is empty.
  ...
}
# iterate over fixed length records.
open("fixed-record-file") {|f|
  while record = f.read(256)
    ...
  end
}
# iterate over variable length records.
# record is prefixed by 32-bit length.
open("variable-record-file") {|f|
  while len = f.read(4)
    len = len.unpack("N")[0] # 32-bit length
    record = f.read(len) # This returns a string even if len is 0.
  end
}

Note that this method behaves like fread() function in C. This means it retry to invoke read(2) system call to read data with the specified length (or until EOF). This behavior is preserved even if ios is non-blocking mode. (This method is non-blocking flag insensitive as other methods.) If you need the behavior like single read(2) system call, consider readpartial, read_nonblock and sysread.

Dir.glob

Dir.glob( pattern, [flags] ) -> matches
Dir.glob( pattern, [flags] ) { |filename| block }  -> nil

Expands pattern, which is an Array of patterns or a pattern String, and returns the results as matches or as arguments given to the block.

Note that this pattern is not a regexp, it's closer to a shell glob. See File::fnmatch for the meaning of the flags parameter. Note that case sensitivity depends on your system (so File::FNM_CASEFOLD is ignored), as does the order in which the results are returned.

*
Matches any file. Can be restricted by other values in the glob.
Equivalent to `/ .* /x` in regexp.
`*`

: Matches all files

`c*`

: Matches all files beginning with c

`*c`

: Matches all files ending with c

`*c*`

: Match all files that have c in them (including at the beginning or

    end).
Note, this will not match Unix-like hidden files (dotfiles).  In order to
include those in the match results, you must use the File::FNM_DOTMATCH
flag or something like `"{*,.*}"`.
**

Matches directories recursively.

?

Matches any one character. Equivalent to /.{1}/ in regexp.

[set]
Matches any one character in set. Behaves exactly like character sets
in Regexp, including set negation (`[^a-z]`).
{p,q}
Matches either literal p or literal q. Equivalent to pattern
alternation in regexp.
Matching literals may be more than one character in length.  More than two
literals may be specified.
\\
Escapes the next metacharacter.
Note that this means you cannot use backslash on windows as part of a
glob, i.e.  `Dir["c:\\foo*"]` will not work, use `Dir["c:/foo*"]` instead.

Examples:

Dir["config.?"]                     #=> ["config.h"]
Dir.glob("config.?")                #=> ["config.h"]
Dir.glob("*.[a-z][a-z]")            #=> ["main.rb"]
Dir.glob("*.[^r]*")                 #=> ["config.h"]
Dir.glob("*.{rb,h}")                #=> ["main.rb", "config.h"]
Dir.glob("*")                       #=> ["config.h", "main.rb"]
Dir.glob("*", File::FNM_DOTMATCH)   #=> [".", "..", "config.h", "main.rb"]
rbfiles = File.join("**", "*.rb")
Dir.glob(rbfiles)                   #=> ["main.rb",
                                    #    "lib/song.rb",
                                    #    "lib/song/karaoke.rb"]
libdirs = File.join("**", "lib")
Dir.glob(libdirs)                   #=> ["lib"]
librbfiles = File.join("**", "lib", "**", "*.rb")
Dir.glob(librbfiles)                #=> ["lib/song.rb",
                                    #    "lib/song/karaoke.rb"]
librbfiles = File.join("**", "lib", "*.rb")
Dir.glob(librbfiles)                #=> ["lib/song.rb"]

Example

# Dir[] is an alias of Dir.glob()
Dir['*.md'].each do |f|
  lines = IO.read(f).count("\n")
  puts "#{f}: #{lines}"
end
#=> notes.md: 52
#=> presentation.md: 164
#=> tour.md: 112

Time

>> Time.now
=> 2014-06-20 18:35:53 -0400
>> Time.now.tuesday?
=> true
>> require 'time'
>> Time.parse('6:00')
=> 2014-06-20 06:00:00 -0400

Time#parse

parse(date, now=self.now) { |year| ... }

Parses date using Date._parse and converts it to a Time object.

If a block is given, the year described in date is converted by the block. For example:

Time.parse(...) {|y| 0 <= y && y < 100 ? (y >= 69 ? y + 1900 : y + 2000) : y}

If the upper components of the given time are broken or missing, they are supplied with those of now. For the lower components, the minimum values (1 or 0) are assumed if broken or missing. For example:

# Suppose it is "Thu Nov 29 14:33:20 GMT 2001" now and
# your time zone is GMT:
now = Time.parse("Thu Nov 29 14:33:20 GMT 2001")
Time.parse("16:30", now)     #=> 2001-11-29 16:30:00 +0900
Time.parse("7/23", now)      #=> 2001-07-23 00:00:00 +0900
Time.parse("Aug 31", now)    #=> 2001-08-31 00:00:00 +0900
Time.parse("Aug 2000", now)  #=> 2000-08-01 00:00:00 +0900

Since there are numerous conflicts among locally defined time zone abbreviations all over the world, this method is not intended to understand all of them. For example, the abbreviation "CST" is used variously as:

-06:00 in America/Chicago,
-05:00 in America/Havana,
+08:00 in Asia/Harbin,
+09:30 in Australia/Darwin,
+10:30 in Australia/Adelaide,
etc.

Based on this fact, this method only understands the time zone abbreviations described in RFC 822 and the system time zone, in the order named. (i.e. a definition in RFC 822 overrides the system time zone definition.) The system time zone is taken from Time.local(year, 1, 1).zone and Time.local(year, 7, 1).zone. If the extracted time zone abbreviation does not match any of them, it is ignored and the given time is regarded as a local time.

ArgumentError is raised if Date._parse cannot extract information from date or if the Time class cannot represent specified date.

This method can be used as a fail-safe for other parsing methods as:

Time.rfc2822(date) rescue Time.parse(date)
Time.httpdate(date) rescue Time.parse(date)
Time.xmlschema(date) rescue Time.parse(date)

A failure of Time.parse should be checked, though.

You must require 'time' to use this method.

Enumerable Mastery

find_all the ways you can become a ruby ninja, select the right ones, collect them in your mind, and then be lazy and don't actually do anything.

# Finds most common starting letter in English
File.open('/usr/share/dict/words','r').map(&:downcase)
  .chunk(&:ord).map {|c, l| [c.chr, l.length]}
  .sort_by(&:last).take(3)  # => ["s", 25162]

Enumerable.map

enum.map     { |obj| block } -> array
enum.map                     -> an_enumerator

Returns a new array with the results of running block once for every element in enum.

If no block is given, an enumerator is returned instead.

(1..4).map { |i| i*i }      #=> [1, 4, 9, 16]
(1..4).collect { "cat"  }   #=> ["cat", "cat", "cat", "cat"]

Enumerable.reduce

enum.reduce(initial, sym) -> obj
enum.reduce(sym)          -> obj
enum.reduce(initial) { |memo, obj| block }  -> obj
enum.reduce          { |memo, obj| block }  -> obj

Combines all elements of enum by applying a binary operation, specified by a block or a symbol that names a method or operator.

If you specify a block, then for each element in enum the block is passed an accumulator value (memo) and the element. If you specify a symbol instead, then each element in the collection will be passed to the named method of memo. In either case, the result becomes the new value for memo. At the end of the iteration, the final value of memo is the return value for the method.

If you do not explicitly specify an initial value for memo, then the first element of collection is used as the initial value of memo.

# Sum some numbers
(5..10).reduce(:+)                             #=> 45
# Same using a block and inject
(5..10).inject { |sum, n| sum + n }            #=> 45
# Multiply some numbers
(5..10).reduce(1, :*)                          #=> 151200
# Same using a block
(5..10).inject(1) { |product, n| product * n } #=> 151200
# find the longest word
longest = %w{ cat sheep bear }.inject do |memo, word|
   memo.length > word.length ? memo : word
end
longest                                        #=> "sheep"

Enumerable.select

enum.select   { |obj| block } -> array
enum.select                   -> an_enumerator

Returns an array containing all elements of enum for which the given block returns a true value.

If no block is given, an Enumerator is returned instead.

(1..10).find_all { |i|  i % 3 == 0 }   #=> [3, 6, 9]
[1,2,3,4,5].select { |num|  num.even?  }   #=> [2, 4]

See also Enumerable#reject.

[1,2,3,4,5].reject { |num|  num.even?  } #=> [1, 3, 5]

Enumerable.all?

enum.all? [{ |obj| block } ]   -> true or false

Passes each element of the collection to the given block. The method returns true if the block never returns false or nil. If the block is not given, Ruby adds an implicit block of { |obj| obj } which will cause #all? to return true when none of the collection members are false or nil.

%w[ant bear cat].all? { |word| word.length >= 3 } #=> true
%w[ant bear cat].all? { |word| word.length >= 4 } #=> false
[nil, true, 99].all?                              #=> false
# any? also exists
%w[ant bear cat].any? { |word| word.length >= 4 } #=> true

Maxes and Mins

>> [5, 7].max
=> 7

>> a = 10.times.map { rand(10) }
=> [4, 1, 0, 5, 5, 2, 3, 7, 6, 0]
>> a.max
=> 7
>> a.min
=> 0
>> a.minmax
=> [0, 7]
>> a.max_by {|n| n % 4}
=> 3

Enumerable.grep

enum.grep(pattern)                  -> array
enum.grep(pattern) { |obj| block }  -> array

Returns an array of every element in enum for which Pattern === element. If the optional block is supplied, each matching element is passed to it, and the block's result is stored in the output array.

(1..100).grep 38..44   #=> [38, 39, 40, 41, 42, 43, 44]
c = IO.constants
c.grep(/SEEK/)         #=> [:SEEK_SET, :SEEK_CUR, :SEEK_END]
res = c.grep(/SEEK/) { |v| IO.const_get(v) }
res                    #=> [0, 1, 2]

Enumerable.lazy

e.lazy -> lazy_enumerator

Returns a lazy enumerator, whose methods map/collect, flat_map/collect_concat, select/find_all, reject, grep, zip, take, take_while, drop, and drop_while enumerate values only on an as-needed basis. However, if a block is given to zip, values are enumerated immediately.

Example

The following program finds pythagorean triples:

def pythagorean_triples
  (1..Float::INFINITY).lazy.flat_map {|z|
    (1..z).flat_map {|x|
      (x..z).select {|y|
        x**2 + y**2 == z**2
      }.map {|y|
        [x, y, z]
      }
    }
  }
end
# show first ten pythagorean triples
p pythagorean_triples.take(10).force # take is lazy, so force is needed
p pythagorean_triples.first(10)      # first is eager
# show pythagorean triples less than 100
p pythagorean_triples.take_while { |*, z| z < 100 }.force

Array#flatten

ary.flatten -> new_ary
ary.flatten(level) -> new_ary

Returns a new array that is a one-dimensional flattening of self (recursively).

That is, for every element that is an array, extract its elements into the new array.

The optional level argument determines the level of recursion to flatten.

s = [ 1, 2, 3 ]           #=> [1, 2, 3]
t = [ 4, 5, 6, [7, 8] ]   #=> [4, 5, 6, [7, 8]]
a = [ s, t, 9, 10 ]       #=> [[1, 2, 3], [4, 5, 6, [7, 8]], 9, 10]
a.flatten                 #=> [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
a = [ 1, 2, [3, [4, 5] ] ]
a.flatten(1)              #=> [1, 2, 3, [4, 5]]

Array#transpose

ary.transpose -> new_ary

Assumes that self is an array of arrays and transposes the rows and columns.

a = [[1,2], [3,4], [5,6]]
a.transpose   #=> [[1, 3, 5], [2, 4, 6]]

If the length of the subarrays don't match, an IndexError is raised.

Extra Tools

All of Them (Favourites Bolded)

abbrev base64 benchmark bigdecimal cgi cmath coverage csv date dbm debug delegate digest dl drb e2mmap English erb etc expect extmk fcntl fiddle fileutils find forwardable gdbm getoptlong gserver io/console io/nonblock io/wait ipaddr json ologger mathn matrix minitest minitest/benchmark minitest/spec mkmf monitor mutex_m net/ftp net/http net/imap net/pop net/smtp net/telnet nkf objspace observer open-uri open3 openssl optparse ostruct pathname pp prettyprint prime profile profiler pstore psych pty racc racc/parser rake rdoc readline resolv rexml rinda ripper rss scanf sdbm securerandom set shell shellwords singleton socket stringio strscan sync syslog tempfile test/unit thwait time timeout tk tmpdir tracer tsort uri weakref webrick win32ole xmlrpc yaml zlib

PP (Pretty Print)

>> require 'pp'
>> a = Array.new(5) { Array.new(5, 42) }
=> [[42, 42, 42, 42, 42], [42, 42, 42, 42, 42], [42, 42, 42, 42, 42], [42, 42, 42, 42, 42], [42, 42, 42, 42, 42]]
>> pp a
[[42, 42, 42, 42, 42],
 [42, 42, 42, 42, 42],
 [42, 42, 42, 42, 42],
 [42, 42, 42, 42, 42],
 [42, 42, 42, 42, 42]]
>> pp PP.new
#<PP:0x007fbb6c8047b8
 @buffer=[],
 @buffer_width=0,
 @genspace=
  #<Proc:0x007fbb6c804678@/usr/local/Cellar/ruby/2.1.2_1/lib/ruby/2.1.0/prettyprint.rb:84 (lambda)>,
 @group_queue=
  #<PrettyPrint::GroupQueue:0x007fbb6c804420
   @queue=
    [[#<PrettyPrint::Group:0x007fbb6c8044e8
       @break=false,
       @breakables=[],
       @depth=0>]]>,
 @group_stack=
  [#<PrettyPrint::Group:0x007fbb6c8044e8
    @break=false,
    @breakables=[],
    @depth=0>],
 @indent=0,
 @maxwidth=79,
 @newline="\n",
 @output="",
 @output_width=0>

Internet Support!

Testing, Optimizing, Debugging

DEBUGGER__ < Object

This library provides debugging functionality to Ruby.

To add a debugger to your code, start by requiring debug in your program:

def say(word)
  require 'debug'
  puts word
end

This will cause Ruby to interrupt execution and show a prompt when the say method is run.

Once you're inside the prompt, you can start debugging your program.

(rdb:1) p word
"hello"

Getting help

You can get help at any time by pressing h.

(rdb:1) h
Debugger help v.-0.002b
Commands
  b[reak] [file:|class:]<line|method>
  b[reak] [class.]<line|method>
                             set breakpoint to some position
  wat[ch] <expression>       set watchpoint to some expression
  cat[ch] (<exception>|off)  set catchpoint to an exception
  b[reak]                    list breakpoints
  cat[ch]                    show catchpoint
  del[ete][ nnn]             delete some or all breakpoints
  disp[lay] <expression>     add expression into display expression list
  undisp[lay][ nnn]          delete one particular or all display expressions
  c[ont]                     run until program ends or hit breakpoint
  s[tep][ nnn]               step (into methods) one line or till line nnn
  n[ext][ nnn]               go over one line or till line nnn
  w[here]                    display frames
  f[rame]                    alias for where
  l[ist][ (-|nn-mm)]         list program, - lists backwards
                             nn-mm lists given lines
  up[ nn]                    move to higher frame
  down[ nn]                  move to lower frame
  fin[ish]                   return to outer frame
  tr[ace] (on|off)           set trace mode of current thread
  tr[ace] (on|off) all       set trace mode of all threads
  q[uit]                     exit from debugger
  v[ar] g[lobal]             show global variables
  v[ar] l[ocal]              show local variables
  v[ar] i[nstance] <object>  show instance variables of object
  v[ar] c[onst] <object>     show constants of object
  m[ethod] i[nstance] <obj>  show methods of object
  m[ethod] <class|module>    show instance methods of class or module
  th[read] l[ist]            list all threads
  th[read] c[ur[rent]]       show current thread
  th[read] [sw[itch]] <nnn>  switch thread context to nnn
  th[read] stop <nnn>        stop thread nnn
  th[read] resume <nnn>      resume thread nnn
  p expression               evaluate expression and print its value
  h[elp]                     print this help
  <everything else>          evaluate

Usage

The following is a list of common functionalities that the debugger provides.

In general, a debugger is used to find bugs in your program, which often means pausing execution and inspecting variables at some point in time.

Let's look at an example:

def my_method(foo)
  require 'debug'
  foo = get_foo if foo.nil?
  raise if foo.nil?
end

When you run this program, the debugger will kick in just before the foo assignment.

(rdb:1) p foo
nil

In this example, it'd be interesting to move to the next line and inspect the value of foo again. You can do that by pressing n:

(rdb:1) n # goes to next line
(rdb:1) p foo
nil

You now know that the original value of foo was nil, and that it still was nil after calling get_foo.

Other useful commands for navigating through your code are:

c
Runs the program until it either exists or encounters another breakpoint.
You usually press `c` when you are finished debugging your program and
want to resume its execution.
s
Steps into method definition. In the previous example, s would take you
inside the method definition of `get_foo`.
r
Restart the program.
q
Quit the program.

Inspecting variables

You can use the debugger to easily inspect both local and global variables. We've seen how to inspect local variables before:

(rdb:1) p my_arg
42

You can also pretty print the result of variables or expressions:

(rdb:1) pp %w{a very long long array containing many words}
["a",
 "very",
 "long",
 ...
]

You can list all local variables with +v l+:

(rdb:1) v l
  foo => "hello"

Similarly, you can show all global variables with +v g+:

(rdb:1) v g
  all global variables

Finally, you can omit p if you simply want to evaluate a variable or expression

(rdb:1) 5**2
25

Going beyond basics

Ruby Debug provides more advanced functionalities like switching between threads, setting breakpoints and watch expressions, and more. The full list of commands is available at any time by pressing h.

Staying out of trouble

Make sure you remove every instance of +require 'debug'+ before shipping your code. Failing to do so may result in your program hanging unpredictably.

Debug is not available in safe mode. ## Instance methods:

break_points
context
debug_thread_info
display
get_thread
interrupt
make_thread_list
resume
set_last_thread
set_trace
stdout
stdout=
suspend
thread_list
thread_list_all
waiting

YAML

YAML Ain't Markup Language

This module provides a Ruby interface for data serialization in YAML format.

The underlying implementation is the libyaml wrapper Psych.

Usage

Working with YAML can be very simple, for example:

require 'yaml' # STEP ONE, REQUIRE YAML!
# Parse a YAML string
YAML.load("--- foo") #=> "foo"
# Emit some YAML
YAML.dump("foo")     # => "--- foo\n...\n"
{ :a => 'b'}.to_yaml  # => "---\n:a: b\n"

Security

Do not use YAML to load untrusted data. Doing so is unsafe and could allow malicious input to execute arbitrary code inside your application. Please see doc/security.rdoc for more information.

History

Syck was the original for YAML implementation in Ruby's standard library developed by why the lucky stiff.

You can still use Syck, if you prefer, for parsing and emitting YAML, but you must install the 'syck' gem now in order to use it.

In older Ruby versions, ie. <= 1.9, Syck is still provided, however it was completely removed with the release of Ruby 2.0.0.

More info

For more advanced details on the implementation see Psych, and also check out http://yaml.org for spec details and other helpful information.

Other Parsers

RDoc::Markdown < Object

RDoc::Markdown as described by the markdown syntax. To choose Markdown as your only default format see RDoc::Options@Saved+Options for instructions on setting up a .doc_options file to store your project default. ### Usage Here is a brief example of using this parse to read a markdown file by hand.

data = File.read("README.md")
formatter = RDoc::Markup::ToHtml.new(RDoc::Options.new, nil)
html = RDoc::Markdown.parse(data).accept(@formatter)
# do something with html

Extensions

The following markdown extensions are supported by the parser, but not all are used in RDoc output by default. #### RDoc The RDoc Markdown parser has the following built-in behaviors that cannot be disabled. Underscores embedded in words are never interpreted as emphasis. (While the markdown dingus emphasizes in-word underscores, neither the Markdown syntax nor MarkdownTest mention this behavior.) For HTML output, RDoc always auto-links bare URLs. #### Break on Newline The break_on_newline extension converts all newlines into hard line breaks as in Github Flavored Markdown. This extension is disabled by default. #### CSS The #css extension enables CSS blocks to be included in the output, but they are not used for any built-in RDoc output format. This extension is disabled by default. Example:

<style type="text/css">
h1 { font-size: 3em }
</style>

Definition Lists

The definition_lists extension allows definition lists using the PHP Markdown Extra syntax, but only one label and definition are supported at this time. This extension is enabled by default. Example:

cat

: A small furry mammal that seems to sleep a lot

ant
A little insect that is known

to enjoy picnics

Produces: cat : A small furry mammal that seems to sleep a lot ant : A little insect that is known to enjoy picnics

Github

The #github extension enables a partial set of Github Flavored Markdown. This extension is enabled by default. Supported github extensions include: ##### Fenced code blocks Use `around a block of code instead of indenting it four spaces. ##### Syntax highlighting Use rubyas the start of a code fence to add syntax highlighting. (Currently onlyruby` syntax is supported). #### HTML Enables raw HTML to be included in the output. This extension is enabled by default. Example:

<table>
...
</table>

Notes

The #notes extension enables footnote support. This extension is enabled by default. Example:

Here is some text[^1] including an inline footnote ^[for short footnotes]
...
[^1]: With the footnote text down at the bottom

Produces: Here is some text[^1] including an inline footnote [^2] ### Limitations * Link titles are not used * Footnotes are collapsed into a single paragraph

Author

This markdown parser is a port to kpeg from peg-markdown by John MacFarlane. It is used under the MIT license: Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. The port to kpeg was performed by Eric Hodel and Evan Phoenix [^1]: With the footnote text down at the bottom [^2]: for short footnotes ## Constants:

DEFAULT_EXTENSIONS
Extensions enabled by default
EXTENSIONS
Supported extensions
HTML_ENTITIES
HTML entity name map for RDoc::Markdown

Pathname < Object

Pathname represents the name of a file or directory on the filesystem, but not the file itself.

The pathname depends on the Operating System: Unix, Windows, etc. This library works with pathnames of local OS, however non-Unix pathnames are supported experimentally.

A Pathname can be relative or absolute. It's not until you try to reference the file that it even matters whether the file exists or not.

Pathname is immutable. It has no method for destructive update.

The goal of this class is to manipulate file path information in a neater way than standard Ruby provides. The examples below demonstrate the difference.

All functionality from File, FileTest, and some from Dir and FileUtils is included, in an unsurprising way. It is essentially a facade for all of these, and more.

Examples

Example 1: Using Pathname

require 'pathname'
pn = Pathname.new("/usr/bin/ruby")
size = pn.size              # 27662
isdir = pn.directory?       # false
dir  = pn.dirname           # Pathname:/usr/bin
base = pn.basename          # Pathname:ruby
dir, base = pn.split        # [Pathname:/usr/bin, Pathname:ruby]
data = pn.read
pn.open { |f| _ }
pn.each_line { |line| _ }

Example 2: Using standard Ruby

pn = "/usr/bin/ruby"
size = File.size(pn)        # 27662
isdir = File.directory?(pn) # false
dir  = File.dirname(pn)     # "/usr/bin"
base = File.basename(pn)    # "ruby"
dir, base = File.split(pn)  # ["/usr/bin", "ruby"]
data = File.read(pn)
File.open(pn) { |f| _ }
File.foreach(pn) { |line| _ }

Example 3: Special features

p1 = Pathname.new("/usr/lib")   # Pathname:/usr/lib
p2 = p1 + "ruby/1.8"            # Pathname:/usr/lib/ruby/1.8
p3 = p1.parent                  # Pathname:/usr
p4 = p2.relative_path_from(p3)  # Pathname:lib/ruby/1.8
pwd = Pathname.pwd              # Pathname:/home/gavin
pwd.absolute?                   # true
p5 = Pathname.new "."           # Pathname:.
p5 = p5 + "music/../articles"   # Pathname:music/../articles
p5.cleanpath                    # Pathname:articles
p5.realpath                     # Pathname:/home/gavin/articles
p5.children                     # [Pathname:/home/gavin/articles/linux, ...]

Breakdown of functionality

Core methods

These methods are effectively manipulating a String, because that's all a path is. None of these access the file system except for #mountpoint?, #children, #each_child, #realdirpath and #realpath.

File status predicate methods

These methods are a facade for FileTest: * #blockdev? * #chardev? * #directory? * #executable? * #executable_real? * #exist? * #file? * #grpowned? * #owned? * #pipe? * #readable? * #world_readable? * #readable_real? * #setgid? * #setuid? * #size * #size? * #socket? * #sticky? * #symlink? * #writable? * #world_writable? * #writable_real? * #zero?

File property and manipulation methods

These methods are a facade for File: * #atime * #ctime * #mtime * #chmod(mode) * #lchmod(mode) * #chown(owner, group) * #lchown(owner, group) * #fnmatch(pattern, args) #fnmatch?(pattern, args) #ftype * #make_link(old) * #open(args, &block) #readlink * #rename(to) * #stat * #lstat * #make_symlink(old) * #truncate(length) * #utime(atime, mtime) * #basename(args) #dirname * #extname * #expand_path(args) #split

Directory methods

These methods are a facade for Dir: * Pathname.glob(args) Pathname.getwd / Pathname.pwd * #rmdir * #entries * #each_entry(&block) * #mkdir(args) #opendir(*args)

IO

These methods are a facade for IO: * #each_line(args, &block) #read(args) #binread(args) #readlines(args) #sysopen(*args)

Utilities

These methods are a mixture of Find, FileUtils, and others: * #find(&block) * #mkpath * #rmtree * #unlink / #delete

Method documentation

As the above section shows, most of the methods in Pathname are facades. The documentation for these methods generally just says, for instance, "See FileTest.writable?", as you should be familiar with the original method anyway, and its documentation (e.g. through ri) will contain more information. In some cases, a brief description will follow.

OpenStruct < Object

OpenStruct serialization/deserialization

An OpenStruct is a data structure, similar to a Hash, that allows the definition of arbitrary attributes with their accompanying values. This is accomplished by using Ruby's metaprogramming to define methods on the class itself.

Examples:

require 'ostruct'
person = OpenStruct.new
person.name    = "John Smith"
person.age     = 70
person.pension = 300
puts person.name     # -> "John Smith"
puts person.age      # -> 70
puts person.address  # -> nil

An OpenStruct employs a Hash internally to store the methods and values and can even be initialized with one:

australia = OpenStruct.new(:country => "Australia", :population => 20_000_000)
p australia   # -> <OpenStruct country="Australia" population=20000000>

Hash keys with spaces or characters that would normally not be able to use for method calls (e.g. ()[]*) will not be immediately available on the OpenStruct object as a method for retrieval or assignment, but can be still be reached through the Object#send method.

measurements = OpenStruct.new("length (in inches)" => 24)
measurements.send("length (in inches)")  # -> 24
data_point = OpenStruct.new(:queued? => true)
data_point.queued?                       # -> true
data_point.send("queued?=",false)
data_point.queued?                       # -> false

Removing the presence of a method requires the execution the delete_field method as setting the property value to nil will not remove the method.

first_pet = OpenStruct.new(:name => 'Rowdy', :owner => 'John Smith')
first_pet.owner = nil
second_pet = OpenStruct.new(:name => 'Rowdy')
first_pet == second_pet   # -> false
first_pet.delete_field(:owner)
first_pet == second_pet   # -> true

Implementation:

An OpenStruct utilizes Ruby's method lookup structure to find and define the necessary methods for properties. This is accomplished through the method method_missing and define_method.

This should be a consideration if there is a concern about the performance of the objects that are created, as there is much more overhead in the setting of these properties compared to using a Hash or a Struct.

Tk

Ruby's built in GUI library. Not suitable for fancy things but great for simple little programs.

require 'tk'

root = TkRoot.new { title "Hello, World!" }
TkLabel.new(root) do
   text 'Hello, World!'
   pack { padx 15 ; pady 15; side 'left' }
end
Tk.mainloop

Win32OLE

You are no longer allowed to even think about using Visual Basic.

require 'win32ole'

excel = WIN32OLE.new('Excel.Application')
excel.visible = true
workbook = excel.Workbooks.Add();
worksheet = workbook.Worksheets(1);
worksheet.Range("A1:D1").value = ["North","South","East","West"];
worksheet.Range("A2:B2").value = [5.2, 10];
worksheet.Range("C2").value = 8;
worksheet.Range("D2").value = 20;

range = worksheet.Range("A1:D2");
range.select
chart = workbook.Charts.Add;

workbook.saved = true;

excel.ActiveWorkbook.Close(0);
excel.Quit();

Mathn

mathn changes the way Ruby does math to be more precise, Rational and lispy.

# Without mathn:
3 / 2 => 1 # Integer
20 / 9 * 3 * 14 / 7 * 3 / 2 # => 18

# With mathn:
require 'mathn'
3 / 2 => 3/2 # Rational
20 / 9 * 3 * 14 / 7 * 3 / 2 # => 20

mathn features late rounding and lacks truncation of intermediate results.

Prime < Object

Includes:

Enumerable ## Extended by:

OldCompatibility
Forwardable

The set of all prime numbers.

Example

Prime.each(100) do |prime|
  p prime  #=> 2, 3, 5, 7, 11, ...., 97
end

Prime is Enumerable:

Prime.first 5 # => [2, 3, 5, 7, 11]

Retrieving the instance

Prime.new is obsolete. Now Prime has the default instance and you can access it as Prime.instance.

For convenience, each instance method of Prime.instance can be accessed as a class method of Prime.

e.g.

Prime.instance.prime?(2)  #=> true
Prime.prime?(2)           #=> true

Generators

A "generator" provides an implementation of enumerating pseudo-prime numbers and it remembers the position of enumeration and upper bound. Furthermore, it is an external iterator of prime enumeration which is compatible with an Enumerator.

Prime::PseudoPrimeGenerator is the base class for generators. There are few implementations of generator.

Prime::EratosthenesGenerator
Uses eratosthenes' sieve.
Prime::TrialDivisionGenerator
Uses the trial division method.
Prime::Generator23
Generates all positive integers which are not divisible by either 2 or 3.
This sequence is very bad as a pseudo-prime sequence. But this is faster
and uses much less memory than the other generators. So, it is suitable
for factorizing an integer which is not large but has many prime factors.
e.g. for Prime#prime? .

The End

Learn to use the Standard Library, it's pretty cool.