Learning Ruby

Foreword

This document assumes you know some other languages already, preferrably Java, PHP or something with a similiar C style syntax.

Why and about ruby

In ruby, _everything_ is a class/object, similiar to javascript. It also allows patching code on runtime and has decent reflection stuff and all you need and ever want.

Datatypes

Everything is an object in ruby, but you should know that there is a special type of string, the "SYMBOL".
A Symbol is a const string, and the notation is like :mysym

Most objects support the following methods to convert between common types:

'foo'.to_i # => Exception?
'5'.to_i # => 5
5.to_s # => "5"
5.to_f # = 5.0
'foo'.to_sym # => :foo
:foo.to_s # => "foo"

A short syntax

In ruby you can write very short and elegant code. Like in perl it might be hard to read then for beginners, or even for yourself.

# Prepended if
foo = bar if bar != nil

# unless; the opposite of if
foo = bar unless bar.nil?

# No need for return
def default_username
  "Peter"
end

# Semicolon only needed for multiple statements in a single line
def default_username; "Peter"; end

# No need for parantheses
class Peter
  def i_could_be_an_attribute; 4; end
end
Peter.new.i_could_be_an_attribute # => 4

Duct Typing




Hashes and Arrays

Ruby is like Javascript here.

myarray = [1,2,3]
myhash = {foo:'bar', blub:[1,2,3], :foo2 => "bar2"}

Just note that foo: 'bar' is the same as :foo => 'bar'

Strings and qu(ai)rks

Similar to PHP, you can define Strings as literal or with interpreter support.

s1 = '#{2.minutes}' # => "#{2.minutes}":String
s2 = "#{2.minutes}" # => "120":String

In ruby you can have extra fancyness: %q/%Q allows both quotes without escaping.
s1 = %q{'"*"'"}.length # => 5  

Re(ge)x(p)

Here ruby is a bit like Perl.
TODO: explain =~
matches = /^[a-z][a-z_0-9]{15}$/i.match(s) # => nil||Array
Regexp.new("^[a-z][a-z_0-9]{#{len}}$", true).match(s) # => nil||Array

How to class in ruby?!?!

Ruby is quite different from C++, Java and PHP when it comes to class definitions.
Instance variables are donated as @myinstancevar. They are only visible within the class, no inheritance.
To make an instance variable visible you have to create a public method which returns it, or use reflection: myobj.instance_variable_get(:@myinstancevar)

Code Example:

class MyClass
  @i_am_static_because_i_am_not_inside_a_function_o_o = 3
  
  def initialize(arg=nil)
    # I am the constructor, called on MyClass.new
    @a_normal_instance_var = 5
  end
  
  def get_normal
    @a_normal_instance_var
  end
  
  def a_normal_instance_var=(value)
    # Ruby methods can contain =(setter), ?(beauty), and !(assign to self, call_exception, force, whatever you feel like an exclamation could mean)
    @a_normal_instance_var = value
  end
  
  def [](index)
    "You have sent me [#{index}]"
  end
  
  def self.i_am_a_static_method
    @i_am_static_because_i_am_not_inside_a_function_o_o = 8
  end
  
  private
  def i_am_a_private_method
  end
  
end

Call static methods like this:

MyClass.i_am_a_static_method
MyClass.new(5).class.i_am_a_static_method

Monkeypatching!

Now my favorite part about ruby... patching existing code :)

It is simple as that; every definition you write extends the existing defintion:

class MyClass
  def foo
    "Hello"
  end
end

class MyClass
  def bar
    "Now MyClass has foo and bar methods \o/"
  end
end

class MyClass
  def foo
    "Hello World, i overwrote you!"
  end
end

But beware; Monkeypatching is not a good coding practice and can easily lead to problems!

Dynamic Reflections and stuff

You probably want to use dynamic methods and attributes.
Simply use "send" to call methods dynamically: myobj.send('thefunc', arg1, arg2)
Use myobj.instance_variable_get, myobj.instance_variable_set, myobj.instance_variable_defined? to handle attributes.