Ruby Basics: Difference between revisions

From Wiki
Jump to navigation Jump to search
Line 134: Line 134:
1.upto(5) { |i| print i, " " }
1.upto(5) { |i| print i, " " }
5.downto(1) { |i| print i, " " }
5.downto(1) { |i| print i, " " }
</source>
end a program early:
<source lang="ruby">
exit if str.nil? or str.empty?
abort "#{temp} is not a valid number." if temp !~ /-?\d+/
</source>
</source>



Revision as of 23:49, 4 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.

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

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