Ruby Basics
Program Structure
- one statement per line, or separate by semicolons
- wrap to next line with \
- end-of-line comment with #
- multi-line comment:
=begin
here is my comment
on two different lines
=end
- Hello World:
#!/usr/bin/ruby
puts 'Hello World'
- The
require
statement reads and executes a file immediately, if it hasn't already.
Types
Everything inherits from the Object class and may access the methods of the Kernel module.
- nil is NilClass
- true is TrueClass, false is FalseClass
- Symbol (e.g. :dog)
- Fixnum includes Integer and Float
- Bignum is for arbitrarily large integers
- String
- Array
- Hash
to_s, to_i, to_a # convert to Strings, to Integer, to Array
x.class # to see the class
Variables
Foo # constant
foo # local variable
$foo # global variable
@foo # object/instance variable
@@foo # class variable
Parallel assignment:
x, y, z = 100, 200, 500
Default-based assignment:
x ||= 10 # assigns 10 to x only if x hasn't yet been defined
Methods
def myMethod(a, b=default_value, c*) # define a method, a is a required argument
some code # b is optional
end # c represents an array of further arguments
myMethod(2, 3) # call the method
myMethod 2, 3 # call the method without parentheses
myObject.myMethod(a, b) # call an object method
myClass::myMethod(a, b) # call a class method
Control flow
if
(may optionally throw a then or colon after the condition):
if x < 10
puts "x < 10"
elsif x > 10
puts "x > 10"
else
puts "x is 10"
end
puts "hi there" if name == "Bill"
case
(a colon comes after each test case)
lang = :fr
dog = case lang
when :en: "dog"
when :es: "perro"
when :fr: "chien"
when :de: "Hund"
else "dog"
end
# "chien" is assigned to dog
case scale
when 0: puts "lowest"
when 1..3: puts "medium"
when 4..5: puts "high"
else puts "off scale"
end
# => high
while
(may optionally throw in a do after the condition)
while i < breeds.size
temp << breeds[i].capitalize
i +=1
end
begin
puts temp
temp += 0.1
end while temp < 98.6
unless
is the opposite of if
, until
is the opposite of while
loop with break
:
loop do
print "Type something: "
line = gets
break if line =~ /q|Q/
puts line
end
for
loop and variants:
for i in 1..5
print i, " "
end
for i in 1..5 do print i, " "
5.times { |i| print i, " " }
1.upto(5) { |i| print i, " " }
5.downto(1) { |i| print i, " " }
end a program early:
exit if str.nil? or str.empty?
abort "#{temp} is not a valid number." if temp !~ /-?\d+/
Code Blocks and Iteration
each
, select
, and detect
accept code blocks
single-line form:
[1,2,3].each { |i| puts i}
multi-line form:
[1,2,3].each do |i|
puts i
end
can also do python-style:
for i in [1,2,3]
puts i
end
each_index
to access index of list elements:
list.each_index do |i|
puts "#{i}->#{list[i]}"
end
code blocks as objects:
log = lambda { |msg| puts "[LOG] #{msg}" }
log.call("A test log message.")
log.class # Proc
call a code block from a function (the block needs to be the last argument):
def log(name, message, &level)
print "log file %s: " % name
level.call(message) if level
end
error = lambda { |msg| puts "[ERROR] #{msg}" }
log("test.log", "Here is an error message", &error)
log("test.log", "Here is a warning message") {|msg| puts "[WARN] #{msg}"}
access external variables from a code block:
tax_percent = 6
position = lambda do
"I have always supported a #{tax_percent}% tax on imported limes."
end
puts position.call
# => "I have always supported a 6% tax on imported limes."
tax_percent = 7.25
puts position.call
# => "I have always supported a 7.25% tax on imported limes."
build a custom iterator (yield calls the anonymous code block argument):
class Tree
attr_reader :value
def initialize(value)
@value = value
@children = []
end
def <<(value)
subtree = Tree.new(value)
@children << subtree
return subtree
end
def each
yield value
@children.each do |child|
child.each { |e| yield e }
end
end
end
t = Tree.new("Parent")
child1 = t << "Child 1"
child1 << "Grandchild 1.1"
child1 << "Grandchild 1.2"
child2 = t << "Child 2"
child2 << "Grandchild 2.1"
t.each { |x| puts x }
# Parent
# Child 1
# Grandchild 1.1
# Grandchild 1.2
# Child 2
# Grandchild 2.1
Error Handling
begin
Article.find(1037)
rescue ActiveRecord::RecordNotFound
puts "We couldn't find that record"
end