| A Concise Introduction to Ruby Copyright ©2006, 2007 by David Matuszek |
| Prelude | Comments | Strings | Ranges |
| Tools | Names and scope of names | Pseudo variables | Arrays |
| Objects and classes | Reserved words | Operators | Hashes |
| Methods | Numbers | Statement types | Modules |
| Layout | Input/Output |
Ruby is a succinct, powerful, enjoyable language. That said, it must be noted that Ruby is not identical across platforms, newer versions are not always upwardly compatible with older versions, and resources are not always in complete agreement about the syntax, semantics, and conventions of the language. Nonetheless, any errors in this document are my responsibility.
Ruby is extremely dynamic. Anything the programmer has done, the programmer can revise, add to, or undo at any time. A primary design goal of Ruby is that it be fun to program in. This document describes the syntax of Ruby, but is too brief to convey good idiomatic usage of Ruby.
My main references are Ruby in a Nutshell: A Desktop Quick Reference by Yukihiro Matsumoto ("Matz"), and Programming Ruby: The Pragmatic Programmers' Guide by Dave Thomas. Ruby is the creation of Matz, but Dave Thomas is the main advocate and documenter.
load "filename" to load predefined code, such as function definitions. vi; to quit vi, type :q and hit Enter). Ruby is a completely object-oriented language--all values are objects.
Hence messages such as -5.abs are legal.
A class defines a new type of object. Classes are defined as:
class NameOfClass
# variable and method definitions go here
end
Class names must be capitalized.
If this same class is defined again, any new definitions are added to the class.
To create a new object of a given class, use object = NameOfClass.new.
If the class has a method named initialize, that method will
be called
just after the object has been created. Parameters may be given to
the new method, and those same parameters will be passed along
to the initialize method.
Instance methods are defined as
def method_name(parameter1, ..., parameterN)
# statements
end
and called with
instance.method_name(parameter1, ..., parameterN)
Class methods are defined as
def NameOfClass.method_name(parameter1, ..., parameterN)
# statementsend
and called with
NameOfClass.method_name(parameter1, ..., parameterN)
In all of the above, the parentheses are optional; however, in complex expressions the parentheses may be required for disambiguation.
There may be only one method with a given name in the same class. If a named method is defined more than once, the new definition replaces the old one.
A method may contain explicit return or return value statements. If
a method terminates by reaching the end of the method, the value returned
is the last value computed (which, for many types of statements, is nil).
Ruby is line-oriented: Each statement goes on a separate line. If a statement ends with an operator, comma, or backslash, it is continued on the next line. Semicolons can be used to separate multiple statements on a single line.
Standard indentation in Ruby is two spaces, not four as in Java.
If a line contains exactly the character sequence __END__ (two
underlines on each side), with no whitespace, it ends the program. Any additional
lines are data.
Comments start with a pound sign (#) and continue to the end of the line. Multiline comments are enclosed by =begin (starting in column 1) and =end (starting in column 1).
Variables and constants hold references to objects. Variables and constants do not have types; any variable name can reference any type of object. Capitalization conventions given below are enforced by Ruby.
"Constants" can be altered (!); doing so yields a warning message.
| Identifier type | Naming conventions | Scope of names |
|---|---|---|
| Local variables | Begin with a lowercase letter or underscore and consist of letters,
underscores, and/or digits. Underscores, not camelCase, are used to separate
words. Example: Method names also follow this rule. Example: |
Local variables are available within the immediately enclosing block,
method, class, module, or program. Method parameters are local to the method. Block parameters and variables first assigned in a block are local to the block, unless they are already in existence, in which case they are inherited. Loops do not create scopes, so variables that first occur with a loop are local to the enclosing scope. ( loop do...end is a method, not
a loop.) |
| Method names | Method names follow the same conventions as local variables. In addition, methods that return a boolean often end with ?, and those that modify their receiver often end with !. Examples: find_best_value, capitalize!, empty? |
Instance methods are available on instances of the class in which they are defined. Class methods can be defined with |
| Instance variables | Begin with the @ sign followed by a lowercase letter. Underscores
are used to separate words. Example: @best_value |
Instance variables are available only within instance methods of the class,
and have a default initial value of nil. |
| Class variables | Begin with @@. Example: @@number_of_instances |
Class variables are available throughout the immediately enclosing class.
They must be initialized before use. Variables declared at the top level
belong to the Object class. |
| Global variables | Begin with $. Some (mostly deprecated) Ruby-defined variables
consist of $ and
a punctuation mark. Example: $> is a synonym for $stdout. |
Global variables are available everywhere, and have a default initial
value of nil. It's usually
not good style to define your own global variables. |
| Constants | Value constants and constant object references
use uppercase letters and underscores. Example: MAX_SIZE Class names and module names begin with a capital and use CamelCase. Example: ChessBoard |
Constants are declared in a class or module, but cannot be declared within
a method. Outside the defining class or module, they may be accessed by
classObject::constant or moduleObject::constant. |
|
|
Integers are decimal by default, but may begin with a base indicator: 0 for octal, 0b for binary, 0x for hexadecimal, or 0d for decimal. Integers may be any size (limited by available memory).
Prefixing a single character with ? gives that character's numeric value. For example, ?a is 97.
Floating-point (real) numbers contain a decimal point, an exponent (following an e), or both. There must be at least one digit before the decimal point and before the e.
For readability, numbers may contain underscores.
Strings contain ASCII, not Unicode, characters. Newlines may occur within strings. Adjacent strings are concatenated. There are a variety of ways to write literal strings.
Strings may be enclosed in single quotes ('). Within a singly-quoted
string, the only escaped character is \' (single
quote). Substitutions are not performed.
Strings may be enclosed with any almost any punctuation mark as a delimiter, prefixed by %q. Example: %q!Hello!. However, if the opening delimiter is (, [, {, or <, the closing delimiter is ), ], }, or >, respectively. These strings act as singly-quoted strings.
Strings may be enclosed in double quotes ("). Within a doubly-quoted
string, all escaped characters are recognized, and actual values are substituted
for the general forms #{expression}and #{expression}. If the expression is a single variable beginning with $ or @, the braces may be omitted: #$var and #@var.
Strings may be enclosed with delimiters, prefixed by %Q. Example: %Q!Hello!. Delimiters are the same as for %q. These strings act as doubly-quoted strings.
Strings may be enclosed in backquotes (`), or any delimiter prefixed by %x. Delimiters are the same as for %q. Escaped characters and substitutions are allowed. The string is evaluated as a command to the underlying operating system, and the result of the command is returned as a string.
"Here documents" are for multiline strings. A string may begin with <<delimiter, where the delimiter is any sequence not containing whitespace, and ends with the delimiter in the same column. A string may begin with <<-delimiter, in which case the closing delimiter may be indented.
The initial delimiter may be enclosed in single quotes, double quotes or backquotes, to specify how the string is to be treated. The default is to treat the string as doubly-quoted.
"Characters" are ASCII, not Unicode.
| Method | Description |
|---|---|
<< |
Append another string or a character. |
=~ |
Match the regular expression and return the position of the match, or nil if no match. |
capitalize, capitalize! |
Upcase the first character and downcase all others. |
center(length) |
Pad with spaces on either side to make a string of the given length. |
chomp, chomp! |
Remove a newline from the end of the string, if one is present. |
count(description...) |
Count the characters fitting at least one "description". A description is a character string, but can use ch1-ch2 and ^ (negation) as in regular expressions. |
delete(description...), delete!(description...) |
Delete the characters fitting at least one "description" (see count). |
downcase, downcase! |
Convert all letters to lowercase. |
include?(s_or_c) |
Tests whether the string includes the given string or character. |
index(pat [, offset]) |
Search for the first occurrence of the given string, character, or regular expression (starting from offset, if given) and return its position, or nil if not found. |
ljust(length) |
Pad with spaces on the left to make a string of the given length. |
rindex(pat [, limit]) |
Search for the last occurrence of the given string, character, or regular expression (starting at or before limit, if given) and return its position, or nil if not found. |
rjust(length) |
Pad with spaces on the left to make a string of the given length. |
strip, strip! |
Remove whitespace from both ends of the string. |
swapcase, swapcase! |
Change the capitalization of all letters. |
tr(from, to), tr!(from, to) |
Replace the characters in from with the corresponding characters in to. Both from and to may use ch1-ch2 notation, and from can start with ^ for negation. |
upcase, upcase! |
Convert all letters to uppercase. |
selfself in C++ or this in Java.true, falsenilnull in Java.__FILE____LINE____FILE__.Highest precedence operators are at the top.
Most operators are methods, hence can be redefined. This feature should be used with extreme care and forethought. "Nonmethods" cannot be redefined.
| Operator | Meaning |
|---|---|
:: |
Same as dot (.) in Java. Nonmethod. |
[ ] [ ]= |
Element reference, element set |
** |
Exponentiation |
! ~ + - |
Not (nonmethod), complement, unary plus, unary minus |
* / % |
Multiply, divide, modulo |
+ - |
Add, subtract |
<< >> |
Left shift, right shift |
& |
Bitwise and |
| ^ |
Bitwise or, bitwise exclusive or |
< <= >= > |
Less, less or equals, greater or equals, greater |
<=> == === != =~ !~ |
Comparison, equality, case equals, unequal, match, nonmatch |
&& |
Logical and (short circuit, nonmethod) |
|| |
Logical or (short circuit, nonmethod) |
.. ... |
Inclusive range, exclusive range (nonmethod) |
? : |
Ternary if-then-else (nonmethod) |
= += -= *= /= **= %= |
Assignments (all nonmethods) |
defined? |
Test if symbol is defined |
not |
Logical negation (nonmethod) |
or and |
Logical or, logical and (both short circuit, both nonmethods) |
if unless while until |
Expression modifiers |
begin end |
Block expression |
Brackets, [ ], indicate that the enclosed part is optional. An
ellipsis, ... , means that the preceding element may be repeated.
Many methods are practically indistinguishable from statements. Some of these are included in the following table.
| Type | Syntax and description | Examples |
|---|---|---|
| = +=, *=, etc. |
Assignment. More than one value may be assigned at a time. |
|
| alias |
Creates a new name for a method, operator, global variable, or regular expression backreference. |
alias display puts |
begin ... end |
begin [code] [rescue [exception, ...] [code]] [ensure # may be more than one [code]] end
|
begin
eval string
rescue SyntaxError,
NameError => boom
print "Can't compile:" + boom
rescue StandardError => bang
print "Script error:" + bang
end |
| break |
break [expression]Exits a loop. If used within a block, the value of the expression is
the value of the loop. |
break |
| case |
case expression [when expression[, expression...][then] code]... [else code] end Comparisons are done using
|
case i when 1, 3, 5 then puts "odd" when 2, 4 puts "even" else puts "too big" end |
| class |
class ClassName [< SuperClass] code end The A class definition may be repeated (the |
class Something puts "whatever" end |
do ... end |
method_call do [|parameter, ...|]| [code] endIntroduces a block, optionally passing parameters into the block. The yield statement will return values from the block. |
array.each do |element| puts element end |
method_call { [|parameter, ...|] [code] }
Braces may be used in place of do...end. |
array.each { |e| puts e } |
|
| each |
The method |
my_set.each do |element| puts element end |
| for |
for var[, var...] in expression [do] code endRuby's for loop is less flexible than in C. |
for i in 1..10
puts "#{i} --> #{i * i}"
end
|
| if |
if condition [then] code [elsif condition [then] code] [else code] endConditions are separated from code by newlines, semicolons, or the word then. |
if count == 0 puts 'yes' elsif count > 0 puts 'no' else puts 'maybe' end if count==0; puts 'yes'; end |
statement if condition |
puts 'yes' if count == 0 |
|
| loop |
Loops until a |
loop do c *= 2 break if c > 1000 end |
| next |
next Within a loop, jumps to just before the loop test. |
next |
| raise |
Within a |
raise |
Raises a |
raise "You goofed!" |
|
Raises an error of the given type, optionally with the given message and stack trace. |
raise NameError, "Oops" |
|
| redo |
redo Within a loop, restarts the loop body, but does not reevaluate the condition or get the next iterated element. Within a block, restarts the |
redo |
| require |
The |
require 'chess_board.rb' |
| rescue |
rescue ExceptionType, ... [=> variable]The rescue clause is used to catch raised exceptions, of the
given ExceptionType or any subtype thereof. It can
be used (1) in a method, (2) within a begin...end block, and
(3) as a statement suffix. The variable, if present,
will hold the exception object; it is also in the special variable $!. |
rescue Exception => e |
| retry |
retryWithin a loop, restarts the loop body after reevaluating the condition or getting the next iterated element. |
retry |
| unless |
unless condition [then] code [else code] endLike an if statement with the condition negated. |
unless foo == '' puts foo end |
statement unless condition |
puts foo unless foo == '' |
|
| until |
until condition [do] code end Like a The condition is separated from the code by |
until count > 100 do count *= 2 end |
statement until condition |
count *= 2 until count > 100 |
|
begin code end untilcondition In this form, if the |
begin count *= 2 end until count > 100 |
|
| while |
while condition [do] code endThe condition is separated from the code by do, a newline,or
a semicolon. |
while count < 100 count *= 2 end |
statement while condition |
count *= 2 while count < 100 |
|
begin code end while condition In this form, if the |
begin count *= 2 end while count < 100 |
|
| yield |
yield [value, ...] Returns zero or more values from a block. |
yield result |
min..max, includes both endpoints; the three-dot form, min...limit, includes min but not limit.
An array is a sequence of values indexed by integers; the first location in the array is location 0 (zero). Negative integers can be used to index the array from the other end; -1 is the last location in the array. The values in an array may be of different types. Example:
0 |
1 |
2 |
3 |
4 |
|||||
|
|||||||||
-5 |
-4 |
-3 |
-2 |
-1 |
|||||
Arrays may be created by enclosing comma-separated values in square brackets; a final trailing comma is ignored. For example, you can create the above array with
my_array = [ "ace", 250, 3.14, "hi!", :abc ]
An easy way to create an array of strings is with %w (for singly-quoted strings) or %W (for doubly quoted strings). Example:
words = %w( apple banana cherry )
You can also create an array with Array.new.
Any (reasonable) integer can be used as an array index. If you read from an array location that hasn't been used, you get nil; if you write to a previously unused location, it will be created. For example, the following sequence is perfectly legal, and prints three nils and an abc.:
a = Array.new; a[3] = "abc"; a.each { |v| puts v }
If you index into an array with a pair of numbers, a[start, count], you get a new array of count values copied from a, starting from start. If you index with a range, a[min..max], you get a new array of those values copied from a.
Some of the more useful array methods are each, push, pop, sort, sort!, and join.
A hash is a mapping of keys to values. Any object that responds to the hash and eql? messages can be used as a key; objects that are eql? must have the same hash code. Immutable objects, such as symbols, make the best keys..
A hash may be created by enclose comma-separated key => value pairs inside braces; for example,
my_hash = { :ace => 1, :jack => 11, :queen => 12, :king => 13 }
Hashes may be "indexed" by a key within brackets, for example, my_hash[:jack] gives 11. If the key does not exist in the hash, nil is returned as the value. New key-value pairs may be added to hashes, for example, my_hash[:foo] = :bar.
The order of key-value pairs in a hash is essentially random.
A module is defined like a class, and may define class methods, instance methods, instance variables, and constants:
module ModuleName expressions end
Unlike a class, you cannot create an instance of a module.
There are two ways to use modules:
require statement, you can reference module methods with ModuleName.method, and constants with ModuleName::Constant. You cannot access instance variables or methods. include the module in a class, it is as if everything defined in the module is defined in the class. printprint 'Enter
a number: ' putsputs "I read:
#{input}" printfprintf("Float:
%5.2f, int: %i, string: %s", 3.1416, 17, 'foo') STDOUT.flushprint 'Gimme a number: '; STDOUT.flush; number = gets file.sync = true file. getsARGV is an array of command-line arguments. ARGF treats the command-line arguments as a virtual concatenation of the
named files. Dir.pwd returns the current working directory.Dir.chdir(path) changes the current working
directory to the given (existing) directory.Dir.mkdir(path) creates a new directory.Dir.mkdir(path, permissions) creates a new directory
with the given Unix permissions (as an octal number).Dir.rmdir(path) removes a directory.Dir.entries(path) and Dir.foreach(path) return a listing of all the file in the given
directory. d = Dir.open(path) opens a directory stream. Then...
d.path returns the path.d.tell returns the current directory entry.d.read reads the next directory entry.d.rewind goes back to the beginning of the stream.d.each iterates through the directory entriesd.close closes the directory stream. File.new(name, mode) creates a new file. The mode may be:
"r" --read from beginning of file."w" -- write from beginning of existing or new
file; old content is discarded."a" -- append to the end of an existing file, or create a
new file."r+" -- read and/or write, from beginning of file."w+" -- read and/or write from beginning of existing or
new file; old content
is discarded."a+" -- read/write to the end of an existing
or new file.f = File.open(path) opens a file. Then...
f.each iterates through the lines of a (text) file.f.chmod(permissions) changes the Unix permissions of the file. f.close closes
the file.f.closed? tests if the file is closed.File.file?(path) tests if the file is a plain file.File.directory?(path) tests if the file is a directory.File.readable?(path) , File.writable?(path),
and file.executable?(path) test the status
of the file. File.rename(old_name, new_name) renames a file.File.delete(name) deletes a file.| Program | Output |
|---|---|
ARGV.each { |arg| puts "arg -> #{arg}" }
puts "pwd -> #{Dir.pwd}"
Dir.foreach(".") { |file| puts "file -> #{file}" }
Dir.mkdir("goofus", 0755) unless File.exists? "goofus"
if File.exists? "goofus"
Dir.chdir("goofus")
puts "pwd -> #{Dir.pwd}"
puts " File 'goofus' created"
puts " readable? #{File.readable? "goofus"}"
puts " writable? #{File.writable? "goofus"}"
puts " executable? #{File.executable? "goofus"}"
puts " file? #{File.file? "goofus"}"
puts " directory? #{File.directory? "goofus"}"
f = File.new("doofus", "w")
f.puts "Line one", "Line two"
f.close # it's important to close the file!
File.open "doofus" do |f2|
f2.each_line { |line| puts line }
end # the block form automatically closes the file
File.delete("doofus")
puts " 'doofus' deleted" unless File.exists? "doofus"
end
Dir.chdir("..")
puts "pwd -> #{Dir.pwd}"
Dir.rmdir("goofus") if File.exists? "goofus"
puts " 'goofus' deleted" unless File.exists? "goofus" |
arg ->arg -> hello arg -> 123 pwd -> C:/Workspace/RubyTests file -> . file -> .. file -> .loadpath file -> .project file -> io_tests.rb pwd -> C:/Workspace/RubyTests/goofus File 'goofus' created readable? false writable? false executable? false file? false directory? false Line one Line two 'doofus' deleted pwd -> C:/Workspace/RubyTests 'goofus' deleted |