Ruby Basics: Difference between revisions
Line 57: | Line 57: | ||
x ||= 10 # assigns 10 to x only if x hasn't yet been defined | x ||= 10 # assigns 10 to x only if x hasn't yet been defined | ||
</source> | </source> | ||
== Operators == | |||
Ternary operator: | |||
<source lang="ruby"> | |||
x = ( temp < 70 ) ? "cold" : "hot" | |||
</source> | |||
Spaceship operator: | |||
<source lang="ruby"> | |||
a<=>b | |||
</source> | |||
* if a < b it returns -1 | |||
* if a = b it returns 0 | |||
* if a > b it returns 1 | |||
== Methods == | == Methods == |
Revision as of 21:51, 5 October 2011
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. - Add this to the bottom of a Ruby file to run it directly (usually for debugging):
if $0 == __FILE__
my_test_method
end
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
A word on booleans
Some may be used to thinking that a false value may be represented as a zero, a null string, a null character, or various other things. But in Ruby, all of these are true; in fact, everything is true except false and nil.
Variables
Foo # constant
foo # local variable
$foo # global variable
@foo # object/instance variable
@@foo # class variable
Parallel assignment:
x, y, z = 100, 200, 500
x = y = z = 0
Default-based assignment:
x ||= 10 # assigns 10 to x only if x hasn't yet been defined
Operators
Ternary operator:
x = ( temp < 70 ) ? "cold" : "hot"
Spaceship operator:
a<=>b
- if a < b it returns -1
- if a = b it returns 0
- if a > b it returns 1
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
singleton methods are tied to an object, not the class:
str = "Hello, world!"
str2 = "Goodbye!"
def str.spell
self.split(/./).join("-")
end
str.spell # "H-e-l-l-o-,- -w-o-r-l-d-!"
str2.spell # error!
The return
at the end of a method can be omitted. A method always returns the last expression evaluated in its body, regardless of where that happens.
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
begin
x = Math.sqrt(y/z)
# ...
rescue => err
puts err
end
begin
# Error-prone code...
rescue
# Handle exceptions
ensure
# This code is always executed
end
Runtime Evaluation
def calculate(op1, operator, op2)
string = op1.to_s + operator + op2.to_s
# operator is assumed to be a string; make one big
# string of it and the two operands
eval(string) # Evaluate and return a value
end
@alpha = 25
@beta = 12
puts calculate(2, "+", 2) # Prints 4
puts calculate(5, "*", "@alpha") # Prints 125
puts calculate("@beta", "**", 3) # Prints 1728
puts "Method name: "
meth_name = gets
puts "Line of code: "
code = gets
string = %[def #{meth_name}\n #{code}\n end] # Build a string
eval(string) # Define the method
eval(meth_name) # Call the method
if platform == Windows
def my_action
action1
end
elsif platform == Linux
def my_action
action2
end
else
def my_action
default_action
end
end