Programming Ruby: The Pragmatic Programmer's Guide

# Programming Ruby ### The Pragmatic Programmer's Guide
Previous < | Contents ^ | Next >

# Standard Library

Ruby comes ``out of the box'' with a large and useful library of modules and classes. This chapter contains a sampling of the more useful of these.

Interestingly, and unlike some of the code in later chapters, all of these libraries are written in Ruby. You'll find the source in the `lib` subdirectory of the standard Ruby distribution.

class Complex |
Parent: | Numeric
Version: | 1.6

### Index:

new Arithmetic operations <=> == abs abs2 arg conjugate image polar real to_f to_i to_r to_s

`require "complex"`
``
`v1 = Complex(2,3)` | » | `Complex(2, 3)`
`v2 = 2.im` | » | `Complex(0, 2)`
`v1 + v2` | » | `Complex(2, 5)`
`v1 * v2` | » | `Complex(-6, 4)`
`v2**2` | » | `Complex(-4, 0)`
`Math.sin(v1)` | » | `Complex(9.154499147, -4.16890696)`
`v1 < v2` | » | `false`
`v2**2 == -4` | » | `true`

constants

`Complex::I` |  | 0 +1i

class methods
new | Complex.new( a, b ) -> aComplex
|  | Returns a + bi.

In addition to the `Complex.new` constructor, the `Complex` library defines the method `Numeric.im` , such that aNumeric `.im` returns 0 + aNumeric i. Complex numbers are also constructed using the global method `Complex`, which takes one or two arguments. The value it returns depends on the type of its arguments:

a | b | Result
Number | Number | a + bi
Complex | 0 | a
Complex | Complex | `Complex( a.real - b.image, a.image + b.real )`
Number | Complex | `Complex( a - b.image, b.real )`

instance methods
Arithmetic operations |
|  | Performs various arithmetic operations on ref.
ref | + | aNumeric -> aComplex | Addition
ref | - | aNumeric -> aComplex | Subtraction
ref | * | aNumeric -> aComplex | Multiplication
ref | / | aNumeric -> aComplex | Division
ref | % | aNumeric -> aComplex | Remainder
ref | ** | aNumeric -> aComplex | Exponentiation (real and complex power)
<=> | ref <=> other -> -1, 0, +1
|  | Returns ref.abs `<=>` other.abs.
== | ref == anObject -> `true` or `false`
|  | If anObject is a complex number, returns `true` if its real and imaginary parts match ref. If anObject is a simple number, returns `true` if ref.`real` equals anObject and ref.`image` is zero. Otherwise, attempts to coerce anObject to a complex number and compares the result.
abs | ref.abs -> aFloat
|  | Absolute value.
abs2 | ref.abs2 -> aFloat
|  | Square of absolute value.
arg | ref.arg -> aFloat
|  | Argument (angle from (1,0)).
conjugate | ref.conjugate -> aComplex
|  | Complex conjugate.
image | ref.image -> aNumeric
|  | The imaginary part of ref.
polar | ref.polar -> anArray
|  | Returns the two-element array: [c.abs, c.arg].
real | ref.real -> aNumeric
|  | The real part of ref.
to_f | ref.to_f -> aComplex
|  | Returns `Complex(real.to_f, image.to_f)`.
to_i | ref.to_i -> aComplex
|  | Returns `Complex(real.to_i, image.to_i)`.
to_r | ref.to_r -> aComplex
|  | Returns `Complex(real.to_r, image.to_r)`, converting both parts of the complex to a rational number.
to_s | ref.to_s -> aString
|  | String representation of ref.

In addition, the `Math` functions `sqrt`, `exp`, `cos`, `sin`, `tan`, `log`, `log10`, and `atan2` are extended to support a `Complex` argument.

class Date |
Parent: | Object
Version: | 1.6

### Index:

exist2? exist? existw? gregorian_leap? julian_leap? leap? new new1 new2 new3 neww today Accessors + -- << <=> === >> downto england gregorian italy jd julian leap? mjd newsg next ns? os? sg step succ to_s upto

`require 'date'`
``
`d = Date.new(2000, 3, 31)` | » | `#<Date: 2451635,2299161>`
`[d.year, d.yday, d.wday]` | » | `[2000, 91, 5]`
`[d.month, d.mday]` | » | `[3, 31]`
`[d.cwyear, d.cweek, d.cwday]` | » | `[2000, 13, 5]`
`[d.jd, d.mjd]` | » | `[2451635, 51634.5]`
`(d << 1).to_s` | » | `"2000-02-29"`
`d.succ.to_s` | » | `"2000-04-01"`
`(d + 100).to_s` | » | `"2000-07-09"`
`d.leap?` | » | `true`
`Date.new(2000, 3, -10).to_s` | » | `"2000-03-22"`
`d1 = Date.neww(2000, 13, 7)` | » | `#<Date: 2451637,2299161>`
`d1.to_s` | » | `"2000-04-02"`
`[d1.cwday, d1.wday]` | » | `[7, 0]`

The `date` library implements class `Date`, which provides a comprehensive set of facilities for storing, manipulating, and converting dates. To document its options, we need to take a brief historical detour to establish some vocabulary.

Internally a date is stored as a Julian day number, the number of days since midday, January 1st, 4713 BCE.[In the code, you may find references to the year -4712. As astronomical dates include a year zero, 4713 BCE is the same year as -4712.] The rules for converting a Julian day number to a calendar date are complicated because the Romans estimated the length of a year incorrectly. In the Julian calendar (often called Old Style, or O.S.), every year divisible by 4 is a leap year. The `Date` class has options to convert dates using this as an assumption.

By the sixteenth century, the inaccuracies in this measurement had become apparent. An edict from Pope Gregory XIII in 1582 created the New Style (N.S.) or Gregorian calendar, where years divisible by 100 were no longer leap years unless they were also divisible by 400. This system was adopted by most Catholic countries immediately, but religious differences held up a wider adoption. England (and several other countries) switched in 1752, with some countries following later. The `Date` class allows you to determine whether to implement the cutover in 1582 (the `Date::ITALY` option), 1752 (`Date::ENGLAND`), or another date of your choosing.

The `Date` class also provides conversions to Modified Julian Day (MJD) numbers. MJD values count from midnight, November 17, 1858. Because these values count from midnight, not midday, there is a half-day added to the conversion factor.

The descriptions that follow use the abbreviations listed in Table 24.1 on page 441.

Abbreviations used describing dates
Field | Meaning
cwday | An ISO 8601 calendar weekday. 1 is Monday, 7 is Sunday.
cweek | An ISO 8601 calendar week. Week 1 is the week containing the first Thursday (or equivalently the week that contains January 4th).
cwyear | An ISO 8601 calendar-week-based year. May be different from year, as it rolls forward only on a Monday.
jd | The Julian day number---the number of days since January 1st, 4713 BCE.
mday | The day of the month (1..31).
mjd | A modified Julian day number.
mon | The month of the year (1..12).
sg | The start of the Gregorian correction: `Date::ITALY` (the default) for 1582, `Date::ENGLAND` for 1752, or `JULIAN`, meaning no correction. You may also provide an arbitrary Julian day number for this parameter, in which case the correction will start from this date.
wday | The day of the week (0 is Sunday).
week | The week number into a year (1..53).
yday | The day into the year (1..366).
year | A year (1966, 2001, and the like).

Class `Date` exports the constant arrays `Date::MONTHNAMES` and `Date::DAYNAMES`, which can be indexed by mon and wday values to return the corresponding English names.

The `Date` class also provides low-level date-conversion methods:

* `civil_to_jd` | * `jd_to_civil`
* `commercial_to_jd` | * `jd_to_commercial`
* `ordinal_to_jd` | * `jd_to_ordinal`
* `jd_to_mjd` | * `mjd_to_jd`

These methods perform limited error checking of their parameters, and are not documented here. The somewhat confusingly named `exist..?` routines perform conversions from different formats into a Julian day number with error checking. These routines also automatically normalize their parameters.

mixins
Comparable: | <, <=, ==, >=, >, between?

class methods
exist2? | Date.exist2?( year, yday, sg=`Date::ITALY`) -> jd
|  | Converts a year and yday into a Julian day number, returning `nil` on error.
exist? | Date.exist?( year, mon, mday, sg=`Date::ITALY`) -> jd
|  | Converts a year, mon, and mday into a Julian day number, or `nil` if the parameters are invalid.
existw? | Date.existw?( cyear, cweek, cwday, sg=`Date::ITALY`) -> jd
|  | Converts a cyear, cweek, and cwday into a Julian day number.
gregorian_leap? | Date.gregorian_leap?( year ) -> `true` or `false`
|  | If year does not end with ``00'', returns `true` if year is divisible by 4, otherwise returns `true` if year is divisible by 400.
julian_leap? | Date.julian_leap?( year ) -> `true` or `false`
|  | Returns `true` if year is divisible by 4.
leap? | Date.leap?( year ) -> `true` or `false`
|  | Synonym for `Date.gregorian_leap?`.
new | Date.new( year=-4712, mon=1, mday=1, sg=`Date::ITALY`) -> aNewDate
|  | Returns a `Date` for the given year, mon, and mday. If mon is negative, it counts back from the end of the year. If mday is negative, it counts back from the end of the month.
new1 | Date.new1( jd, sg=`Date::ITALY`) -> aNewDate
|  | Creates a `Date` corresponding to the given Julian day number.
new2 | Date.new2( year=-4712, yday=1, sg=`Date::ITALY`) -> aNewDate
|  | Returns a `Date` for the given year and yday. If yday is negative, it counts back from the end of the year.
new3 | Date.new3( year=-4712, mon=1, mday=1, sg=`Date::ITALY`) -> aNewDate
|  | Synonym for `Date.new`.
neww | Date.neww( cyear=1582, cweek=41, cwday=5, sg=`Date::ITALY`) -> aNewDate
|  | Returns a `Date` for the given cyear, cweek, and cwday. If cweek is negative, it counts back from the end of the year. If cwday is negative, it counts back from the end of the week.
today | Date.today( sg=`Date::ITALY`) -> aNewDate
|  | Returns a `Date` for today.

instance methods
Accessors | ref.year -> year ref.yday -> yday ref.mjd -> mjd ref.mon -> mon ref.month -> mon ref.mday -> mday ref.day -> mday ref.cwyear -> cwyear ref.cweek -> cweek ref.cwday -> cwday ref.wday -> wday
|  | Returns the given component of ref as a number.
+ | ref + anInteger -> aNewDate
|  | Returns a new `Date` anInteger days from ref.
-- | ref `-` anInteger -> aNewDate ref `-` anOtherDate -> anInteger
|  | The first form returns a new `Date` anInteger days before ref. The second form returns the number of days between ref and anOtherDate.
<< | ref << anInteger -> aNewDate
|  | Returns a new `Date` formed by subtracting anInteger months to ref, adjusting the mday value back to the last day of the month if it otherwise exceeds it.
<=> | ref <=> anOther -> -1, 0, +1
|  | anOther must be a `Numeric`, in which case it is treated as a Julian day number, or a `Date`. Returns -1, 0, +1 if ref is less than, equal to, or greater than anOther. See module `Comparable` on page 402.
=== | ref === anOther -> `true` or `false`
|  | anOther must be a `Numeric`, in which case it is treated as a Julian day number, or a `Date`. Returns `true` if the Julian day number of anOther is the same as ref.
>> | ref >> anInteger -> aNewDate
|  | Returns a new `Date` formed by adding anInteger months to ref, adjusting the mday value back to the last day of the month if it otherwise exceeds it.
downto | ref.downto( aDateMin ) {| date | block } -> ref
|  | Invokes block with dates from ref down to aDateMin.
england | ref.england -> aDate
|  | Equivalent to ref `.newsg(Date::ENGLAND)`.
gregorian | ref.gregorian -> aDate
|  | Equivalent to ref `.newsg(Date::GREGORIAN)`.
italy | ref.italy -> aDate
|  | Equivalent to ref `.newsg(Date::ITALY)`.
jd | ref.jd -> jd
|  | Returns the Julian day number for ref.
julian | ref.julian -> aDate
|  | Equivalent to ref `.newsg(Date::JULIAN)`.
leap? | ref.leap? -> `true` or `false`
|  | Returns `true` if ref falls within a leap year.
mjd | ref.mjd -> mjd
|  | Returns the Julian day number of ref converted to a modified Julian day number.
newsg | ref.newsg( sg=`Date::ITALY` ) -> aNewDate
|  | Returns a new `Date`.
next | ref.next -> aNewDate
|  | Synonym for ref.succ.
ns? | ref.ns? -> `true` or `false`
|  | Returns `true` if ref falls in the period of New Style dates.
os? | ref.os? -> `true` or `false`
|  | Returns `true` if ref falls in the period of Old Style dates.
sg | ref.sg -> anInteger
|  | Returns the Julian day number of the start of New Style dates for ref.
step | ref.step( aDateLimit, step ) {| date | block } -> ref
|  | Invokes block with dates starting at ref, incrementing by step days, ending at the first date greater than aDateLimit (less than for a negative step).
succ | ref.succ -> aNewDate
|  | Returns the date of ref plus one day.
to_s | ref.to_s -> aString
|  | Returns `self` as ``year-mon-mday.''
upto | ref.upto( aDateMax ) {| date | block } -> ref
|  | Invokes block with dates from ref to aDateMax.

Library: English

    require "English"

    $OUTPUT_FIELD_SEPARATOR = ' -- '
    "waterbuffalo" =~ /buff/
    print $LOADED_FEATURES, $POSTMATCH, $PID, "\n"
    print $", $', $$, "\n"

produces:

    English.rb -- alo -- 19685 --
    English.rb -- alo -- 19685 --

Include the English library file in a Ruby script, and you can reference the global variables such as `$_` using less cryptic names, listed in the following table.

`$*` | $ARGV | `$"` | $LOADED_FEATURES
`$?` | $CHILD_STATUS | `$&` | $MATCH
`$<` | $DEFAULT_INPUT | `$.` | $NR
`$>` | $DEFAULT_OUTPUT | `$,` | $OFS
`$!` | $ERROR_INFO | `$\` | $ORS
`$@` | $ERROR_POSITION | `$\` | $OUTPUT_RECORD_SEPARATOR
`$;` | $FIELD_SEPARATOR | `$,` | $OUTPUT_FIELD_SEPARATOR
`$;` | $FS | `$$` | $PID
`$=` | $IGNORECASE | `$'` | $POSTMATCH
`$.` | $INPUT_LINE_NUMBER | `$`` | $PREMATCH
`$/` | $INPUT_RECORD_SEPARATOR | `$$` | $PROCESS_ID
`$~` | $LAST_MATCH_INFO | `$0` | $PROGRAM_NAME
`$+` | $LAST_PAREN_MATCH | `$/` | $RS
`$_` | $LAST_READ_LINE

module Find

### Index:

find prune

    require "find"
    Find.find("/etc/passwd", "/var/spool/lp1", ".") do |f|
      Find.prune if f == "."
      puts f
    end

produces:

    /etc/passwd
    /var/spool/lp1
    /var/spool/lp1/status
    /var/spool/lp1/lock
    /var/spool/lp1/.seq

The `Find` module supports the top-down traversal of a set of file paths.

class methods
find | ref.find( [ aName ]* ) {| aFileName | block }
|  | Calls the associated block with the name of every file and directory listed as arguments, then recursively on their subdirectories, and so on.
prune | ref.prune
|  | Skips the current file or directory, restarting the loop with the next entry. If the current file is a directory, that directory will not be recursively entered. Meaningful only within the block associated with `Find::find`.

class File |
Parent: | IO
Version: | 1.6

### Index:

cmp compare copy cp install makedirs mkpath move mv rm_f safe_unlink syscopy

`require 'ftools'`
``
`File.copy 'testfile', 'testfile1'` | » | `true`
`File.compare 'testfile', 'testfile1'` | » | `true`

The `FTools` library adds several methods to the built-in `File` class. These methods are particularly useful to programs that move and copy files, such as installers.

class methods
cmp | ref.cmp( name1, name2, verbose=`false` ) -> `true` or `false`
|  | Synonym for `File.compare` .
compare | ref.compare( name1, name2, verbose=`false` ) -> `true` or `false`
|  | Returns `true` only if the contents of files name1 and name2 are identical.
copy | ref.copy( fromName, toName, verbose=`false` ) -> `true` or `false`
|  | Equivalent to calling `File.syscopy` , but logs the attempt to `$stderr` if verbose is not `false`.
cp | ref.cp( fromName, toName, verbose=`false` ) -> `true` or `false`
|  | Synonym for `File.copy` .
install | ref.install( fromName, toName, aMode=`nil`, verbose=`false` )
|  | Copies file fromName to file toName using `File.syscopy` , unless toName already exists and has the same content as fromName. Sets the mode of the resulting file to aMode unless aMode is `nil`.
makedirs | ref.makedirs( [ dirName ]* [, aBoolean ] )
|  | Creates the given directories, logging each attempt to `$stderr` if the last parameter is `true`. Creates any missing parent directories as required.
mkpath | ref.mkpath( [ dirName ]* [, aBoolean ] )
|  | Synonym for `File.makedirs` .
move | ref.move( fromName, toName, verbose=`false` ) -> `true` or `false`
|  | Effectively renames fromName to toName, logging to `$stderr` if verbose is not `false`.
mv | ref.mv( fromName, toName, verbose=`false` ) -> `true` or `false`
|  | Synonym for `File.move` .
rm_f | ref.rm_f( [ fileName ]* [, aBoolean ] ) -> anInteger
|  | Synonym for `File.safe_unlink` (the name refers to the Unix `rm -f` command).
safe_unlink | ref.safe_unlink( [ fileName ]* [, aBoolean ] ) -> anInteger or `nil`
|  | Unlinks (deletes) the given files, logging to `$stderr` if the last parameter is `true`. The method attempts to make all files writable before unlinking them, so no errors will occur deleting read-only files. Returns the number of files deleted, or `nil` on error.
syscopy | ref.syscopy( fromName, toName ) -> `true` or `false`
|  | Efficiently copies the file named fromName to toName. If toName names a directory, the destination will be a file in that directory with the same basename as fromName. After the copy, the file mode of toName will be the same as that of fromName. Returns `true` on success.

class GetoptLong |
Parent: | Object
Version: | 1.6

### Index:

new each error? error_message get get_option ordering ordering= quiet quiet= quiet? set_options terminate terminated?

    # Call using "ruby example.rb --size 10k -v -q a.txt b.doc"

    require 'getoptlong'

    # specify the options we accept and initialize
    # the option parser

    opts = GetoptLong.new(
      [ "--size",    "-s",            GetoptLong::REQUIRED_ARGUMENT ],
      [ "--verbose", "-v",            GetoptLong::NO_ARGUMENT ],
      [ "--query",   "-q",            GetoptLong::NO_ARGUMENT ],
      [ "--check",   "--valid", "-c", GetoptLong::NO_ARGUMENT ]
    )

    # process the parsed options

    opts.each do |opt, arg|
      puts "Option: #{opt}, arg #{arg.inspect}"
    end

    puts "Remaining args: #{ARGV.join(', ')}"

produces:

    Option: --size, arg "10k"
    Option: --verbose, arg ""
    Option: --query, arg ""
    Remaining args: a.txt, b.doc

Class `GetoptLong` supports GNU-style command-line option parsing. Options may be a minus sign (`-') followed by a single character, or two minus signs (`--') followed by a name (a long option). Long options may be abbreviated to their shortest unambiguous lengths.

A single internal option may have multiple external representations. For example, the option to control verbose output could be any of `-v`, `--verbose`, or `--details`. Some options may also take an associated value.

Each internal option is passed to `GetoptLong` as an array, containing strings representing the option's external forms and a flag. The flag (`NO_ARGUMENT`, `REQUIRED_ARGUMENT`, or `OPTIONAL_ARGUMENT`) specifies how `GetoptLong` is to associate an argument with the option.

If the environment variable `POSIXLY_CORRECT` is set, all options must precede nonoptions on the command line. Otherwise, the default behavior of `GetoptLong` is to reorganize the command line to put the options at the front. This behavior may be changed by setting `GetoptLong#ordering=` to one of the constants `PERMUTE`, `REQUIRE_ORDER`, or `RETURN_IN_ORDER`. `POSIXLY_CORRECT` may not be overridden.

constants

Per-option constants

`NO_ARGUMENT` |  | Flags an option that takes no argument.

`OPTIONAL_ARGUMENT` |  | A nonoption following this option will be used as this option's argument.

`REQUIRED_ARGUMENT` |  | This option must be followed by an argument.

Overall constants

`PERMUTE` |  | Options and their arguments will be shuffled to the front of the command line.

`REQUIRE_ORDER` |  | Options and their arguments must appear at the start of the command line. The first nonoption terminates option processing.

`RETURN_IN_ORDER` |  | Return options in the order in which they occur on the command line.

class methods
new | GetoptLong.new( [ options ]* ) -> ref
|  | Returns a new option parser. Any options are passed to ref.`set_options`.

instance methods
each | ref.each {| anOption, anArgument | block }
|  | Loops calling `GetoptLong#get`, passing the returned option and argument to the associated block. The loop ends when `get` returns `nil` for anOption.
error? | ref.error? -> anException
|  | Returns an `Exception` object documenting any error that has occurred, or `nil` if there has not been an error.
error_message | ref.error_message -> aString
|  | Returns the text of the last error message.
get | ref.get -> [ anOption, anArgument ]
|  | Returns the next option, along with any associated argument. If there is no argument, `nil` is returned for anArgument. If there are no remaining unprocessed options, or if there is an error in option processing and `quiet` has been set, `nil` is returned for anOption. Otherwise, if there is an error, a message is written to `$stderr` and an exception (a subclass of `StandardError`) is raised. The option string returned is the first option that was given in the corresponding array passed to `set_options`.
get_option | ref.get_option -> [ anOption, anArgument ]
|  | Synonym for `GetoptLong#get`.
ordering | ref.ordering -> aFixnum
|  | Returns the current ordering.
ordering= | ref.ordering = aFixnum
|  | Sets the ordering to one of `PERMUTE`, `REQUIRE_ORDER`, or `RETURN_IN_ORDER`. Quietly ignored if the environment variable `POSIXLY_CORRECT` is set. Ordering may not be changed once option processing has been started.
quiet | ref.quiet -> `true` or `false`
|  | Returns the current value of the `quiet` attribute.
quiet= | ref.quiet = `true` or `false`
|  | Sets the current value of the `quiet` attribute. If `false`, any errors encountered are reported to `$stderr`.
quiet? | ref.quiet? -> `true` or `false`
|  | Synonym for `GetoptLong#quiet`.
set_options | ref.set_options( [ anOptArray ]* ) -> ref
|  | Each parameter is an array specifying a single internal option. The array contains one or more strings specifying the external form(s) of the option, and one of the flags `NO_ARGUMENT`, `OPTIONAL_ARGUMENT`, or `REQUIRED_ARGUMENT`. See the sample code on page 448 for examples of use.
terminate | ref.terminate -> ref
|  | Terminates option processing. Any remaining arguments are written back to `ARGV`. This may be called from within a `GetoptLong#each` or on its own. For example, calling the following program using ```ruby example.rb --size 10k -v -term -q a.txt b.doc`'' will leave the `-q` and filenames in `ARGV`.

    require 'getoptlong'

    opts = GetoptLong.new(
      [ "--size",    "-s",            GetoptLong::REQUIRED_ARGUMENT ],
      [ "--verbose", "-v",            GetoptLong::NO_ARGUMENT ],
      [ "--term",    "-t",            GetoptLong::NO_ARGUMENT ],
      [ "--query",   "-q",            GetoptLong::NO_ARGUMENT ],
      [ "--check",   "--valid", "-c", GetoptLong::NO_ARGUMENT ]
      )

    opts.each do |opt, arg|
      puts "Option: #{opt}, arg #{arg.inspect}"
      opts.terminate if (opt == '--term')
    end

    puts "Remaining args: #{ARGV.join(', ')}"
produces:
    Option: --size, arg "10k"
    Option: --verbose, arg ""
    Option: --term, arg ""
    Remaining args: -q, a.txt, b.doc
terminated? | ref.terminated? -> `true` or `false`
|  | Returns `true` if option processing has been terminated.

module mkmf

### Index:

create_makefile dir_config find_library have_func have_header have_library

The `mkmf` library is used by Ruby extension modules to help create `Makefiles`. When writing an extension, you create a program named ```extconf.rb`'', which may be as simple as:

    require 'mkmf'
    create_makefile("Test")

When run, this script will produce a `Makefile` suited to the target platform. `mkmf` contains several methods you can use to find libraries and include files and to set compiler flags.

For more information on creating extension modules, see Chapter 17, which begins on page 169.

constants

`PLATFORM` | varies | A constant string that describes the platform on which Ruby is running, such as ``mswin32'' or ``i686-linux.''

`$CFLAGS` |  | Global variable for compiler flags.

`$LDFLAGS` |  | Global variable for linker flags.

instance methods
create_makefile | create_makefile( target )
|  | Creates a `Makefile` for an extension named target. If this method is not called, no `Makefile` is created.
dir_config | dir_config( name )
|  | Looks for directory configuration options for name given as arguments to this program or to the original build of Ruby. These arguments may be one of:
`--with-` name `-dir`=directory
`--with-` name `-include`=directory
`--with-` name `-lib`=directory
The given directories will be added to the appropriate search paths (include or link) in the `Makefile`.
find_library | find_library( name, function, [ path ]+ ) -> `true` or `false`
|  | Same as `have_library`, but will also search in the given directory paths.
have_func | have_func( function ) -> `true` or `false`
|  | If the named function exists in the standard compile environment, adds the directive -DHAVE_FUNCTION to the compile command in the `Makefile` and returns `true`.
have_header | have_header( header ) -> `true` or `false`
|  | If the given header file can be found in the standard search path, adds the directive -DHAVE_HEADER to the compile command in the `Makefile` and returns `true`.
have_library | have_library( library, function ) -> `true` or `false`
|  | If the given function exists in the named library, which must exist in the standard search path or in a directory added with `dir_config`, adds the library to the link command in the `Makefile` and returns `true`.

module ParseDate

### Index:

parsedate

The `ParseDate` module defines a single method, `ParseDate::parsedate`, which converts a date and/or time string into its constituents. It uses heuristics that handle a wide variety of date and time formats, including a subset of ISO 8601, Unix `ctime`, and most common written variants. The following table shows some examples.

StringGuess? | yy | mm | dd | hh | min | sec | zone | wd
1999-09-05 23:55:21+0900 | F | 1999 | 9 | 5 | 23 | 55 | 21 | +0900 | --
1983-12-25 | F | 1983 | 12 | 25 | -- | -- | -- | -- | --
1965-11-10 T13:45 | F | 1965 | 11 | 10 | 13 | 45 | -- | -- | --
10/9/75 1:30pm | F | 75 | 10 | 9 | 13 | 30 | -- | -- | --
10/9/75 1:30pm | T | 1975 | 10 | 9 | 13 | 30 | -- | -- | --
Mon Feb 28 17:15:49 CST 2000 | F | 2000 | 2 | 28 | 17 | 15 | 49 | CST | 1
Tue, 02-Mar-99 11:20:32 GMT | F | 99 | 3 | 2 | 11 | 20 | 32 | GMT | 2
Tue, 02-Mar-99 11:20:32 GMT | T | 1999 | 3 | 2 | 11 | 20 | 32 | GMT | 2
12-January-1990, 04:00 WET | F | 1990 | 1 | 12 | 4 | 0 | -- | WET | --
4/3/99 | F | 99 | 4 | 3 | -- | -- | -- | -- | --
4/3/99 | T | 1999 | 4 | 3 | -- | -- | -- | -- | --
10th February, 1976 | F | 1976 | 2 | 10 | -- | -- | -- | -- | --
March 1st, 84 | T | 1984 | 3 | 1 | -- | -- | -- | -- | --
Friday | F | -- | -- | -- | -- | -- | -- | -- | 5

class methods
parsedate | ref.parsedate( aString, guessYear=`false` ) -> [ year, mon, mday, hour, min, sec, zone, wday ]
|  | Parses a string containing a date and/or a time, returning an array of `Fixnum` objects containing the various components. `nil` is returned for fields that cannot be parsed from aString. If the result contains a year that is less than 100 and guessYear is true, `parsedate` will return a year value equal to year plus 2000 if year is less than 69, year plus 1900 otherwise.

Library: profile

The `profile` library prints to `$stderr` a summary of the number of calls to, and the time spent in, each method in a Ruby program. The output is sorted by the total time spent in each method. Profiling can be enabled from the command line using the `-r` `profile` option, or from within a source program by requiring the `profile` module.

    require 'profile'
    def ackerman(m, n)
      if m == 0 then  n+1
      elsif n == 0 and m > 0 then ackerman(m-1, 1)
      else ackerman(m-1, ackerman(m, n-1))
      end
    end
    ackerman(3,3)

produces:

     time   seconds   seconds    calls  ms/call  ms/call  name
     74.04     2.51      2.51     2432     1.03    42.68  Object#ackerman
     14.16     2.99      0.48     3676     0.13     0.13  Fixnum#==
      9.14     3.30      0.31     2431     0.13     0.13  Fixnum#-
      2.36     3.38      0.08     1188     0.07     0.07  Fixnum#+
      0.29     3.39      0.01       57     0.18     0.18  Fixnum#>
      0.00     3.39      0.00        1     0.00     0.00  Module#method_added
      0.00     3.39      0.00        1     0.00  3390.00  #toplevel

class PStore |
Parent: | Object
Version: | 1.6

### Index:

new [ ] [ ]= abort commit path root? roots transaction

The `PStore` class provides transactional, file-based persistent storage of Ruby objects. The following example stores two hierarchies in a PStore. The first, identified by the key ```names`'', is an array of Strings. The second, identified by ```tree`'', is a simple binary tree.

    require "pstore"

    class T
      def initialize(val, left=nil, right=nil)
        @val, @left, @right = val, left, right
      end
      def to_a
        [ @val, @left.to_a, @right.to_a ]
      end
    end

    store = PStore.new("/tmp/store")
    store.transaction do
       store['names'] = [ 'Douglas', 'Barenberg', 'Meyer' ]
       store['tree']  = T.new('top',
                          T.new('A', T.new('B')),
                          T.new('C', T.new('D', nil, T.new('E'))))
    end

    # now read it back in

    store.transaction do
       puts "Roots: #{store.roots.join(', ')}"
       puts store['names'].join(', ')
       puts store['tree'].to_a.inspect
    end

produces:

    Roots: names, tree
    Douglas, Barenberg, Meyer
    ["top", ["A", ["B", [], []], []], ["C", ["D", [], ["E", [], []]], []]]

Each `PStore` can store several object hierarchies. Each hierarchy has a root, identified by a key (often a string). At the start of a `PStore` transaction, these hierarchies are read from a disk file and made available to the Ruby program. At the end of the transaction, the hierarchies are written back to the file. Any changes made to objects in these hierarchies are therefore saved on disk, to be read at the start of the next transaction that uses that file.

In normal use, a `PStore` object is created and then is used one or more times to control a transaction. Within the body of the transaction, any object hierarchies that had previously been saved are made available, and any changes to object hierarchies, and any new hierarchies, are written back to the file at the end.

class methods
new | PStore.new( aFilename ) -> aPStore
|  | Returns a new `PStore` object associated with the given file. If the file exists, its contents must have been previously written by `PStore`.

instance methods
[ ] | ref[ anObject ] -> anOtherObject
|  | Root Access---Returns the root of an object hierarchy identified by anObject. An exception is raised if anObject does not identify a root.
[ ]= | ref[ anObject ] = anOtherObject -> anOtherObject
|  | Root Creation---Sets anOtherObject as the base of the object hierarchy to be identified using anObject.
abort | ref.abort
|  | Terminates this transaction, losing any changes made to the object hierarchies.
commit | ref.commit
|  | Terminates the current transaction, saving the object hierarchies into the store's file.
path | ref.path -> aString
|  | Returns the name of the file associated with this store.
root? | ref.root?( anObject ) -> `true` or `false`
|  | Returns `true` if anObject is the key of a root in this store.
roots | ref.roots -> anArray
|  | Returns an array containing the keys of the root objects available in this store.
transaction | ref.transaction {| ref | block } -> anObject
|  | If the file associated with ref exists, reads in the object hierarchies from it. It then executes the associated block, passing in ref. The block may use this parameter to access the roots of the hierarchies and hence access the persistent objects. If the block calls `PStore#abort`, or if it raises an exception, no data is saved back to the associated file. Otherwise, if it invokes `PStore#commit`, or if it terminates normally, the object hierarchies are written back to the file. The value returned is the value returned by the block.

class Tempfile |
Parent: | [IO]
Version: | 1.6

### Index:

new close open path

`require "tempfile"`
``
`tf = Tempfile.new("afile")`
`tf.path` | » | `"/tmp/afile19701.0"`
`tf.puts("Cosi Fan Tutte")` | » | `nil`
`tf.close` | » | `nil`
`tf.open` | » | `#<File:0x40195040>`
`tf.gets` | » | `"Cosi Fan Tutte\n"`
`tf.close(true)` | » | `#<File:0x40195040>`

Class `Tempfile` creates managed temporary files. Although they behave the same as any other `IO` objects, temporary files are automatically deleted when the Ruby program terminates. Once a `Tempfile` object has been created, the underlying file may be opened and closed a number of times in succession.

`Tempfile` does not directly inherit from `IO`. Instead, it delegates calls to a `File` object. From the programmer's perspective, apart from the unusual `new`, `open,` and `close` semantics, a `Tempfile` object behaves as if it were an `IO` object.

class methods
new | Tempfile.new( basename, tmpdir=<see below> ) -> ref
|  | Constructs a temporary file in the given directory. The file name is built by concatenating basename, the current process id and (as an extension) a unique sequence number. If the tmpdir parameter is not supplied, it defaults to the value of one of the environment variables `TMPDIR`, `TMP`, or `TEMP`, or to the directory `/tmp`. The file is then opened using mode ``w+'', which allows reading and writing and deletes any existing content (see Table 22.5 on page 326).

open Tempfile.open( basename, tmpdir ) -> ref

Synonym for `Tempfile.new`.

instance methods
close | ref.close( final=`false` )
|  | Closes ref. If final is `true`, deletes the underlying real file. If final is `false`, ref may be subsequently reopened. In all cases, the underlying file is deleted when the program terminates.
open | ref.open
|  | Reopens ref using mode ``r+'', which allows reading and writing but does not delete existing content.
path | ref.path -> aString
|  | Returns the full path of the underlying file.

class Mutex |
Parent: | Object
Version: | 1.6

### Index:

lock locked? synchronize try_lock unlock

    require 'thread'
    sema4 = Mutex.new

    a = Thread.new {
      sema4.synchronize {
        # access shared resource
      }
    }

    b = Thread.new {
      sema4.synchronize {
        # access shared resource
      }
    }

`Mutex` implements a simple semaphore that can be used to coordinate access to shared data from multiple concurrent threads.

instance methods
lock | ref.lock -> ref
|  | Attempts to grab the lock and waits if it isn't available.
locked? | ref.locked? -> `true` or `false`
|  | Returns `true` if this lock is currently held by some thread.
synchronize | ref.synchronize { block } -> ref
|  | Obtains a lock (using `Mutex#lock`), runs the block, and releases the lock when the block completes.
try_lock | ref.try_lock -> `true` or `false`
|  | Attempts to obtain the lock and returns immediately. Returns `true` if the lock was granted.
unlock | ref.unlock -> ref or `nil`
|  | Releases the lock. Returns `nil` if ref wasn't locked.

class ConditionVariable |
Parent: | Object
Version: | 1.6

### Index:

broadcast signal wait

    require 'thread'
    mutex = Mutex.new
    resource = ConditionVariable.new

    a = Thread.new {
      mutex.synchronize {
        # Thread 'a' now needs the resource
        resource.wait(mutex)
        # 'a' can now have the resource
      }
    }

    b = Thread.new {
      mutex.synchronize {
        # Thread 'b' has finished using the resource
        resource.signal
      }
    }

`ConditionVariable` objects augment class `Mutex`. Using condition variables, it is possible to suspend while in the middle of a critical section until a resource becomes available (see the discussion on page 117).

instance methods
broadcast | ref.broadcast
|  | Wakes up all threads waiting for this lock.
signal | ref.signal
|  | Wakes up the first thread in line waiting for this lock.
wait | ref.wait( aMutex ) -> aMutex
|  | Releases the lock held in aMutex and waits; reacquires the lock on wakeup.

Library: timeout

    require "timeout"

    for snooze in 1..2
      puts "About to sleep for #{snooze}"
      timeout(1.5) do
        sleep(snooze)
      end
      puts "That was refreshing"
    end

produces:

    About to sleep for 1
    That was refreshing
    About to sleep for 2
    /tc/usr/lib/ruby/1.6/timeout.rb:37: execution expired (TimeoutError)
    	from prog.rb:5:in `timeout'
    	from prog.rb:5
    	from prog.rb:3:in `each'
    	from prog.rb:3

The `timeout` method takes a single parameter, representing a timeout period in seconds, and a block. The block is executed, and a timer is run concurrently. If the block terminates before the timeout, `timeout` returns `true`. Otherwise, a `TimeoutError` exception is raised.

class WeakRef |
Parent: | Delegator
Version: | 1.6

### Index:

new weakref_alive?

    require "weakref"

    ref = "fol de rol"
    puts "Initial object is #{ref}"
    ref = WeakRef.new(ref)
    puts "Weak reference is #{ref}"
    ObjectSpace.garbage_collect
    puts "But then it is #{ref}"

produces:

    Initial object is fol de rol
    Weak reference is fol de rol
    prog.rb:8: Illegal Reference - probably recycled (WeakRef::RefError)

In Ruby, objects are not eligible for garbage collection if there are still references to them. Normally, this is a Good Thing---it would be disconcerting to have an object simply evaporate while you were using it. However, sometimes you may need more flexibility. For example, you might want to implement an in-memory cache of commonly used file contents. As you read more files, the cache grows. At some point, you may run low on memory. The garbage collector will be invoked, but the objects in the cache are all referenced by the cache data structures, and so will not be deleted.

A weak reference behaves exactly as any normal object reference with one important exception---the referenced object may be garbage collected, even while references to it exist. In the cache example, if the cached files were accessed using weak references, once memory runs low they will be garbage collected, freeing memory for the rest of the application.

Weak references introduce a slight complexity. As the object referenced can be deleted by garbage collection at any time, code that accesses these objects must take care to ensure that the references are valid. Two techniques can be used. First, the code can reference the objects normally. Any attempt to reference an object that has been garbage collected will raise a `WeakRef::RefError` exception.

An alternative approach is to use the `WeakRef#weakref_alive?` method to check that a reference is valid before using it. Garbage collection must be disabled during the test and subsequent reference to the object. In a single-threaded program, you could use something like:

    ref = WeakRef.new(someObject)
    #
    # .. some time later
    #

    gcWasDisabled = GC.disable
    if ref.weakref_alive?
      # do stuff with 'ref'
    end
    GC.enable unless gcWasDisabled

class methods
new | WeakRef.new( anObject ) -> ref
|  | Creates and returns a weak reference to anObject. All future references to anObject should be made using ref.

instance methods
weakref_alive? | ref.weakref_alive? -> `true` or `false`
|  | Returns `false` if the object referenced by ref has been garbage collected.

Previous < | Contents ^ | Next >

Extracted from the book "Programming Ruby - The Pragmatic Programmer's Guide"
Copyright © 2000 Addison Wesley Longman, Inc. Released under the terms of the Open Publication License V1.0.
This reference is available for download.