|
Tip
|
Do not use prepackaged Ruby on Linux distributions. |
On Linux use rbenv package manager with the
ruby-build extension to install Ruby.
For windows there is an installer Ruby Installer simplifies the installation to the "windows standard approach".
The simplest way to install Ruby on macOS is to use homebrew package manager
$ brew install rubyin case there is a need to have multiple installations
rbenv
is a good tool to use. Another popular tool is called rvm but nowadays they do too
much magic and we recommend using rbenv instead.
|
Tip
|
Usually you put ruby and relates command on PATH so you do not need to always
specify the whole path to the executable. With tools like rbenv this is done for you.
|
$ ruby -vruns Ruby and prints it’s version. Simplest way to verify that your instalation works as expected.
$ ruby script.rbinterprets the script.rb. However instead of running the script explicitly, you can add the shebang line to your script
#!/usr/bin/env rubyand make it executable (chmox +x script.rb) and run it simply as ./script.rb.
Ruby a programming language with following aspects
Ruby can be used for writing scripts, one-liners, web applications and even for mobile and desktop applications.
MRI is the Ruby reference implementation, with several other implementations like JRuby, Rubinius,
IronRuby or MagLev. As well, there is ISO standard implemented in mruby.
There are some implicit conversions (e.g. every object has to_s method to provide
string representation) but in most cases in case you try to operate on different types
Ruby will complain, unless such operation is explicitly provided.
5 + "a" # => TypeError: String can't be coerced into FixnumThe type of a variable is defined by the value assigned to that variable. There is no explicit type information in the code.
a = "string"-
programming languages: Ruby (Rubinius), compilers (LessJS)
-
web applications: Github, Gitlab, Redmine, BaseCamp
-
devops tools: Puppet/Chef/Vagrant
-
cloud platforms: OpenShift (v2)
-
cloud management: Foreman, ManageIQ
-
VIM/Emacs scripts
-
static pages generators - Jekyll
-
programming tools
-
class names are CamelCase
-
file names reflect class names in snake_case format
-
method names are snake_case
-
constants are UPPER_CASE
-
indent by 2 spaces
-
methods returning boolean values end with
? -
methods mutating state end with
!
Basic and most explicit syntax looks like
puts("hello world!");However the parenthesis are optional in case the only one interpretation of the expression
puts "hello world!";and semicolons are optional as well
puts "hello world!"String use either quotation marks " or apostrophes '. Apostrophes does not provide
string substitution as quotations marks do.
a = 'Hello' # => "Hello"
b = "#{a} world" # => "Hello world"
b = '#{a} world' # => "\#{a} world"Ruby allows usage of special characted in method names. The standard is to use
-
the question mark
?for methods that return boolean value -
the exclamation mark
!for methods that mutate the object
1.even? # => false
"ruby".upcase.reverse # => 'YBUR'
"ruby".size.even? # => trueAs mentioned above in Ruby everything is an object, including arrays or numbers. However there are special syntax shorthands to create instances of special classes.
Ruby has two basic number classes Fixnum and Float.
a = 1 # => 1
a.class # => Fixnum
b = 1.1 # => 1.1
b.class # => FloatSpecial value that represents "nothing" is nil.
a = nil # => nilIn a boolean expression, nil is considered false, i.e. it’s only of two possible
values that are not considered true.
As usual there is either true or false.
a = true # => true
b = false # => false
a && b # => false
a || b # => trueArrays is an ordered sequence of values. There are no restrictions on what types can be in a single array.
["a", 1, true] # => ["a", 1, true]Hash is a structure that maps key to a value.
{"a" => true, "b": false} # => {"a"=>true, :b=>false}There are two approaches how to write the mapping, either rocket style
key => valueor json style
key: valueYou can use both syntaxes, however with the json style the value is converted
to symbol, so in case you need to use String or some other type, or get the name
of the key from a variable, you need to use the rocket style. Several well-known
coding guidelines recommend (and enforce) using rockets everywhere.
Methods are called by using the .. Operators are actually methods.
3 + 3 # => 6
3.+(3) # => 6
[1,2][0] #=> 1
[1,2].[](0) # => 1Ruby has global variables prefixed by $.
$stdoutClasses and object can use class variables, though there are not used
very much. Prefer @instance_variables in class-level methods, as
they have more predicatable behavior.
@@class_variables = 1Objects have instance variables.
@instance_variable = 1Local variables have no prefix.
local_variable = 1And finally constants are all upper case.
CONSTANT = 1Everything is considered true except false and nil.
a = nil
b = ""
if a
"we do not get in here"
elsif b
"we got here"
else
"we did not get here"
endRuby has negative variant to if called unless. Essentially unless bool_expr is
equivalent to if !(bool_expr). It is used the same way as normal if.
a = nil
b = ""
unless a
"we do get in here"
elsif b
"we did not get here"
else
"we did not get here"
endRuby has inline method of using conditionals called modifier statements.
puts "Hello" if true
puts "Hello" unless falseTernary operator is available as well.
experssion ? 'was evaluated true' : 'was evaluated false'Another way to do conditions is to use case statement.
case input
when 'q', 'e'
quit
when 'f'
format
else
help
endCase statement can as well check on variable class.
case var
when String
"it's string"
when Class
"it's class"
when Number
"it's number"
endAnother way to use case statement is to use it as if and elsif.
case
when a == "a"
"a equals a"
when b == "b"
"b equals b"
endThere are basic logical expressions
-
and
&& -
or
|| -
not
!
as well && can be replaced with and, || can be replaced with or and ! can
be replaced with not.
There are basic comparison operators
-
equal
== -
not equal
!= -
lesser then
< -
greater then
> -
lesser then or equal
⇐ -
greater then or equal
>= -
regular expression match
=~
Regular expressions are enclosed with /. The simplest way is to use the regexp
operator.
string = 'localhost:2000'
string =~ /.*:.+/ # 0
string =~ /(.)*:(.)+/ # sets $1 a $2as well there is a match method on string.
data = string.match(/^(.):(\d+)$/)
data[1] # => localhost
data[2] # => 2000while repeats as long as the condition is true.
while a < b
a += 1
endTo go through the body of the loop at least once
begin
a += 1
end while a < bThere is as well inline way to write the loop
a += 1 while a < bAnd finally the negative counterpart until
until a > b
a += 1
endMethods in Ruby always return some value. If it is not explicitly returned using the
return keyword, the return value is the value of the last expression in the method.
Return as usual returns from method and ends the execution of the method.
# Simple method with two arguments
def mth(a, b)
end
# Method with default value for 2nd argument
def mth(a, b=1)
end
# Method accepting any number of arguments, available as Array args
def mth(*args)
end
# Method requiring at least two arguments
def mth(a, b, *args)
endThe require method loads code from another file. Ruby keeps track of required files
and skips loading files that would be loaded 2nd time. Files are looked up using Ruby’s
load path, which is represented using an array in $LOAD_PATH and $:. The load method does
not keep track of loaded files.
In case the required file ends with [rb, so, o, dll, bundle, jar] extension, the extension may be omitted. There two commands are equivalent
require "somefile"
require "somefile.rb"To keep track of required files, Ruby keep list of all files that were required in the $"
variable.
Blocks have many uses-cases. One of the use cases is the replacement for for cycles
another use case is anonnymous functions. Block are not executed when defined, but
have to be called through the call method (though the calling of call method is
most of the times hidden from the develop as in the examples below).
Arrays have method called each that accepts block and calls the block for every
single element in the array.
arr = [1,2,3,4]
arr.each do |el|
puts el
endwill print all four values to the standard output. Blocks can be written in one more way
arr = [1,2,3,4]
arr.each { |el| puts el }this variant is usually used for single-line blocks.
Block see their own scope plus can access scope in which were defined.
sum = 0
arr = [1,2,3,4]
arr.each { |el| sum += el }Any method can accept a block and call it
def mth
return nil unless block_given?
yield
endThis method will return nil if no block was given or will call the block without any argument and the return value of the block will be return from the method.
Method may also accept blocks as a named argument which is prefixed by &.
def mth(num, &block)
block.call(num)
endthis method will call block saved in the variable block and will pass one argument
which is the first argument passed to the method itself.
In Ruby everything is an object. Object is an instance of some class. Even every class is an instance of class that inherits from Class. Object can have methods
class Hello
def say
"Hello, world!"
end
end
puts Hello.new.sayand instance variables
class Hello
def initialize(msg=nil)
@msg = msg
end
def say
@msg
end
end
puts Hello.new("Hello, world!").sayTo make your instance variables accessible from outside, you define them as attributes. Attributes can be either read-only, write-only or both.
class Hello
attr_reader :one # allows reading by using the .one method
attr_writer :two # allows writing by using the .two = "xy" method
attr_accessor :three # allows both, reading and writing
endRuby allows object inheritance. All methods including constructor are inherited. Methods
can be overridden by children. super is then used to call the original method.
class A
def a
"hello"
end
end
puts A.new.a # => hello
class B < A
end
puts B.new.a # => hello
class C < A
def a
super + " world"
end
end
puts C.new.a # => hello worldAs known from other language, except in Ruby class variables are not used because of some pitfalls in their inheritance.
class A
def self.a
"hello"
end
end
puts A.a # => helloModules are a way to organize your classes in a similar fashion to namespaces. Classes can be included into modules or into other classes.
class A
class B
end
end
module Some
class Thing
end
endModule are however used as well as mixins. When module is included into class all methods defined for that module are available in the class as instance methods.
module Helper
def something
end
end
class A
include Helper
end
A.new.somethingand when used with extend the mehtods are included as class methods
module Helper
def something
end
end
class A
extend Helper
end
A.somethingRuby has only single inheritance, mixins allow to get around this and provide a way to get some kind of multiple inheritance.
By default methods are public, explicitly methods can be made protected or private.
class A
def public_method
end
protected
def protected_method
end
private
def private_method
end
endRuby encourages to react based on behaviour rather then on identity.
class Hunter
def shoot(animal)
bang! if animal.class == Duck
end
endin this case the code checks if it’s a duck and shoots it, however
class Hunter
def shoot(animal)
animal.respond_to?(:quack) && bang!
end
endin this case we care if the animal quacks and the it’s shot.
Exceptions represnt a special state in the execution in a program. When an exception is raised, it will bubling thorugh the stack until is caught.
Exceptions are raised using the raise keyword
raise "This is not expected"On the other hand when an exception needs to be caught, code block is extended with
rescue statement that is called when an exception is caught and optionally ensure
that is called after both exceptional and non-exceptional state. Unless an exception
class is specified explicitly after the rescue keyword, the StandardError class
and it’s ancestors are rescued.
begin
raise "This is not expected"
rescue => e
puts e.message
ensure
puts "always"
end|
Important
|
Don’t inherit directly from Exception class but use
StandardError instead. The direct descendants of Exception are
usually exceptions one doesn’t want to rescue from, such as
SystemExit or NoMemoryError.
|