This chapter will concern itself with a broad overview of the Ruby Language.   It is not meant to be a detailed explanation.   If the reader is already familiar with the Ruby,  this chapter may be skipped.
For a more detailed discussion of the language,  get a copy of  Programming Ruby  by  Dave Thomas.   There are also many free sources of information available on the Web.
The use of literals  gives Ruby much of it's expressive power.   While a single literals are powerful,  it is the ability to assemble complicated literals that sets Ruby apart.   In the coming sections we will discuss a wide variety of literal types.  
The following are some examples of literal expressions:
String Literal: s = "text string"
Array Literal: a = [1, "tmp", 30]
Hash Literal: h = {'cello' => 'string'. 'horn' => 'brass'}
Symbol Literal: s = :name
Numeric Literal: n = 3.0
RegExp Literal: /pattern/
We group of sections will discuss character strings and regular expressions.   Literals are often used to initialize strings and create regular expressions.   These features are used extensively within Ruby.
Single quoted strings only allow two substitutions.   Two backslashes,  ' \ \',  are replaced by a single backslash.   A backslash followed by a single quote is interpreted as a literal single quote,  that is,  just as a character.
'string' # "string" - Simple text '\\new doc' # "\new doc" - Literal backslash followed by text '\n' # "\n" - literal '\n' not a newline! '\'' # "'" - A string consisting of a single quote
One of the features of string literals, some say a quirk,  is that carriage returns do not break a literal string.   That is,  the carriage returned is part of the string.  
'Multi
Line
String' # String = "Multi\n Line\nString"
---Translation Here about Multi-byte Character Strings --------
Double quoted strings provide more character processing when building the literal.   First,  it provides for substations for character groups starting with a backslash.   Second,  it allows for expression interpolation within the string body.
The following is a list backslash substitutions supported by double quoted strings:
\t tab - (0x09) \n newline - (0x0a) \r carriage return - (0x0d) \f form feed - (0x0c) \b backspace - (0x08) \a bell - (0x07) \e escape - (0x1b) \s whitespace - (0x20) \nnn character in octal value nnn \xnn character in hexadecimal value nn \cx control x \C-x control x \M-x meta(alt) x \M-\C-x meta(alt) control x \x character x itself
One of the powerful features of double quoted string literals is the ability to embed expression interpolation into the string body.  Within the a string, the sequence #{expression}  is replaced by the value of that expression.
lvar = 2
@ivar = 3
def md(arg) ... end # md(1) returns "Hello"
# md(2) returns ""
a = "text #{lvar}" # "text 2"
b = "text #{@ivar}" # "text 3"
c = "text #{1 + @ivar}" # "text 4
d = "#{md(1)}, World!" # "Hello, World!"
e = "#{md(2)}abcd"" # "abcd"
f = "#{"Nested"} String" # "Nested String
One Ruby short-cut is that when the expression is simply a global,  instance,  or class variable,  the braces can be dispensed with.    However, local variables must be  parenthesized or the result will be just the insertion of the literal  '#<local>'.
a = "text #@ivar" # "text 3"
b = "text #lvar" # "text #lvar" -- Local Variable must be
parenthesized (Next Line)
c = "text #{lvar}" # "text 2"
There are five basic forms of delimited string literals.
1. %q Single-quoted string 2. %Q Double-quoted string 3. % Double-quoted string 4. %w Array of Strings (Single-quote processing) 5 %W Array of Strings (Double-quote processing)
All of these forms consist a ' %'  sign followed by a classification character,  with the exception of item 3.   A bare ' %'  is treated the same as a ' %Q'
The first character following one these forms becomes the delimiter  for the string.   The delimiting character can be any non-alphanumeric  or non-mulitbyte  character.   Except for the four(4) paired bracketing  characters  ' ( [ { <',  the delimiting character is also used to terminate the string literal.   In the case of the characters  ' ( [ { <',  the closing delimiter must be the closing bracketing  character   ' ) ] } >'  that matches the opening delimiter.  
The examples below are for table item 1 shown above.   Items four and five, array of strings processing,  will be discussed separately.
%q(--text--) # "--text--" %q#--text--# # "--text--" %q2--text--2 # Error: unknown type of %string %qz--text--z # Error: unknown type of %string
The valid use of  ' # '  may be a surprise.   This is an exception to the rule that  ' # '  character starts a comment.   This is because since it is accepted as a delmiter,  the parser will not look for comments until the matching character is found that terminates the string liberal.
The type  character  ' Q '  and the bare ' %'  sign indicate double quote processing.   These are listed as item 2 and 3 in the table above.
%Q(\ttext) # "<tab>text"
%Q#--text--# # "--text--"
%(text \010here) # "texthere"
a = "one"
b = "two"
%|#{a + b}three| # "onetwothere"
The items 4 and 5  from the table above are for processing an array of strings.   These forms are a short cut for generating lists of strings.   For example,  the normal method to create a list of animals is as follows:
arr = ['cat', 'dog', 'whale', 'tiger', 'great\ dane' ]
Notice that this list is being created with single quote strings.   As we have discussed before,  the only processing performed is substitution of backslash quoted backslash,  '\\',  and a backslash quoted single quote,  '  \'  '.  
With item four,  ' %w'  an array of strings is created.  However,  since both  ' %w' and ' %W'  parse a white-space delimited list,  Ruby allows these constructions an additional processing option,  a backslash quoted space,  '  '.    The following example demonstrates this feature.
arr = %w(cat dog whale tiger great\ dane)
printf("%s\n", arr[4]) # "great dane"
One of the benefits is that since delimited input is that you can chose the delimited character.   You must, at times, create string literals that contain many characters that are normally standard delimiters.   These most often include, single and double quotes, and slashes.   By choosing the right delimiter the literal is much easier to create.
list1 = "The quote was \"test the waters\" and \" to be sure\"" list1 = %q(The quote was "test the waters" and " to be sure")
The here document  is yet another way to create strings without having to resort to quoting functions.   A here document starts with initial character string,  either   ' << '  or  ' <<-'.   Immediately after the initial starting string,  the following characters until terminated by white-space or a carriage return,  will constitute the terminating character string.   The following example produces strings with the same contents:
str1 = << EOS
test line 1
test line 2
test line 3
EOS
#
printf("%s\n", str1)
#
str2 = " test line 1
test line 2
test line 3
"
#
printf("%s", str2)
The result of the program fragment above is as follows:
test line 1 test line 2 test line 3 test line 1 test line 2 test line 3
A letter in a string can is equivalent to the integer value stored the that character position,  at least if it not a multi-byte character.   There are several ways to store non-printing characters in a string location.
C1 = "\n" # By a standard backslash code
C2 = "\C-j" # By the equivalent Control Code
#
p "C1 = #{C1.to_s}"
p "C2 = #{C2.to_s}"
The result is:
"C1 = \n" "C2 = \n"
A Regular Expression  in Ruby is delimited by forward slashes.
/regular expression/
A Regular Expression literals are a object of type Regexp.   They can be created in the following ways,  either with or without an option specification.
1. /pattern/
2. /pattern/i
3. %r{pattern}
4. %r{pattern}i
5. Regexp.new('pattern'))
6. Regexp.new('pattern', 'i' )
Ignoring for the moment what patterns consist of,  the processing of such patterns can be modified by appending an option.   Some of these options are:
i - Case Insensitive m - Multiline Mode x - Extended Mode
Regexp is an abbreviation of Regular Expression and will be used interchangeably with it.
The thing to remember about Regexp is that it is a language  with exacting rules.   However,  Regexp is a powerful tool for parsing strings in a wide variety of circumstances.   It is a subject that every programmer should be familiar with.
Let us start with a simple Regexp,  matching it with a text string.   If there is only text and no Regular Expression operators,  the Regexp will match any string that contains the text specified in the Regular Expression embedded within it.   In this and following examples the  ' =~'  operator compares a Regexp with a normal string and returns true if the Regexp matches a portion of text within the string.
/abc/ =~ 'zxyabcdef' # Returns TRUE /ABC/ =~ 'zxyabcdef' # Returns FALSE /ABC/i =~ 'zxyabcdef' # Returns TRUE
The next examples are using the Regexp operators  ' ^',   ' $'  .   These operators match the beginning of the line  and End of the line  respectfully.   These operators are called Anchors.   They only match text that is immediately adjacent the beginning or end of a line.
/^From:/ =~ "From: jack" # Returns TRUE /^ To:/ =~ "To: jill" # Returns FALSE /end$/ =~ "to the end" # Returns TRUE /end$/ =~ "to an end!" # Returns False
The language of Regular Expressions are made up characters that represent themselves and characters the are Regular Expression Operaters.   The following are these operators:
These characters are used to form Regular Expressions Operators:
.    --period
|    --Bar
(  )  --Open/Close Parenthesis
[  ]  --Open/Close Brackets
{  }  --Open/Close Braces
+    --Plus
\    --Backslash
^    --circumflex
$    --Currency Sign
*    --Asterisk
?    --Question Mark
Some these characters stand by themselves,  such as  ' .'  which represents any character except end of line.   Note:  there is an exception to even this simple operator if single line mode is on!
Other operators introduce whole classes of additional operators.   Backslash is such an operator that not only quotes operator characters so the represent themselves,  but also represents character classes.
%  Regular expressionThe study Regular Expressions is beyond the scope of this document.   Whole books written on the subject.   So far we have shown examples of creating Regexp literals by enclosing them within slashs.   We have also shown how compare Regexp and strings with the  ' =~'  Operator.   The following shows two other methods for creating Regular Expressions.
Regular Expressions also have a delimited input form, ' %r'.   For the same reasons that other delimited forms were convenient,  the ability to create Regular Expressions without having to quote special characters works well for these expressions..
%r{^From:} =~ "From: jack" # Returns TRUE
%r{^ To:} =~ "To: jill" # Returns FALSE
%r{
%r{end$} =~ "to the end" # Returns TRUE
%r{end$} =~ "to an end!" # Returns False
Up to now we have used Regexp literals for comparisons,  without specifying that we were actually creating objects of type Regexp.   The following forms all create Regexp Objects:
a = Regexp.new('\s+and\s+') # Regexp that matches an "and"
# surrounded by white-space
b = /\s+and\s+/ # -- same --
c = %r{\s+and\s+} # -- same --
a =~ "jack and jill" # Returns TRUE
a =~ "sand dunes" # Returns TRUE
Arrays are sequential lists  of objects that can be stored,  modified,   and returned by using a wide variety of ruby commands.   Since Ruby employs  "duck"  typing,  arrays may contain a collection of non-heterogeneous items.
Array literals are created by enclosing a comma separated list of items between two brackets.   These items may be literals, variables, constants, symbols, or expressions combining these elements.
[ 1, 2, 3 ]
[ 'This', 'is', 'an', 'array', 'of' and 'string' ]
[ /regexp/, {'hash'=> 3} 4, 'string'?\C-a ]
Lvar = $gvar = @ivar = @@cvar = nil
[ Lvar, $gvar, @ivar and @@cvar ]
[ Object.New (), Object.New (), Object.New () ]
Arrays may also be created with the method new  and loaded in various ways.   One of the common ways is to create an empty array and push  items onto the end of the array.
The following example demonstrates this concept,  and additionally illustrates that each literal has a different  object id.
#!/usr/bin/ruby
#
i = 0
a = Array.new()
while i < 5
a.push([1,2,3].id) #The object ID is different for each pass
printf("%d) %d\n",i,a[i]) #Print formatted result
i = i + 1
end
#Result of program above:
0) 91447254836
1) 91447254776
2) 91447254716
3) 91447254656
4) 91447254596
One that standard uses of array's is to contain a list of words,  in other words a array of strings.   This happens often enough that Ruby provides two delimited constructions to handle assembling such arrays.  
The  ' %w' and ' %W'  forms convert space delimited lists of strings into arrays of strings.   The lower case form uses single quote processing, with the addition of  ' \<spc>> '&  processing.   The upper case form, ' %W',  performs double quote processing on the individual strings!
%w(alpha beta gamma delta)
# Returns ['alpha', 'beta', 'gamma', 'delta']
%w<month fire water wooden gold earth day>
# Returns ['month', 'water', 'gold', 'earth', 'day']
%w{Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec}
# Returns ['jan','Feb','Mar','Apr', ... ,'Sep','Oct','Nov','Dec']
The  ' %W'  uses double quote processing on the isolated strings.   This means that expressions can be embedded within strings.   The following example shows the difference in the processing by the two forms.
n = 5
%w (list0 list #{n}) # Returns [ 'list0', 'list #{n}' ]
%W (list0 list #{n}) # Returns [ 'list0', 'list5' ]
A Hash Table  is an indexed collection of data accessible by a key.   Data stored in a Hash Table consists of a pair of values,  a  Key  and a value.   A Hash literal is constructed by enclosing in braces  Key/Value  pairs separated by commas.
{'key' => 'value', 'key2' => 'value2'}
{3 => 0, 'string' => 5, [ 'array' ] => 9}
{Object.New () => 3, Object.New () => 'string'}
A Hash literal can also be created over multiple lines
{0 => 0,
1 => 3,
2 => 6}
You will find that Hash Tables are the most commonly used data structures in Ruby.   Chapter 3,  "Name and Name Charts",  extensively documents Hash Table usage and construction.
The Hash Table is the most efficient to implement lookup tables.   As documented in the book,  they are used extensively in the construction of the Ruby Language itself.
New entries can be added to a Hash Table using the  ' [ ]= '  operator,  and retrieved with the  ' [ ] '  operator.   In addition to using Literals to populate a new Hash Table, the new  method can create an empty Hash Table.
h = Hash.new()
h['key1'] = 'value1'
h['key2'] = 'value2' # h = {'key1' => 'value1', 'key2' => 'value2'}
a = h['key2'] # a = 'value2'
A Range literal is the oddball which did not come from another language.   Ranges are often seen as a way create indexes for arrays.   When a Range is connected with two dots it includes the terminal value,  if three dots the terminal value is not included in the Range.
0..5 # 0 up to 5 (Including 5) 0...5 # 0 up to 5 (NOT including 5) 1+2..9 # 3 up to 9 (Including 9) 'a'..'z' # 'a' thru 'z' (Including 'z')
Ranges provide three separate features: sequences, conditions, and intervals.
1. Sequences 2. Conditions 3. intervals
Sequences generate a series of objects which can be used feedstock for a variety of uses.   As stated above they can be used a index's.   They can also create an array and populate it.
(1..5).to_a # a = [1,2,3,4,5]
The following example uses a Range to provide indexes:
#!/usr/bin/ruby
#
a = 10
(1..5).each { |b|
puts a + b
}
They can be used to create conditionals.   The following program prints out all input lines between the time it sees a "start"  until it sees a "end"  in the input stream.   Notice that a Regular Expressions are used for testing the line contents.
#!/usr/bin/ruby # while line = gets puts line if line =~ /start/..line =~/end/ end
Finally,  they can be used for providing intervals.
(1..10) === 5 # Returns TRUE
(1..10) === 15 # Returns FALSE
('a'..'j') === 'e' # Returns TRUE
('a'..'j') === 'm' # Returns FALSE
Intervals are often seen is case  statements:
kind = case year
when 0..9 then "tens"
when 10..99 then "hundreds"
when 100..999 then "thousands"
else "Out of Range"
end
Symbols  are an alternative to constants for creating names with unique values.   Often you wish to create a set of constants,  lets say the main points of a compass:  North,  East,  South,  and West.   The program does not care what the value is,  as long as it is unique.
#!/usr/bin/ruby
#
def walk(dir)
case dir
when :North
puts "North Pasture"
when :east
puts "Homestead"
when :South
puts "ocean"
when :West
puts "city"
else
puts "unkown"
end
end
#
puts "Show Direction:"
walk(:North)
puts "Show Direction"
walk(:South)
puts "Done"
Hash keys are often symbols.   This ensures that the keys are unique.   Why?   By definition Symbols always have unique values  and are guaranteed to be the same value through out the program.
h = { :North => "NORTH", :South => "SOUTH" }
An Important aspect of symbols and strings is that they can be converted to each other.   This does not imply that symbols and strings are always replaceable with each other,  but they can substitute for each other in some cases.   For example a catch  block specification may be a string or a symbol:
#!/usr/bin/ruby
#
catch ("done") do # done is a string
for num in (1..6)
throw "done" if num == 4
puts num
end
puts "DONE"
end
puts "After catch block"
------------------------
#!/usr/bin/ruby
#
catch (:done) do # done is a symbol
for num in (1..6)
throw :done if num == 4
puts num
end
puts "DONE"
end
puts "After catch block"
Another place symbols are used is to specify names for attr_reader and attr_writer.   In the example below we replace long winded structure with the more compact attr_reader version.
class getdata # Long winded way
def name
@name
end
def age
@age
end
def initialize(name, age)
@name = name
@age = age
end
end
class Getdata # With attr_reader form
attr_reader :name, :age
def initialize(name, age)
@name = name
@age = age
end
end
#Both classes are initialized the same way
ga = Getdata.new("john", "55")
#Both load variables of the same names
#Both produce the same output!
puts "Name = #{ga.name} -- Age = #{ga.age}"
Result: Name = john -- Age = 55
Numerical values come in three basic flavors:  Fixnum,  Bignum,  and Floats.   Both Fixnum and Bignum store fixed point numbers. However, the Fixnum stores numbers as a binary word and that limits it size either 31 or 63 bits, depending on the word size of the processor.   Numbers larger than this size are stored as Bignum, which stores the number as a series of integers.   The only limit is the size of the available memory for Ruby.
Decimal Numbers: Fixnum: 2 Fixnum: :: Fixnum: 65536 Fixnum: 4294967296 Bignum: 18446744073709551616 # Exceed size of Fixnum 123_199_001 # Underbars are ignored in decimal numbers Floats: float: 12.34 # 12.34 float: -0.1234e2 # -12.34 float: 1234e-2 # 12.34
Methods are the workhorses of Ruby.   If defined at the top level they become functional methods.   That is,  a method not bound to class.   All other methods are defined within the class definition,  and used to implement class functions.
A method is created by def  statement.   It consists of the reserved word,  def,  followed by the name of the method.   The name is followed by the method parameters.   These may be enclosed with parenthesis,  but that is optional.
The following demonstrates both kinds of methods in a working program:
#!/usr/bin/ruby
#
def fun1(arg)
puts "fun1 = #{arg}"
end
class C
def initialize
puts "Initialized!"
end
def method1(arg)
puts "method1 = #{arg}"
end
end
#
fun1(11) # No class prefix required (Top-Level method)
c = C.new() # Create instance of Class 'C'
c.method1(99) # Execute it method!
Results:
fun1 = 11
Initialized!
method1 = 99
The value  returned by a method is the last value evaluated by the method.   If a return statement is used,  it's argument is the last value evaluated.   It is stating the obvious,  that all methods return a value.
def rone()
return 1
999
end
#
def rboth(arg)
if arg == 2
return 2
else
999
end
end
#
puts rone()
puts rboth(2)
puts rboth(1)
Results:
1
2
999
Ruby makes it possible to define default arguments for methods.   Without this feature,  the following program would produce errors for dtest  and dtest().
def dtest(arg1=nil)
if !arg1
puts "Nil Arg"
else
puts "#{arg1}"
end
end
dtest
dtest()
dtest(23)
Results:
Nil Arg
Nil Arg
23
However,  there is a rule the affects where default values may be used.   Default arguments must always follow arguments without defaults.   In particular,  you can not place defaulted arguments in the middle defaulted arguments.
The following produces a syntax error when run.
def wrong_decl (arg1, arg2 = nil and arg3)
puts " #{arg2}"
end
While parenthesis are certainly allowed in statements and expressions,  Ruby in many cases does not required the syntax queues that many other languages require.   If parenthesis are not required to parse a statement,  they are optional.
puts 'Hello, World!' # Instead of: puts('Hello, World!')
obj = Object.new # Instead of: obj = Object.new()
As of Ruby 1.8.6 some of optional parenthesis were scheduled to be enforced future versions of Ruby.   The following is an example of where this enforcement was rescinded in Ruby 1.9.
#!./ruby fname = "~/Bin/zznumb" puts(File.basename(fname)) # zz:4 puts(File.basename fname) # zz:5 puts File.basename fname Results 1.8.6: ./zz:4: warning: parenthesize argument(s) for future version ./zz:5: warning: parenthesize argument(s) for future version zznumb zznumb zznumb Results 1.9.0: zznumb zznumb zznumb
Another example of optional parenthesis is the definition and calling of methods.   Methods may have many parameters or none and parenthesis are still optional in many cases:
def method1 p1, p2, p3
printf("P1: %s P2: %s P3: %s\n", p1,p2,p3)
end
def method2 # No paramters
puts "No parameters"
end
method1 "good", "bad", "ugly"
method2
Results:
P1: good P2: bad P3: ugly
No parameters
The may be times when a method be called with a unknown number of arguments.   Ruby supports variable length argument lists.   A variable length argument is made up of two parts.   First, zero to n number of fixed argument specifications,  followed parameter prefixed with a asterisk.
The fixed arguments must be present,  and not defaulted.   Any arguments beyond the fixed items are collected into an array and passed in last argument (i.e. *arg).
def varg(arg1, *rest)
p "#arg1-#{arg1}, rest=#{rest.inspect}"
end
varg("one")
varg("one", "two")
varg("one", "two", "three)
Results:
"arg1-one, rest=[]"
"arg1-one, rest=[\"two\"]"
"arg1-one, rest=[\"two\", \"three\"]"
The previous section created variable length argument lists using the asterisk prefix.   This section shows another use of the asterisk prefix.   The asterisk is often refereed to as splat,  due to the fact the an asterisk looks somewhat like a bug that hit a windshield!
You can convert any collection or enumerable object into its individual items and pass those
def do_job(a, b, c) p(a, b, c) end list = [ 1, 2, 3 ] do_job(*list) results: 1 2 3
It is also possible to transfer arguments in this manner through more than one level. The following example extends the previous code.
def get_job(*args) do_job(*args) end get_job(*list) results: # do_job generates same result! 1 2 3
Since almost no exception,  all expressions in Ruby are essentially method calls.   The presence of "syntactic sugar" sometimes masks this truth.   The following are method calls!
1 + 2 # 1.+(2) a == b # a.==(b) -/regexp/ # /regexp/.- obj.attr = val # obj.attr=(val) obj[i] # obj.[](i) obj[k] = v # obj.[]=(k, v)
It takes some time to become accustomed to the object oriented constructions underlying the Ruby syntax.   For example,  "1 + 2" is actually:  Object '1',  receiving method '+',  with argument '2'.
This is because unlike some other object oriented languages,  even integers  are objects in Ruby.   So to perform calculations it necessary to apply methods to integers to get results.

Figure 1: Method Execution Sequence
Standard method names come in three classes.   Names without the postfix symbols,  question marks and explanation marks,  are the primary methods.   The question mark postfix indicates that the method is a conditional method.   The explanation point postfix indicates a possibly dangerous method.   These methods are generally methods that make changes to objects in-place.
In the example below,  the include?  method returns true if the parameter is a sub-string of the receiver.
str = "Test Job xx" str.include? "job" # False (Compare is case sensitive) str.include? "xx" # True
In the example below,  downcase!  returns the updated string or nil if no changes are made.   Just downcase  always returns the updated string,  even if no changes are made.
str = "This is BIG" # s = str.downcase # s = "this is big" -- str = "This is BIG" # x = str.downcase! # x = "this is big" -- str = "this is big" # y = str.downcase! # y = nil -- str = "this is big"
Ruby supports,  as most languages,  both binary and unary operators.   The most prevalent are the binary operators.   As the name binary suggest,  these operators take two parameters.  
1 + 2 # 1.+(2) -- '1' is the receiver, + is the method,
'2' is the methods parameter.
In more complicated expressions either operator precedence or parenthesis determine the order of execution.   The chart below shows the precedence of the variable binary operators:
(PRECEDENCE: Top(highest) to bottom(lowest)) :: [] ** -(unary) +(unary) ! ~ * / % + - << >> & | ^ > >= < <= <=> == === != =~ !~ && || .. ... =(+=, -=...) not and or All of the above are just methods except these: =, .., ..., !, not, &&, and, ||, or, !=, !~ In addition, assignment operators(+= etc.) are not user-definable.
There are two unary operators,  '+',  and '-'.   As unary suggests these operators only take one parameter.
+2 # A positive integer value of 2 -1.0 # A negative floating value of minus 1.0
Objects often provide methods to access,  set,  and/or modify their internal states.   The internal states exposed in this manner are called Attributes. An Attribute writer takes the following form:
class C
def arg=(new_value)
@arg = new_value
end
end
C.arg = next_value # Sets '@arg' to 'next_value'
Ruby supplies a short cut for this structure,  the attr_writer  statement.   The following is exactly equivalent to the previous example.
class C attr_writer :arg end C.arg = next_value # Sets '@arg' to 'next_value'
The attr_reader  statement works in a similar manner,  but is setup for read attribute operations.   The underlying form is as follows:
class C
def arg
@arg
end
end
puts "Argument = #{C.arg}" # Display's value of '@arg'
Using the attr_reader statement is exactly equivalent to the previous example.
class C
attr_reader :arg
end
puts "Argument = #{C.arg}" # Display's value of '@arg'
When left value side of an expression (the lvalue) is an array element reference,  the ' [ ]=' operator in the receiver is called.   It is passed with one or more indexes,  followed by the rvalue of the expression.
obj[1] = "data one" # obj.[]=(1, "data one") obj[1, 3] = "data two" # obj.[]=(1, 3, "data two")
SuperThe key word super  is used to indicate that a method should execute it's parents version of a method before processing the local version.   This allows the inherited method behavior to be executed as part of the current method processing.   This is the heart of a feature,  that allows methods to inherit behavior's so that their functionality can be extended.
In the following example,  a method is defined in class A  that prints a message.   Then class B  is sub-classed from is parent A.   Both have a method named test.   Now,  normally this means that the method test  residing in class B  would be executed, for it would have precedence.
However,  the sub-classed method test  has the statement super  within it.   This means that the inherited method is called with any necessary parameters at that point.   Typically this means that any further processing for the method follows the super invocation.
class A
def test(arg)
puts "#{arg} executed in A"
end
end
class B < A
def test(arg, next)
super(arg)
puts "#{next} called from B"
end
end
B.new.test("ARGA", "NEXT")
Results:
ARGA executed in A
NEXT Called from B
At this point,  we can use another short-cut provided by Ruby.   If the call to super  is execute with zero parameters  by a sub-classed method,  it will call the method in the super-class with the parameters that the current method received.   It should be noted that this assumes super-class has  a method of the same name.
Notice in the following example,  that zero parameters is not  the same thing as an empty parameter list.   The call super  is different from super().   The latter sends an empty  parameter list!
class A
def test(*args)
p args
end
end
class B < A
def test(a, b, c)
super
end
end
class C < A
def test(a, b, c)
super()
end
end
B.new.test(1,2,3)
[1, 2, 3]
C.new.test(1,2,3)
[]
Ruby defines three levels of protection for object, methods, modules and class constants.
Access control is set withing the class definition.   The default protection for classes and modules is private.  The default protection for structures is public.   The access control set will remain in effect until is changed or the cless definition is closed.
As a side note,  these three statements are methods  not reserved words!   They can and are most often used without parenthesis,  as in the example below.   When used in this manner they set the default protection  for all subsequently define methods until changed.
Class C
public
def a1 () # public
def a2 () # public
private
def b1 () # private
def b2 () # private
protected
def c1 () # protected
def c2 () # protected
end
The alternate form,  names of methods and constants are sent as parameters.   This sets the protection for just the specified methods and constants.
Class C public def a1 () # public def a2 () # public def z1 () # public at the time of definition :: :: private(z1) # private protection until changed
There is one subtle 'feature' related to access control and visibility.   It is possible in a sub-class definition to change the visibly of a method or constant in a super-class of a object.   In the sub-class changes the access control setting for a method in it's parent,  the visibility of the method is changed for sub-class instances.
class Base
def btest
puts "Test in Base Called!"
end
private :btest
end
class C < Base
public :btest
end
class D < Base
end
c = C.new()
puts "Class C calling btest"
c.btest()
d = D.new()
puts "Class D calling btest"
d.btest()
Results:
Class C calling btest
Test in Base Called!
Class D calling btest
./zz:24: private method `btest' called for # (NoMethodError)
Normally the a module method can not be called until the module in mixed-in with a class.
module Math
def sin(x)
puts "Math 'sin(#{x}) was called!"
end
module_function :sin
end
include Math
sin(2)
Result:
Math 'sin(2) was called!
However, Ruby provides a way to call properly setup module functions without having to include the module.   This an advantage when one one tor two module functions are need.   The reason that the module methods can be called with polluting the name-space with unnecessary module functions and constants.
Ruby accomplishes this with the module_function()  method.   Within the Module the module_function() statement designates those methods that can be called externally without including the module itself.   The module_function() creates module functions for the named methods.   These are copies of the originals and may modified independently.   Note:  that the module itself is the receiver,  not the class calling the module method.
module Math
def sin(x)
puts "Math 'sin(#{x}) was called!"
end
module_function :sin
end
Math.sin(999)
include Math
sin(001)
# Math 'sin(999) was called!
# Math 'sin(1) was called!
An iterators  is construction traverses a collection of objects and invokes a block  for each element in the collection.   We will look at the C/C++,  but keep in mind many other languages contain similar constructs.   These languages typically use for  and while  loops to traverse collections,  primarily arrays.
arr = [ 1, 3, 4 9, 14] # Given: Used below also
for (i = 0; i < 5; i++) { # 'for' loop
-- action ---
}
i = 0
while i < 5 { # 'while' loop
--- action ---
i += 1;
}
Ruby blocks are groups of code inside a pair of parenthesis,  or a do ... end  construction.   When Ruby encounters a block it does not execute it,  rather it stores the code and the environment  at time it was encountered.   That includes local variables,  current object,  etc.   Also this block can only appear adjacent to the method call and starting on the source line.
arr.each do | item |
puts "Next Item = #{item}"
end
Notice that an iterator does not need to be told the length of the collection.   Since Ruby has 'duck' typing,  we don't even need to know the type of elements in the collection.   This a much safer way to step through collections.
Some points about blocks need to be covered.   Methods can not transfer to plural blocks.   For example,  you might try to process a two dimensional array with two blocks:
array2D.each do | i | --- some action --- end do | j | --- some action --- end
This sort of processing is possible but must be contained inside one block.
array2D.each do | i, j | --- some action --- end
Another point is the ability of block code to reference local variables outside the block itself.   The following is example of referencing a local variable.
lvar = 'ok'
[ 0,1,2 ].each do |i|
puts "#{i} -- " + lvar
end
Result:
0 -- ok
1 -- ok
2 -- ok
There is a concern to be covered when modifying local variables outside the block.   If the block modifies the outer local variable,  it's value will reflect the final value set by the block when the block exits!   We will slightly modify the previous code to show this effect.
lvar = "OK"
[ 0,1,2 ].each do |i|
if i == 2
lvar = "Error"
end
puts "#{i} -- " + lvar
end
#
puts "Exiting value of 'lvar' " + lvar
Results:
0 -- OK
1 -- OK
2 -- Error
Exiting value of 'lvar' Error
If a variable occurs inside a block, but is not present in surrounding scope it will be local to the block and will disappear when the block ends.
[0, 2].each do |element| c = element + 1 end puts C.to_s Result: ...uninitialized constant C (NameError)
Now let's discuss when variable is both in the block and the surrounding scope.   Two things can happen here.   If the variable is specified in the parameter list,  then the version in the block is local to the block.   The variable in the surrounding scope will not be modified.
If the variable is not  in the parameter list,  the variable in the block is actually the same as the variable in the surrounding scope.   If the block changes the variables value,   it will also change the variable in the surrounding scope.
The block local variable can never been seen outside it's block.   If blocks are nested,   then the surrounding scopes can be seen by the nested block. The following example illustrates this concept.
Lvar = 0
[ 1 ] .Each do
Var1 = 1
[ 2 ] .Each do
Var2 = 2
[ 3 ] .Each do
Var3 = 3
# here lvar and var1, var2, var3 are visible
End
# here lvar and var1, var2 are visible
End
# here lvar and var1 are visible
End
# here just lvar is visible
% Ruby -e ' [ 0 ] .Each do I = 0 End P i # here it becomes error ' -e:5: Undefined local variable or method `i' For #< Object:0x40163a9c> (NameError)
The are two ways to create a block.   First, the block can be contained in a do...end  form.   Second it can be contained in matching pair of parenthesis.
arr = [ 0, 1, 2]
arr.each do |i|
puts i
end
arr.each { |i|
puts i
}
The only functional difference between these forms the precedence of the operators.   In this case the parenthesis bind tighter  than the do...end  form.   As you can see in the following example,  the precedence of the parenthesis changes the how the statement is interpreted.
M m do...end # m (m) do...end
M m {....} # m (m() {....})
A convention has crystallized among Ruby programmers to use parenthesis for single line blocks and do...end  for multi-line blocks.   While this is not in any mandatory,  it is coming close to being an best practice.
YieldYield  is the magic code that creates iterators.   How is that?   Within iterators there is logic to step through the collection specified.   Typically a iterator steps through a collection one at a time.   Although this is how iterators like each work,  there are other schemes that could be used.   Even and odd numbers might be a canidate,  or how about a iterator that scanned collections for prime numbers?   These types of iterators can also be created by users using standard iterators and applying the selection criteria at the block itself.
In the following example we create our own iterator.   Notice the yield()  statement.   When a yield executed it branches to the associated block and loads any parameters that are specified.   When the block finishes execution,  it returns to the statement immediately following the yield()  statement.
class Array
def my_each
i= 0
while i < self.length
yield self [ i ] # Yield (jump) to block
i+= 1 # Return from block
end
end
end
[ 0,1,2,3,4 ] .each do |i|
p i
end
[ 0,1,2,3,4 ] .my_each do |i|
p i
end
A yield()  call is somewhat similar to a function call in C or C++.   It jumps to a function code location with the specified parameters and when it returns to the next statement after the function call.   Further,  it returns a value.
One last point.   There must be a block  associated with method using an iterator. To see why,  try entering the following code into 'irb'.
% Ruby -e ' [ 0,1,2 ].Each'
-e:1:In `each': No block given (LocalJumpError)
From -e:1
ProcAs hopefully you remember that blocks  are chucks of code associated with a method.   These blocks execute in the context in which they were defined.   Blocks are not  objects.   They are simply blocks of code.   They can be converted to proc  objects in several ways.
The first way is to add a ampersand prefixed variable after the parameters of the method.   This variable(&block) will contain the proc object created when this function is executed.   Within the method body this proc can be executed by the call  method.
def meth1(p1, p2, &block)
puts block.call(p1,p2)
end
meth1(1,2) { puts "a block" }
meth1(3,4) { |p1, p2| puts "NEW CALL #{p1} #{p2}" }
Results:
a block
nil
NEW CALL 3 4
nil
The second method is to call proc.new and provide it a block.   Extending the previous code,  we show how to create proc objects with Proc.new().
block1 = Proc.new { |p1, p2| puts "NEXT CALL #{p1} #{p2}"}
block1 .call(5, 7)
Results:
NEXT CALL 5 7
The last method creates the proc object with lambda method.  
block = lambda { |p1, p2| puts "NEXT CALL #{p1} #{p2}"}
block.call(5, 7)
Results:
NEXT CALL 5 7
Proc objects internally respond to the command next.   The next command causes the block to exit.   The following shows examples of all three kinds of Proc object generation.
def meth
res = yield
"The block returns! #{res}"
end
puts meth { next 99}
pr = Proc.new { next 98}
puts pr.call
pr = lambda { next 97}
puts pr.call
Results:
The block returns! 99
98
97
def print_block (&block)
puts block
end
print_block() { puts "Test !"}
print_block()
#
nil
Another way to attack the problem is to create a proc object and use that as a substitute for enclosing the code itself with the parenthesis.   In the example bwlow,  both methods produce the exact same results.
xblock = Proc.new {|i| p i} # Method 1 - Create a proc object
[ 0,1,2 ].each(&xblock)
--- OR ---
[ 0,1,2 ].each {|i| p i} # Method 2 - Use a Raw Block
Results:
0
1
2
The following code is also equivalent to the two methods above!
def each_item(&block) [ 0,1,2 ].each(&block) end each_item do |i| p i end Results: 0 1 2
Since almost all things in Ruby are actual objects,  then the statements created in the language are primary made up of various expressions.   For example,  the control structure if  is an expression and it has some value.
IfThe explanation of  if  is probably not necessary,  but a discussion of all the basic statements is required.   When a conditional expression is true  it executes itself.   For programmers from 'C' and other languages it is important that they understand what constitutes true and false in Ruby.
If the value of an expression is nil  or  false   it is false.   All other values are true.   The following example shows the results of some basic conditional values.
z = 0 # Hey 'C' guys: Notice the zero is true NOT FALSE! o = 1 m = -1 n = nil f = false t = true if z then puts "z is true" end if o then puts "1 is true" end if m then puts "m is true" end if n then ; else puts "n is false" end if f then ; else puts "f is false" end if t then puts "t is true" end Results: z is true 1 is true m is true n is false f is false t is true
Some standard conditional statements:
P (if true then 1 else 2 end) P (if false then 1 else 2 end) P (if false then 1 elsif true then 2 else 3 end) Results: 1 2 2
Finally,   if no part of the  if  has a matching expression,  then nil  is returned.   The following statements both return nil.
p (if false then 1 end) p (if true then end) Results: nil nil
One unusual aspect of Ruby is the ability to add a conditional on the end of a statement.   If the conditional is false  then the statement will not execute.
print "debug\n" if $debug # Prints if variable '$debug' is true.
UnlessThe unless  statement is the reverse of the if statement,   While it provides an  else statement,  there is no elsif.   The following is the syntax of the unless statement.
unless expr [then] expr... [else expr...] end
The above syntax is the equivalent to the following if syntex.
if !(cond) ... else ... end
As it was with the if  statement,  an unless  modifier can be added to a statement.   If the unless  condition is true  the statement will not execute.
print "stop\n" unless valid($passwd)
And &&, or ||, not !The Boolean 'AND'  operator and the Boolean  'OR'  operator come in two flavors.   The alphabetic versions and  and or.  and the &&  and || operators respectfully. The following conditional statements are identical with the exception that the alphabetic versions have a low precedence than the symbol versions.   This can be significant if expressions are not properly parenthesized.
if <cond> and <cond>  puts "OK!" # Print if both <cond> are true end if <cond> &&; <cond>  puts "OK!" # Print if both <cond> are true end end
The following Boolean 'OR' statements are also identical except for precedence.
if <cond> or <cond>  puts "OK!" # Print if either <cond> is true end if <cond> || <cond>  puts "OK!" # Print if either <cond> is true end
The following Boolean 'NOT' statement also comes in alphabetic and symbol form.
if not false puts "OK!" # Print if 'not false' is true end if !false puts "OK!" # Print if !false is true end
The ternary  operator is an old friend from the 'C' and 'C++' languages.   If syntax form is as follows:
<boolean-expression>  ? <expr1>  : <expr2> 
This statement returns <expr1>  if the boolean-expression is true,  <expr2>  if false.
Ruby provides a number of loop constructs.   The while  and until  should be familiar with most programmers.   These syntax for these is as follows:
While boolean-expression  [ do | : ] --- body --- end until boolean-expression  [ do | : ] --- body --- end
The while and until expressions can also be used as modifiers.   In both cases if the expression is a begin/end block the will be executed at least one time.   If is not a block,   it will execute zero or more times depending on the value of the Boolean-expression.
expression  while  boolean-expression expression  until  boolean-expression
Now,  the following loop constructs should be new to 'C'/'C++' programmers.   In particular,  the for  loop is nothing like the 'C' language version.   Let us look at it's syntax.
for name [, name]... in expression  [ do | : ] --- body --- end
A for  is executed like an each loop  (See below).   The difference is that local variables defined within it's loop are available outside to loop.   This is not the case an each loop.
expression.each do | name [, name]... | --- body --- end
Finally, there is the loop  statement that iterates over it's associated block.   It should be noted that is actually an method  defined in the kernel, not a language construct.
loop do --- body --- --- break --- # loop does not provide an exit --- body --- end
The following is an example of a working loop block:
i = 0
loop do
puts "Line: #{i}"
i += 1
break if i > 2
end
Results:
Line: 0
Line: 1
Line: 2
The break, redo, next  and   retry are used to change the flow of while, until,  and iterator  controlled loops.   These changes made to the flow are as follows:
1.  Break -  Terminates the immediately enclosing loop.  Control              resumes at the statement following the block 2.  redo  -  Repeats the loop, without advancing the iterator,              or reevaluating the condition expression. 3.  next  -  Skips to end of loop,  starts next iteration. 4.  retry -  Restarts to loop and reevaluates to condition expression.
The following is an example using break  and next.
i = 1
while true
if i > 10
puts "i > 10 = #{i}"
break # Execute break if 'i' greater than 10
elsif i % 2 == 0
i *= 2
puts "i * 2 = #{i}"
next # Execute next following (i * 2)
end
i += 1
puts "i + 1 = #{i}" # Default execution (i + 1)
end
Results:
i + 1 = 2
i * 2 = 4
i * 2 = 8
i * 2 = 16
i > 10 = 16
CaseThe case statement is a powerful language structure for sorting through a large number of conditions affecting a decision or decisions.   It in it's simpler form is like a multi-way if  statement.   The syntax of this first form is:
case
when <object> boolean-expression <object>
--- body ---
when <object> boolean-expression <object>
--- body ---
else
--- body ---
end
An actual case expression looks like the following:
e
[1, 6, 10, 18, 20 ].each do |numb|
case
when numb == 10
puts "It was 10"
when numb < 5
puts "It was less than 5"
when numb < 20
puts "It was less than 20"
else
puts "Else Called!"
end
end
It was less than 5
It was less than 20
It was 10
It was less than 20
Else Called!
The more common form of the case  statement depends on the case equality operator: '==='.   This form compares the target,  as specified by the case statements parameter, to the various when clause  values.   The following shows the syntax of the 'target' form of case.
case <target>
when <object> # <object> === <target>
--- body ---
when <object> # <object> === <target>
--- body ---
else
--- body ---
end
The nature of the comparison is dependent on the class involved.   Strings are simple string compression between the when clause  value and the target.   Regular expressions are just pattern matches between the when and target values.   Ranges check for the target being within the range specified by the when clause.
[ "exit", 12, "debug", "quit", "fail", 8, "donut"].each do |command|
case command
when "debug"
puts "Debug Found"
when /^\d*$/
puts "Digit Commmand Found"
when "exit", "quit", "fail"
puts "Time to get out!"
when (1..10)
puts "Number between 1 and 10 Found!"
else
puts "Unknown target: #{command}"
end
end
Results:
Time to get out!
Unknown target: 12
Debug Found
Time to get out!
Time to get out!
Number between 1 and 10 Found!
Unknown target: donut
An exception is a way for the programmer to handle various errors.   This can be done several ways.   If the error is recoverable,  then the exception can be caught  and handled by the user.   If it is not recoverable,  the use may still need to process the exception to prevent other errors.  Closing files,  deleting partial results, etc.
However,  there are times when the user wishes to generate an exception.   This generally happens when a program must unwind  the stack to get back to a position where the error can be handled.   As often occurs,  the portion of the program generating the error may have no way of knowing how process the error.
The underlying purpose of exceptions is that the exceptions are passed up through the layers of a program.   At each level,  a particular exception can be caught and any other errors may be passed on.   In a well written program,  all recoverable errors should be caught by the entity that knows how to recover from that error.
The following is an example of a simple exception being raised by the user.   In this first case the error is generated but not handled.   In cases where errors are eventually not  handled,  Ruby is the handler of last resort.   Errors of this sort are reported to the user and the program is aborted.
[ 0, 2, 4,7,8,10].each do |cond|
puts "Cond = #{cond}"
raise(ArgumentError, "Cond is not even number") if (cond % 2) != 0
end
Results:
Cond = 0
Cond = 2
Cond = 4
Cond = 7
.... Cond is not even number (ArgumentError)
How do we handle this situation?   Ruby provides the rescue clause.   The user surrounds the code that may generate an exception with a begin...end  block.   At the end the block a rescue  clause will catch the specified exceptions.
["puts 'start'", "x","puts 'end'"].each do |string|
begin
eval string
raise ArgumentError, "Error Raised" if string.include?('start')
#
rescue NameError => boom
print "String doesn't compile: " + boom
puts ""
#
rescue ArgumentError => bang
print "Argument Error: " + bang
puts ""
end
end
Results
start
Argument Error: Error Raised
String doesn't compile: (eval): undefined local variable or method `x'
end
The previous results show that the first and third strings evaluate correctly.   However, because we raised a bogus exception for strings containing 'start',  an ArgumentError  exception was raised for the first string!   The second string does not evaluate and raises an NaemError  exception.
Rescue will only process the exceptions specified.   After you process an exception,  you may place a 'bare' raise statement that will process any additional exceptions.
Since Exception objects are represented in a hierarchy,  using a high level exception such as Standard Error  will preempt errors such as ArgumentError.   For example replacing the first rescue group above with the following produces a different result.   As you can see below,  the StandardError  clause processed the ArguementError  exception.
:: :: ::
rescue StandardError, NameError => boom # Inserted StandardError
print "String doesn't compile: " + boom
puts ""
:: :: ::
end
Results:
start
String doesn't compile: Error Raised
String doesn't compile: (eval): undefined local variable or method `x'
end
If no exception is detected,  then none of the rescue clauses bodies are executed. In some cases the user may wish execute some code if no exception occurred.   The else  clause is used for this purpose:
[1, 2, 3, 4].each do | x |
begin
print "line: #{x}"
if x > 4
raise ArgumentError, "Argument Error"
end
rescue StandardError => boom
print "String doesn't compile: " + boom
puts ""
else
print " printed Successfully!\n"
end
end
Result:
line: 1 printed Successfully!
line: 2 printed Successfully!
line: 3 printed Successfully!
line: 4 printed Successfully!
% Ruby raise.Rb
Raise.Rb:2:In `raise_exception': Wrong number of argument (ArgumentError)
From raise.Rb:7
Ruby's variables and constants are differentiated by their starting characters:
Object Type First Character ----------------   ---------------- Local Variables Lower Case or '_' Method Parameters Lower Case or '_' Method Names Lower Case or '_' Globals $ Instance Variables @ Class Variables @@ Class Name Upper Case Constants Upper Case
Ruby has a good number of predefined variables.   They all start with a '$' character.   This also classifies them a global.   These are being used less as experience with Ruby grows. A list of some these globals follows:
$$ The process number of the Ruby running this script. $? The status of the last executed child process. $: Load path for scripts and binary modules by load or require. $" The array contains the module names loaded by require. $DEBUG The status of the -d switch. $FILENAME Current input file from $<. Same as $<.filename. $LOAD_PATH The alias to the $:.
There are six pseudo variables:
self nil true false __FILE__ __LINE__self, nil, true, false, __FILE__, and __LINE__.
Finally, there are a number of Pre-defined global constants.   A sampling of these are:
TRUE FALSE NIL ARGV RUBY_VERSION
The value of a variable can be changed with an assignment statement.   The value assigned can be another value, constant, literal, or just about any expression.
Var = 1
Obj = Object.New
@ivar = 'string'
@@cvar = [ 'array' ]
PI = 3.1415926535
$gvar = {'key' => 'value'}
As for attributes we do not set directly,  but rather set and retrieve these values through a proxies(methods).  
Lets look at a typical 'C/C++' shortcut to perform basic operations on a lvalue:
var += 1 # Equivalent: var = var + 1 var *= 2 # Equivalent: var = var * 2
This can be combined with an attribute methods to provide the same functionality:
class C
def i= (n)
@i = n
end
def i
@i
end
end
obj = C.new
obj.i = 1
obj.i += 2
p obj.i
Results:
3
Defined?The method defined?  is a powerful tool for insuring that arbitrary expressions can be successfully executed.   If the argument is not going to result in a valid return value,  then this method returns nil.   The result for arguments that are defined is the return of a string describing the argument.
defined? 5 # "expression" defined? $; # "global-variable" defined? Alien # "constant" defined? Math::PI # "constant" defined? a = 6 # "assignment" defined? 50.integer? # "method"
The following is a simple example of defined?  usage.   Since any valid argument will return something other than nil,  logically testing the result will return true when the argument is defined!
var = 1 if defined? var puts "defined!" end puts defined? var Results: defined! local-variable
The sentence  structure of Ruby is far more relaxed than 'C' or 'C++'.   As we see the following sections,  Ruby provides more flexibility in statement structures and with much less in the way of syntax 'hints' to the parser.
   Whereas those languages require  a semicolon at the end of sentences to terminate them,  Ruby does not.   Ruby only requires a semicolon if you are putting more than one statement on a line,  or indicating a break in the normal sentence structure.
puts "Hello, World!" ; puts "Hello, Redundantly!" Results: Hello, World! Hello, Redundantly!
As long statements on separate lines much to syntax of Ruby is optional.   The following is a small sample of the Ruby syntax.
a = 1 b = 3 if a == 1 # [then] is optional here c = 4 else c = 5 end # When it is expressed on one line then # more tokens are needed to parse the statement if b == 3 then c = 7 else c = 8 end puts "c = " + c.to_s # Here the semicolon stands in for the empty # 'then'structure. if c != 7 ; else c = 9 end puts "c = " + c.to_s Results: c = 7 c = 9
Another feature of Ruby is that indentation is not significant.   If line breaks occur within binary operators or between parenthesis they are treated as white space.
# The following is equivalent to: "1 + 3 * method(6, 7 + 8)"
1 +
3 *
method(
6,
7 + 8 )
If a user wish to insert a line break in a location that would normally be significant it can be quoted  with a backslash.
p 1 + # Line break not significant 2 p 1 \ # Line break is significant and must be 'quoted' + 3 Results: 3 4
If/Unless ModifierThe if and unless modifiers are similar to the while and until  modifiers.   They provide conditional execution of an expression.   The expression is executed if the conditional modifier evaluates as true for if, or false for unless.
expression if boolean-expression expression unless boolean-expression
While/Until ModifierThe while and until modifiers were discussed previously.  
expression  while  boolean-expression expression  until  boolean-expression
Some examples of these modifiers are shown below:
sleep(1) until ready? begin res = get_response(id) end while need_continue?(res)
The class definition syntax is as follows:
class [ scope:: ] classname [ < super-expression ] --- Body --- end
The scope operator usage is not often used and will not be discussed here in this abbreviated discussion.
The class definition will create a class that is a subclass of either Object  if the super-expression  is missing,  or as subclass of super-expression  if it is present.
Class B # Class B is a subclass of Object --- Body --- end Class C < B # Class C is a subclass of B --- Body --- end
The syntax of method definition is shown below.   Methods may be created with a variety of arguments or none at all.
def[ ( arg, ... ) --- Body --- end
Some example method definitions:
def med1 # No Args a = 1 end def med2(arg1, arg2) # 2 Args a = arg1 + arg2 end def med3(arg1, arg2 = 0) # 2 Args - 2nd Arg default = 0 a = arg1 + arg2 end def med4(arg1, *rest) # 1 Arg and array of variable args a = arg1 end def med5(arg1, arg2, &block) # 2 Args plus block a = arg1 + arg2 end
While most methods are defined for a class as a whole,  there are times that a particular object instance requires a unique method or modification of a method.   This is accomplished by defining the method with a object prefix:
def obj.unique_msg[ (arg [,arg] [,arg = default] [,*arg] [, &block] ) --- body --- end
The unique method is stored in a singleton object attached to the instance object.   When the object in question calls the method,  it is not found in that instance.   The search up the hierarchy runs into the attached singleton containing the method before reaching the super-class.
In the following example the method cls_msg  is modified for obj2.   Even obj2 calls the same method until the singleton message is defined.
class C
def cls_msg
puts "class message"
end
end
obj1 = C.new
obj2 = C.new
obj3 = C.new
obj2.cls_msg
def obj2.cls_msg
puts "Singleton message!"
end
obj1.cls_msg
obj2.cls_msg
obj3.cls_msg
Results:
class message # Before obj2.cls_msg defined!
class message
Singleton message! # After obj2.cls_msg defined!
class message
As we discussed in the previous section,  creating a singleton method  also creates an singleton class  or anonymous class.
It should be understood that a singleton class is a virtual class,  it can not be sub-classed or instatiated.   It's only purpose is to provide a place to mount methods and instance variables that are uniquely associated with the specified Class Name.
machine = "Dozer"
class << machine
def blade_down
puts "The #{self} moves dirt"
end
end
machine.blade_down
Results:
The Dozer moves dirt
Multiple substitutions, or Parallel assignment, is another feature of Ruby.   Let us look a simple case. The following assignments are all equivalent.
a, b, c = 1, 2, 3 # Assignment 1 a = 1 # Assignment 2 b = 2 c = 3 a, b c = [1, 2, 3] # Assignment 3
The sort of assignment can be done with any expression that contains multiple values on the right side to the assignment.
tmp = [ 1, 2, 3 ] a, b, c = tmp ret1, ret2 = some_method() # If returns multiple values
The process of parallel assignment begins when the right side(rvalue) of an assignment is evaluated and contains multiple values.   The rvalue side is evaluated left to right and collected into an array.
At this point the left side(lvalue) is inspected for multiple values.   If it is a single variable,  then that variable is loaded with the rvalue array.   If it contains multiple variables,  they are load left to right with the values from the rvalue array.   The results depend on the number of items in the rvalue's and lvalue's.
a, b, c = [1, 2, 3]
puts "a = #{a} b = #{b} c = #{c}"
a, b, c = [1, 2]
puts "a = #{a} b = #{b} c = #{c}"
unless c
puts "nil or false loaded in c"
end
a, b, c = [1, 2, 3, 4]
puts "a = #{a} b = #{b} c = #{c}"
Results:
a = 1 b = 2 c = 3
a = 1 b = 2 c =
nil or false loaded in c
a = 1 b = 2 c = 3
The arrays on both sides to the assignment will be evaluated and 'flatten' to a single dimension before the actual assignment takes place.
a, (b, c, d) = [ 1, [ 2, 3, 4 ] ]
puts "a = #{a} b = #{b} c = #{c} d = #{d}"
a, (b, (c, d)) = [ 1, [ 2, [ 3, 4 ] ] ]
puts "a = #{a} b = #{b} c = #{c} d = #{d}"
(a, b), (c, d) = [ [ 1, 2 ] , [ 3, 4 ] ]
puts "a = #{a} b = #{b} c = #{c} d = #{d}"
Results:
a = 1 b = 2 c = 3 d = 4
a = 1 b = 2 c = 3 d = 4
a = 1 b = 2 c = 3 d = 4
Index and attribute substitution on the left is still possible:
i = 0
arr = [ ]
arr [ i ], arr [ i+1 ], arr [ i+2 ] = 0, 2, 4
p arr
class C
def attr0= (n)
@attr0 = n
end
def attr1= (n)
@attr1 = n
end
def attr2= (n)
@attr2 = n
end
end
obj = C.new
obj.attr0, obj.attr1, obj.attr2 = "a", "b", "c"
p obj.inspect
results:
[0, 2, 4]
@attr0 = "a", @attr1 = "b", @attr2 = "c" # Inspect result cleaned up
Finally, like the asterisk prefixed parameters in methods,  the same can be used for an last element of the lvalue.
first, *rest = 0, 1, 2, 3, 4 p first p rest Results: 0 [1, 2, 3, 4]
Multiple substitution is deeply embedded in the Ruby syntax.   So it should be of no suprise that multiple paramters can be passed by a yield  into a block.   As you will notice yield and blocks follow the same multiple assignment rules as we discussed in the previous section!
def doit
yield("one", "two", "three")
yield("1", "2", "3")
yield("one", "two")
yield("1", "2")
yield("one", "two", "three", "four")
yield("1", "2", "3", "4")
end
doit {|one,two,three| puts "one= #{one} two= #{two} three= #{three}"}
Results:
one= one two= two three= three
one= 1 two= 2 three= 3
one= one two= two three= # Three = nil
one= 1 two= 2 three= # Three = nil
one= one two= two three= three # Forth value thrown away
one= 1 two= 2 three= 3 # Forth value thrown away
AliasThe alias statement creates a new name for methods, operators, globals, and expression backreference(&$, $', $`, $+). A backrefernce holds the various results of an regular expression matchs.
As we will show below,  when a method is aliased it points to a copy of the old method body.   If the method is subsequently changed,  the aliased method still executes to old method body.
def method1 puts "Method one" end alias method2 method1 # method2 now points at body of method1 method1 method2 def method1 puts "Method Changed!" # Change Method1 end method1 method2 Results: Method one Method one Method Changed! # method1 calls new method body Method one # Aliased method2 calls old method1 body
UndefThe undef  command undefines a method name.   This is similar to the unix unlink command.
Class C Undef method_name end
If the method-name has been aliased,  the method's body is still available through the alias.
def method1 puts "Method one" end alias method2 method1 # Name method2 now points at body of method1 method1 method2 undef method1 begin method1 rescue puts "Method1 Gone!" end method2 # Method2 still points at a copy of method1's body Results: Method one Method one Method1 Gone! # Called by 'method1' Method one # Called by 'method2'
If the rescue clause above did not intercept the Name Error,  a message similar to the following would be printed and the program aborted!
... undefined local variable or method `method1' for ... (NameError)
Any time Ruby sees a pound sign,  ' #',  that is not quoted in the form  ' \#',  Ruby will ignore that character and all following characters till the end of line.    Comments are always ignored by Ruby.
# Comment line # comment -- Multi-line comment # :: :: # comment 1 + 1 # Comment -- In-line comment
This form of documentation must be followed by the rdoc  tag to distinguish the block from other forms of documentation,  provided that it is intended as Rdoc Documentation..
=begin rdoc This type is used for documenting programs with Rdoc. How to setup for Rdoc is beyond the scope of this document. =end
However, for use as a method for inserting multi-line comments,  the following form should be used.
=begin It is the multiline comment comment lines continue until =end =end
