Ruby Basics
In this article, we will get acquainted with the basic types of Ruby, consider the syntax and learn how to use them.
All code will be entered in the interactive console - irb
Ruby.new
Create new file terminal.rb with this code:
1
2
3
4
5
6
7
8
9
10
11
12
13
class Terminal
attr_accessor :title
def initialize(title = 'Awesome Term')
@title = title
end
def run(command = nil)
puts "Welcome to #{title}!"
puts "Running your '#{command}' command..." if command
end
end
.rb - is Ruby file extension
Now open the terminal and run irb
command, you will see Ruby interactive command prompt.
If you write 1 + 1
and press enter, Ruby will immediately execute your code and return the result:
Execute code from a file:
irb(main)> require_relative 'terminal'
irb(main)> t1 = Terminal.new
irb(main)> t1.run
=> Welcome to Awesome Term!
irb(main)> t2 = Terminal.new('Terminator')
irb(main)> t2.run
=> Welcome to Terminator!
irb(main)> t3 = Terminal.new
irb(main)> t3.title = "Just Term"
irb(main)> t3.run
=> Welcome to Just Term!
irb(main)> t4 = Terminal.new
irb(main)> t4.title = "Just Term"
irb(main)> t4.run("ls")
=> Welcome to Just Term!
=> Running your 'ls' command...
require_relative - Ruby method loads the file or library named string relative to the requiring file’s path.
Class is a unique object in Ruby, we can declare it with a special keyword - class
def initialize (title)
- Is a special method in Ruby that allows us to specify the initial values of an object that we can transfer to
Terminal.new('My Term')
But the title argument is not stored anywhere yet.
You must assign a @
variable for storage. (Instance Variables)
class Terminal
def initialize(title)
@title = title
end
end
In the first part we installed Ruby in our system.
Getters and Setters
Run irb
and enter this code:
class Terminal
def initialize(title)
@title = title
end
end
irb(main)> Terminal.new("My Term")
In the console we will see what we got back:
=> #<Terminal:0x00000000017be6b0 @title="My Term">
Call our Terminal object and get the title:
irb(main)> t = Terminal.new('My Term')
irb(main)> puts t.title
puts - a method that returns values in the terminal for each new line.
Oops - we get an error…
undefined method `title' for #<Terminal:0x0000000001667b40 @title="My Term"> (NoMethodError)
Reason - The object has no method title.
Create this method and return the title:
class Terminal
def initialize(title)
@title = title
end
def title
@title
end
end
Once initialized we can use the title object as @title
.
Let’s call again:
irb(main)> t = Terminal.new('My Term')
irb(main)> puts t.title
=> My Term
We can dynamically change the name:
irb(main)> t = Terminal.new('My Term')
irb(main)> t.title = 'Some Term'
irb(main)> puts t.title
=> Some Term
For this we need to add a new method
def title = (val)
New code looks like this:
class Terminal
def initialize(title)
@title = title
end
def title
@title
end
def title=(val)
@title = val
end
end
irb(main)> t = Terminal.new('My Term')
irb(main)> t.title = 'Some Term'
irb(main)> puts t.title
=> Some Term
attr_reader
To avoid always writing methods for initial values, Ruby has the method attr_reader
:
class Terminal
attr_reader :title
def initialize(title)
@title = title
end
end
irb(main)> t = Terminal.new('My Term')
irb(main)> puts t.title
=> My Term
attr_writer
Instead of writing def title = (val)
every time, Ruby has attr_writer
method:
class Terminal
attr_reader :title
attr_writer :title
def initialize(title)
@title = title
end
end
irb(main)> t = Terminal.new
irb(main)> t.title = 'My New Term'
irb(main)> puts t.title
=> My New Term
We can replace attr_reader
and attr_writer
with attr_accessor
, which will add both actions. If they used, we no longer write the @
symbol inside the object.
All methods that are in the object are called Instance Methods
method default value
In the method we can define a default value:
def initialize(title = 'Awesome Term')
end
If we didn’t pass any value to the Terminal.new
, the title would be set to “Awesome Term”.
Interpolation
Consider the method run (command = nil):
def run(command = nil)
puts "Welcome to #{title}!"
puts "Running your '#{command}' command..." if command
end
Here we see an example of interpolation - "# {any Ruby code here}”
The command
variable has a default value of nil, when something is passed in the method the code is called:
puts "Running your '#{command}' command...
Variables
Local - name, age, lang
Instance - @name, @age, @lang
Class - @@name, @@age, @@lang
Global - $NAME, $AGE, $LANG
Variables can be of any type - string, array, tree, etc.
Strings
name = "Alex"
name = 'Alex'
With double quotes ""
- we can use interpolation, as well as special characters \n
\t
\r
hello = "Hello,\nWorld"
puts hello
=> Hello,
=> World
hello = 'Hello,\nWorld'
puts hello
=> Hello,\nWorld
In single quotes, special characters don’t work, nor does interpolation. If there is a way, it is better to use single quotes ''
irb(main)> lang = 'ruby'
# Returns a new copy of the object
irb(main)> puts lang.upcase
=> RUBY
irb(main)> puts lang.capitalize
=> Ruby
irb(main)> puts lang
=> ruby
# If we want to directly change the lang object, we have to call it bang!
irb(main)> lang.upcase!
irb(main)> puts lang
=> Ruby
irb(main)> puts "Hello! " * 3
=> Hello! Hello! Hello!
Concatenation
Concentration can be done by the +
method.
irb(main)> lang = 'ruby'
irb(main)> framework = "Rails"
irb(main)> new_str = lang.capitalize + ' on ' + framework
irb(main)> puts new_str
=> Ruby on Rails
irb(main)> puts new_str.length
=> 13
irb(main)> puts new_str.reverse
=> "sliaR no ybuR"
irb(main)> puts "#{lang} on #{framework}"
=> Ruby on Rails
irb(main)> str = 'Hello'
irb(main)> str = str + ', World'
irb(main)> puts str
=> Hello, World
# Short version
irb(main)> str = 'Hello'
irb(main)> str += ', World'
irb(main)> puts str
=> Hello, World
Integer and Float
irb(main)> counter = 300
irb(main)> counter = counter + 10
=> 310
irb(main)> counter += 100
=> 400
irb(main)> pi = 3.14
irb(main)> ten = 10
irb(main)> ten.to_f
=> 10.0
Type Conversions
irb(main)> age = "28"
irb(main)> puts age + 1
=> in '+': no implicit conversion of Integer into String (TypeError)
irb(main)> age = 28
irb(main)> puts age + "2"
=> in '+': String can't be coerced into Integer (TypeError)
irb(main)> age = 28
irb(main)> puts age + "1".to_i
=> 29
age = "28"
puts age + 1.to_s
=> 281
Symbols
The symbols are identifiers, they have something in common with String.
irb(main)> "hello".to_sym
=> :hello
Once stored in memory and does not change location in memory. The string always has a new address in memory.
irb(main)> :hello.object_id
=> 2219548
irb(main)> :hello.object_id
=> 2219548
irb(main)> "hello".object_id
=> 280
irb(main)> "hello".object_id
=> 300
Boolean (FalseClass, TrueClass and NilClass)
false
andnil
are always falsetrue
and0
, or any variable or object is true
Array
A collection of different elements which can be of any type.
Array initialization:
irb(main)> arr = []
irb(main)> arr = Array.new
irb(main)> arr = Array.new([])
irb(main)> arr = Array.new(nil)
irb(main)> arr = %w()
=> []
irb(main)> arr.class
=> Array
irb(main)> [1, 2, "somestring"].length
=> 3
irb(main)> arr = ['Ruby', 'on', 'Rails', 7]
irb(main)> arr.join(' ')
=> Ruby on Rails 7
Array element indexes start at 0
irb(main)> arr = [1,2,3,4,5]
irb(main)> puts arr[0]
=> 1
irb(main)> puts arr[-1]
=> 5
If the array index is not found it returns nil
irb(main)> arr = [1,2,3,4,5]
irb(main)> arr[9]
=> nil
Add to Array:
irb(main)> arr = []
irb(main)> arr << 1
irb(main)> arr << 2
irb(main)> arr.push(9)
irb(main)> arr[5] = 10
irb(main)> puts arr
=> [1, 2, 9, nil, nil, 10]
# Add to the beginning of the array
irb(main)> arr.unshift(5)
Remove from the array:
irb(main)> arr = [1, 2, 3, 4, 5]
# Returns the last element and removes it from the array
irb(main)> arr.pop
=> 5
irb(main)> puts arr
=> [1, 2, 3, 4]
# Returns the first element and removes it from the array
irb(main)> arr.shift
=> 1
irb(main)> puts arr
=> [2, 3, 4]
irb(main)> arr = [1,2,3,4,5]
irb(main)> arr[0..3]
=> [1,2,3,4]
Hash
A hash is a structure that is also called an associative array, but we can use any type of object in indexes.
The tree index name is unique.
Create a tree
irb(main)> h = {}
irb(main)> h = Hash.new
# Hash default value
irb(main)> h = Hash.new(9)
irb(main)> h[:some_key]
=> 9
Return elements:
irb(main)> h = {
irb(main)> name: 'Alex',
irb(main)> age: 28,
irb(main)> langs: %w(Ruby Elixir Dart)
irb(main)> }
irb(main)> puts h[:name]
=> Alex
irb(main)> puts h[:age]
=> 28
irb(main)> puts h[:langs]
=> ['Ruby', 'Elixir', 'Dart']
Add new elements:
irb(main)> h = {}
irb(main)> h[:name] = 'Alex'
irb(main)> h['age'] = 28
irb(main)> puts h
=> { :name => 'Alex', "age" => 28 }
irb(main)> puts h[:name]
=> Alex
# Returns nil because the key is stored as a string and we point to it as a symbol
irb(main)> puts h[:age]
=> nil
# key can be any object
irb(main)> h = { 1 => "one", 2 => "two" }
irb(main)> puts h[1]
=> one
irb(main)> puts [9]
=> nil
Constants
Always starts with uppercase letters, the stored data does not change. (Changes but shows Ruby Warning)
irb(main)> RUBY_VERSION = 3.0.1
irb(main)> SomeString = "hello"
irb(main)> SomeString = "changes"
=> warning: already initialized constant SomeString
Range
irb(main)> puts (1..10).to_a
=> [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
# include 5
irb(main)> (1..10) == 5
=> true
Control Structures
if - is waiting for any object that will be true
irb(main)> def check_version(version)
irb(main)> if version > 2.6
irb(main)> puts "Ok"
irb(main)> elsif version >= 2.3 || version <= 2.5
irb(main)> puts "Legacy"
irb(main)> else
irb(main)> puts "Very old"
irb(main)> end
irb(main)> end
irb(main)> check_version(2.8)
=> Ok
unless - ends when it is false. (reverse version of if)
irb(main)> is_eq = (1 == 2) # false
irb(main)> unless is_eq
irb(main)> puts "enter unless block"
irb(main)> end
=> enter unless block
case - is a switch analog in other languages, but once entered in when it no longer goes to the next element.
irb(main)> age = 28
irb(main)> case age
irb(main)> when 1..18
irb(main)> puts "<=18"
irb(main)> when 19...31
irb(main)> puts ">18"
irb(main)> else
irb(main)> puts age
irb(main)> end
=> >18