This is a basic tutorial on Ruby. It assumes you already know a scripting language well. (⁖ Python, PHP, JavaScript, Lisp, …) This intro is designed to quickly get you started, understand the syntax. After reading, you should be able to use standard documentation.
Ruby has a interactive command line. In terminal, type irb.
To find your Ruby version, type ruby --version. This tutorial is based on version 1.9.3.
# -*- coding: utf-8 -*- # Ruby # print Ruby version from within Ruby script p RUBY_VERSION # "1.9.73"
Save the above in a file (⁖ “test.rb”). Run it in terminal like this: ruby test.rb.
To print, use p, puts, print.
# -*- coding: utf-8 -*- # ruby a = 5 b = "rabbit" p a, b, 3 # prints each on a new line. =begin this is a multi-line comment p a, b, 3 can be written as p(a, b, 3) parenthesis are often not necessary =end
What's the difference between {puts, p, print}?
puts prints in a human readable form, and adds newline after each argument. For example, string is printed without quotes, array are printed without the brackets or separators.p prints in a technical form. For example, string will include the quotes. This is good for debugging.print is similar to “puts” but does not add newline.What does newline or indentation mean in Ruby?
p(3); is the same as p(3) on a line by itself.p(3) is the same as p 3.Use single quote to quote string exactly. (literal string). \n has no special meaning inside single quote.
# -*- coding: utf-8 -*- # ruby aa = 'tiger' # using single quote for string exactly as is p aa # prints 「"tiger"」 bb = 'this\n and' p bb # prints in one single line. \n has no special meaning here # single quoted string containing newline or tab will be printed as they are cc = 'a b' p cc # prints 「"a\nb"」.
(Perl tip: Ruby's string quoting mechanisms is similar to Perl's. 〔☛ Python, Ruby, Perl: Quoting Strings〕)
Use double quote for strings that contain newline escape \n, or include variable values or Ruby code.
# -*- coding: utf-8 -*- # ruby mm = "tiger\nsnake" puts mm # prints each word in separate line
You can use \n for newline, and \t for tab, etc.
To evaluate a variable or Ruby code within a string, use #{…}.
# -*- coding: utf-8 -*- # ruby # put variable value inside a string aa = 4 bb = "there are #{aa} tigers" p bb # prints “there are 4 tigers” # eval Ruby code inside a string p "there are #{1+2} tigers" # prints “there are 3 tigers”
See: Ruby: Quoting Long String and Heredoc.
Use method length to get number of character in string.
# -*- coding: utf-8 -*- # ruby "2834".length # ⇒ 4
Get substring.
# -*- coding: utf-8 -*- # ruby # get one character p "abcdefg"[2] # ⇒ c # string can contain Unicode p "α♥β"[1] # ⇒ ♥ # get substring, start at index 2, get 3 chars p "abcdefg"[2, 3] # ⇒ cde
String join.
# -*- coding: utf-8 -*- # ruby # string join. Use + p "aa" + "bb" # ⇒ aabb
Replacing substring.
# -*- coding: utf-8 -*- #ruby # replacing string myString = "0123456789" myString[1]= "a" p myString # ⇒ 「"0a23456789"」 # start at index 1, replace 8 chars myString[1,8]= "what" p myString # ⇒ 「"0what9"」
Simple string matching.
# -*- coding: utf-8 -*- # ruby # get the start index of a substring p "in love?".index("love") # ⇒ 3 p "in love?".index("456") # ⇒ nil (not found)
Split a string into a array.
# -*- coding: utf-8 -*- #ruby p "once upon a time".split(" ") # ⇒ ["once", "upon", "a", "time"]
# -*- coding: utf-8 -*- # ruby # string to int p "3".to_i # ⇒ 3 # string to float p "3".to_f # ⇒ 3.0 # int to string p 3.to_s # ⇒ "3" # int to float p 3.to_f # ⇒ 3.0 # float to string p 3.0.to_s # ⇒ "3.0" # float to int p 3.0.to_i # ⇒ 3 # IMPORTANT: decimal number such as 「3.」 must be written with 0 at end, like this 「3.0」, because dot is used for method call
Ruby does not automatically convert between strings and integers like Perl.
In Ruby, when writing decimal number, you must end it with a .0. For example, write 1.0, not 1..
# -*- coding: utf-8 -*- # ruby # decimal number must end with dot and digit p 5/2 # 2 p 5/2.0 # 2.5 p 5/2. # syntax error, unexpected end-of-input, expecting '('
In Ruby, practically everything is a “Object” in the sense of Object Oriented programing (OOP).
Even numbers and strings are objects.
What this effective means is that for any “thing” in Ruby, you can append it with .‹name› where the ‹name› is a method (function).
For example, 3 is a thing in Ruby. So, it has many methods, for example: to_i (convert to integer), to_s (convert to string), and you can call it like this: 3.to_i.
To find the methods of a thing, use the method methods. Example:
# -*- coding: utf-8 -*- # ruby # methods for a integer object p 5.methods # ⇒ [:to_s, :-@, :+, :-, :*, :/, :div, :%, :modulo, :divmod, :fdiv, :**, :abs, :magnitude, :==, :===, :<=>, :>, :>=, :<, :<=, :~, :&, :|, :^, :[], :<<, :>>, :to_f, :size, :zero?, :odd?, :even?, :succ, :integer?, :upto, :downto, :times, :next, :pred, :chr, :ord, :to_i, :to_int, :floor, :ceil, :truncate, :round, :gcd, :lcm, :gcdlcm, :numerator, :denominator, :to_r, :rationalize, :singleton_method_added, :coerce, :i, :+@, :eql?, :quo, :remainder, :real?, :nonzero?, :step, :to_c, :real, :imaginary, :imag, :abs2, :arg, :angle, :phase, :rectangular, :rect, :polar, :conjugate, :conj, :between?, :nil?, :=~, :!~, :hash, :class, :singleton_class, :clone, :dup, :initialize_dup, :initialize_clone, :taint, :tainted?, :untaint, :untrust, :untrusted?, :trust, :freeze, :frozen?, :inspect, :methods, :singleton_methods, :protected_methods, :private_methods, :public_methods, :instance_variables, :instance_variable_get, :instance_variable_set, :instance_variable_defined?, :instance_of?, :kind_of?, :is_a?, :tap, :send, :public_send, :respond_to?, :respond_to_missing?, :extend, :display, :method, :public_method, :define_singleton_method, :object_id, :to_enum, :enum_for, :equal?, :!, :!=, :instance_eval, :instance_exec, :__send__, :__id__] # methods for a string object p "rabbit".methods # ⇒ [:<=>, :==, :===, :eql?, :hash, :casecmp, :+, :*, :%, :[], :[]=, :insert, :length, :size, :bytesize, :empty?, :=~, :match, :succ, :succ!, :next, :next!, :upto, :index, :rindex, :replace, :clear, :chr, :getbyte, :setbyte, :byteslice, :to_i, :to_f, :to_s, :to_str, :inspect, :dump, :upcase, :downcase, :capitalize, :swapcase, :upcase!, :downcase!, :capitalize!, :swapcase!, :hex, :oct, :split, :lines, :bytes, :chars, :codepoints, :reverse, :reverse!, :concat, :<<, :prepend, :crypt, :intern, :to_sym, :ord, :include?, :start_with?, :end_with?, :scan, :ljust, :rjust, :center, :sub, :gsub, :chop, :chomp, :strip, :lstrip, :rstrip, :sub!, :gsub!, :chop!, :chomp!, :strip!, :lstrip!, :rstrip!, :tr, :tr_s, :delete, :squeeze, :count, :tr!, :tr_s!, :delete!, :squeeze!, :each_line, :each_byte, :each_char, :each_codepoint, :sum, :slice, :slice!, :partition, :rpartition, :encoding, :force_encoding, :valid_encoding?, :ascii_only?, :unpack, :encode, :encode!, :to_r, :to_c, :>, :>=, :<, :<=, :between?, :nil?, :!~, :class, :singleton_class, :clone, :dup, :initialize_dup, :initialize_clone, :taint, :tainted?, :untaint, :untrust, :untrusted?, :trust, :freeze, :frozen?, :methods, :singleton_methods, :protected_methods, :private_methods, :public_methods, :instance_variables, :instance_variable_get, :instance_variable_set, :instance_variable_defined?, :instance_of?, :kind_of?, :is_a?, :tap, :send, :public_send, :respond_to?, :respond_to_missing?, :extend, :display, :method, :public_method, :define_singleton_method, :object_id, :to_enum, :enum_for, :equal?, :!, :!=, :instance_eval, :instance_exec, :__send__, :__id__] xx = [3,4,5] # array # methods for a array object. You can also simply do 「p [].methods」 p xx.methods # ⇒ [:inspect, :to_s, :to_a, :to_ary, :frozen?, :==, :eql?, :hash, :[], :[]=, :at, :fetch, :first, :last, :concat, :<<, :push, :pop, :shift, :unshift, :insert, :each, :each_index, :reverse_each, :length, :size, :empty?, :find_index, :index, :rindex, :join, :reverse, :reverse!, :rotate, :rotate!, :sort, :sort!, :sort_by!, :collect, :collect!, :map, :map!, :select, :select!, :keep_if, :values_at, :delete, :delete_at, :delete_if, :reject, :reject!, :zip, :transpose, :replace, :clear, :fill, :include?, :<=>, :slice, :slice!, :assoc, :rassoc, :+, :*, :-, :&, :|, :uniq, :uniq!, :compact, :compact!, :flatten, :flatten!, :count, :shuffle!, :shuffle, :sample, :cycle, :permutation, :combination, :repeated_permutation, :repeated_combination, :product, :take, :take_while, :drop, :drop_while, :pack, :entries, :sort_by, :grep, :find, :detect, :find_all, :flat_map, :collect_concat, :inject, :reduce, :partition, :group_by, :all?, :any?, :one?, :none?, :min, :max, :minmax, :min_by, :max_by, :minmax_by, :member?, :each_with_index, :each_entry, :each_slice, :each_cons, :each_with_object, :chunk, :slice_before, :nil?, :===, :=~, :!~, :class, :singleton_class, :clone, :dup, :initialize_dup, :initialize_clone, :taint, :tainted?, :untaint, :untrust, :untrusted?, :trust, :freeze, :methods, :singleton_methods, :protected_methods, :private_methods, :public_methods, :instance_variables, :instance_variable_get, :instance_variable_set, :instance_variable_defined?, :instance_of?, :kind_of?, :is_a?, :tap, :send, :public_send, :respond_to?, :respond_to_missing?, :extend, :display, :method, :public_method, :define_singleton_method, :object_id, :to_enum, :enum_for, :equal?, :!, :!=, :instance_eval, :instance_exec, :__send__, :__id__]
Method name ending in “!” means it changes the variable's value. For example,
‹myArray›.reverse returns a reversed array.
‹myArray›.reverse! also changes the variable ‹myArray›.
Methods ending in “?” means it returns true or false. (aka “predicate function”.)
In Ruby, variables do not need declaration. Variable does not have a type. Values do have types. The type is a the class they belong to.
Finding the type of a value.
# -*- coding: utf-8 -*- # ruby p 5.kind_of?(Integer) # ⇒ true p 5.class # ⇒ Fixnum p "5".class # ⇒ String p [3,4,5].class # ⇒ Array p true.class # ⇒ trueClass p false.class # ⇒ falseClass p nil.class # ⇒ nilClass
| Starting Symbol | Explanation |
|---|---|
a…z or _ | lower case = local variable |
A…Z | upper case = Constant |
$ | global variable |
@ | instance variable (of a class in OOP) |
@@ | class variable (of a class in OOP) |
# -*- coding: utf-8 -*- # ruby a = 3 $a = 4 @a = 5 @@a = 6 p defined?(a) # ⇒ "local-variable" p defined?($a) # ⇒ "global-variable" p defined?(@a) # ⇒ "instance-variable" p defined?(@@a) # ⇒ "class variable"
Constants starts with a capital letter. This is enforced by Ruby interpreter. However, Ruby actually allows you to redefine a constant. When you do so, it gives a warning.
# -*- coding: utf-8 -*- # ruby C2 = 5 # constant C2 = 6 # warning: already initialized constant C2 p C2 # prints 6
Ruby has several predefined global variables. They are somewhat similar to Perl or unix shell.
| Variable Name | Variable Value |
|---|---|
$0 | name of the Ruby script file currently executing |
$* | command line arguments used to invoke the script. (a array) |
$$ | Ruby process ID |
$? | exit status of last executed child process |
| Variable Name | Variable Value |
|---|---|
$@ | location of latest error |
$_ | string last read by gets |
$. | line number last read by interpreter |
$/ | input record separator |
$\ | output record separator |
| Variable Name | Variable Value |
|---|---|
$& | regex. Last matched string |
$~ | regex. Last regexp match. Returns a array |
$n | regex. nth subexpression in the last match (same as $~[n]) |
$= | regex. case-insensitivity flag |
For complete list of predefined vars, see: Ruby: Predefined Variables.
true and false are builtin objects.
The following evaluates to false:
falsenilEverything else evaluates to true (including zero, empty string or array.). (this is similar to emacs lisp)
Simple “if then”.
# -*- coding: utf-8 -*- # ruby xx = 4 if xx > 0 then p 1 end # prints 1 # formatted in multiple lines if xx > 0 then p 1 end # prints 1
“if then else” and multilpe “elsif”.
# -*- coding: utf-8 -*- # ruby xx = 4 if xx > 0 then p 1 else p 0 end # prints 1 # multiple “else if” if xx > 4 then p 1 elsif xx < 4 then p 0 elsif xx == 4 then p "yy" end # prints "yy" # formatted in one line if xx > 4 then p 1 elsif xx < 4 then p 0 elsif xx == 4 then p "yy" end # prints "yy" # formatted in another way if xx > 4 then p 1 elsif xx < 4 then p 0 elsif xx == 4 then p "yy" end # prints "yy"
“if” construct is also a expression. It returns the value of the last line of the block executed.
# -*- coding: utf-8 -*- # ruby xx = 4 p(if xx > 0 then 1 end) # prints 1 p(if xx > 0 then 1 else 0 end) # prints 1 p( if xx > 4 then 1 elsif xx < 4 then 0 elsif xx == 4 then "yes" end ) # prints "yes" # short form p( xx > 2 ? 1 : 0) # prints 1
“everything” in Ruby is a expression. They return a value. This is similar to most functional programing languages (⁖ Emacs Lisp, JavaScript, Mathematica).
Using “case”. (in other languages, it's also known as {which, switch, cond})
# -*- coding: utf-8 -*- # ruby xx = 3 myResult = case xx when 1 then "one" when 2 then "two" when 3 then "three" when 3 then "four" else "cat" end p myResult # ⇒ “three”
“case” construct is also a expression. It returns a value.
“for” loop.
# -*- coding: utf-8 -*- # ruby for ii in 0..4 do p ii end # prints 0 to 4
Nested “for” loop.
# -*- coding: utf-8 -*- # ruby for ii in 1..2 do for jj in 1..3 do puts "#{ii}, #{jj}" end end # prints # 1, 1 # 1, 2 # 1, 3 # 2, 1 # 2, 2 # 2, 3 # can also be written in one line. for ii in 1..2 do for jj in 1..3 do puts "#{ii}, #{jj}" end end
“while” loop.
# -*- coding: utf-8 -*- # ruby ii = 1 while ii < 9 do puts ii; if ii == 5 then break end ii += 1 end # prints 1 to 5
Semicolon can be replaced by newline.
Creating a range. Use (1..5).to_a. This creates a array with elements 1 to 5.
# -*- coding: utf-8 -*- # ruby a = (1..5).to_a # “to_a” converts to array p a # ⇒ [1, 2, 3, 4, 5]
# -*- coding: utf-8 -*- # ruby p (1..5).class # ⇒ Range # methods for the range p (1..5).methods # ⇒ [:==, :===, :eql?, :hash, :each, :step, :begin, :end, :first, :last, :min, :max, :to_s, :inspect, :exclude_end?, :member?, :include?, :cover?, :to_a, :entries, :sort, :sort_by, :grep, :count, :find, :detect, :find_index, :find_all, :select, :reject, :collect, :map, :flat_map, :collect_concat, :inject, :reduce, :partition, :group_by, :all?, :any?, :one?, :none?, :minmax, :min_by, :max_by, :minmax_by, :each_with_index, :reverse_each, :each_entry, :each_slice, :each_cons, :each_with_object, :zip, :take, :take_while, :drop, :drop_while, :cycle, :chunk, :slice_before, :nil?, :=~, :!~, :<=>, :class, :singleton_class, :clone, :dup, :initialize_dup, :initialize_clone, :taint, :tainted?, :untaint, :untrust, :untrusted?, :trust, :freeze, :frozen?, :methods, :singleton_methods, :protected_methods, :private_methods, :public_methods, :instance_variables, :instance_variable_get, :instance_variable_set, :instance_variable_defined?, :instance_of?, :kind_of?, :is_a?, :tap, :send, :public_send, :respond_to?, :respond_to_missing?, :extend, :display, :method, :public_method, :define_singleton_method, :object_id, :to_enum, :enum_for, :equal?, :!, :!=, :instance_eval, :instance_exec, :__send__, :__id__]
Creating a array.
# -*- coding: utf-8 -*- # ruby # creating a array aa = [3, "four",5] p aa # prints [3, "four", 5] # another way bb = Array.new(3) p bb # prints [nil, nil, nil] # create array of 3 elements, with value of 1 cc = Array.new(3,1) p cc # prints [1, 1, 1] # array can be nested aa = [0, 1, 2, ["8", 9], 3]
Counting elements:
# -*- coding: utf-8 -*- # ruby aa = [3, "four",5] p aa.length # ⇒ 3
Getting a element.
# -*- coding: utf-8 -*- # ruby aa = [0, 1, 2, 3, "four", 5, [6, 8], 7] p aa[0] # ⇒ 0 p aa[-1] # ⇒ 7 p aa[6] # ⇒ [6, 8] p aa[6][0] # ⇒ 6
Finding the index of a element.
# -*- coding: utf-8 -*- # ruby aa = [3, "four",5] p aa.index("four") # ⇒ 1 p aa.index("7") # ⇒ nil
Extracting a sequences of elements.
# -*- coding: utf-8 -*- # ruby aa = [0, 1, 2, 3, "four", 5, 6, 7] # starting at index 3, get 2 elements p aa[3, 2] # ⇒ [3, "four"]
Modify a element.
# -*- coding: utf-8 -*- # ruby aa = [0, 1, 2, 3, "four"] aa[1] = "one" p aa # ⇒ [0, "one", 2, 3, "four"]
Adding element into array.
# -*- coding: utf-8 -*- # ruby aa = [0, 1, 2] p aa.insert(1,"b") # ⇒ [0, "b", 1, 2] p aa # ⇒ [0, "b", 1, 2]
Appending a element.
# -*- coding: utf-8 -*- # ruby # appending to array aa = [0, 1] aa << 2 p aa # ⇒ [0, 1, 2] aa << [5, 6] p aa # ⇒ [0, 1, 2, [5, 6]]
Removing Element.
# -*- coding: utf-8 -*- # ruby aa = [0, "b", 2] aa.delete_at(1) # ⇒ "b" p aa # ⇒ [0, 2]
push and pop. (append or remove a element from the end.)
# -*- coding: utf-8 -*- # ruby aa = [0, 1, 2] # add a element to the end p aa.push("a") # ⇒ [0, 1, 2, "a"] # original array also changed p aa # ⇒ [0, 1, 2, "a"] # pop removes the last element, and returns that p aa.pop # ⇒ "a" p aa # ⇒ [0, 1, 2]
Join 2 arrays.
# -*- coding: utf-8 -*- # ruby aa = [0, 1, 2, 3] bb = ["four", 5] p aa + bb # ⇒ [0, 1, 2, 3, "four", 5]
Array Union, Intersection, Difference
# -*- coding: utf-8 -*- # ruby aa = [0, 8, 7, 3, 1] bb = [3, 4] # difference p aa - bb # ⇒ [0, 8, 7, 1] # intersection p aa & bb # ⇒ [3] # union p aa | bb # ⇒ [0, 8, 7, 3, 1, 4]
Get uniq elements.
# -*- coding: utf-8 -*- # ruby aa = [0, 7, 3, 7] # uniq p aa.uniq # ⇒ [0, 7, 3] # original array not modified p aa # ⇒ [0, 7, 3, 7] # uniq, modify original array aa.uniq! p aa # ⇒ [0, 7, 3]
Sorting array.
# -*- coding: utf-8 -*- # ruby aa = [0, 4, 2] aa.sort # ⇒ [0, 2, 4] # original not changed p aa # ⇒ [0, 4, 2] # change original aa.sort! # ⇒ [0, 2, 4] p aa # ⇒ [0, 2, 4]
Array Comparison
# -*- coding: utf-8 -*- # ruby aa = [0, 1, 2] bb = [0, 1, 2.0] cc = [0, 1, "2"] # check if 2 arrays are the same (ignores type.) p aa == bb # ⇒ true p aa == cc # ⇒ false # check if 2 arrays are the same, and each element has the same type p aa.eql?(bb) # ⇒ false
#-*- coding: utf-8 -*- # ruby # define a keyed list hh = {:john => 3, :mary => 4, :jane => 5, :vicky => 7} p hh # ⇒ {:john=>3, :mary=>4, :jane=>5, :vicky=>7} # getting value from a key p hh[:mary] # 4 # add a entry hh[:pretty] = 99 p hh # ⇒ {:john=>3, :mary=>4, :jane=>5, :vicky=>7, :pretty=>99} # delete a entry hh.delete :vicky p hh # ⇒ {:john=>3, :mary=>4, :jane=>5, :pretty=>99} # get all keys p hh.keys() # ⇒ [:john, :mary, :jane, :pretty] # get all values p hh.values() # ⇒ [3, 4, 5, 99] # check if a key exists p hh.has_key? :mary # ⇒ true p hh.has_value? :jenny # ⇒ false
In Ruby, :something is a “symbol”. It's similar to lisp's symbol. For practical purposes, you can think of it as a static string. Whenever you need to use a string as a label, you should use symbol instead.
In the above example, you could replace all symbols by string. example
#-*- coding: utf-8 -*- # ruby # hash, with keys as string aa = {'john' => 3, 'mary' => 4, 'jane' => 5} # hash, with keys as symbol. bb = {:john => 3, :mary => 4, :jane => 5} # using symbol is more efficient, because each string is a full object
In Ruby, “everything” is a object. So, creating a string creates a object, which often means it's slow. So, the “symbol” datatype is a solution for that.
…
Use backticks `…` to call shell commands.
# -*- coding: utf-8 -*- # ruby # calling unix commands puts `ls -Al` =begin prints the following total 4786 -rw-------+ 1 h3 None 27264 Nov 30 15:48 .bash_history -rwx------+ 1 h3 None 403 Nov 30 15:48 .bashrc -rwx------+ 1 h3 None 285 Nov 18 22:57 .emacs … =end
…
The following is a example of defining a function.
# -*- coding: utf-8 -*- # ruby def f 3 end puts f
The keyword “return” can be used to return value and exit code. Else, the last expression of a function definition is its returned value.
# -*- coding: utf-8 -*- # ruby def f(x) x+1 end puts f(4) # prints 5
# -*- coding: utf-8 -*- # ruby # function with default value def f(x = 3) x+1 end puts f # prints 4
# -*- coding: utf-8 -*- # ruby # example of defining a function with variable number of parameters def ff(*xx) xx.each {|string| puts string} end ff(3,4,5)
…
Defining a class. Class name should start with a capital letter.
# -*- coding: utf-8 -*- # ruby # Object example class Xyz # initializer def initialize(ii) @xx = ii # @xx is a instance variable end # a method. Return the instance variable @xx def mm @xx end # a another method. def nn(aa) @xx + aa end end # create a object. myobj = Xyz.new(3) # call a method p myobj.mm # 3 # call another method with argument p myobj.nn(2) # 5
Instance variable must be accessed by methods only. You must define methods to get instance variable's value, or change it. (this is different from Java or Python.)
@.@@.# -*- coding: utf-8 -*- # ruby # Module name must start with Capital letter module Xyz # … end