Небольшая Ruby-шпаргалка для начинающих и продолжающих с типами данных и основными конструкциями самого дружелюбного языка.
Ruby-шпаргалка по основам кодинга
- официальный сайт сообщества
- онлайн-интерпретатор
Комментарии
# однострочный
some_useful_var = 42
another_useful_var = 7 # однострочный
=begin
блочный комментарий
=end
Вывод значений в консоль
Для вывода массивов удобно использовать print
, для всего остального – puts
.
Переменные и константы
counter = 10 # локальная
user_age = 30 # локальная
$password = "qwerty" # глобальная
PI = 3.14 # константа
Операция присваивания неявно возвращает значение, которое можно использовать.
puts number = 42 # => 42
# параллельное присваивание
a = b = c = 42
# множественное присваивание
a, b, c = 9, 8, 7
Обработка ошибок
begin
raise NoMemoryError, 'Кончилась память'
rescue NoMemoryError => exception_variable
puts 'Ошибка NoMemoryError', exception_variable
else
puts 'Код отработал без ошибок'
ensure
puts 'Этот код выполнится в любом случае'
end
Ruby-шпаргалка по типам данных
Числа
42.class # => Fixnum
999999999999999999999.class # => Bignum
999_999_999_999_999_999_999.class # => Bignum
3.6.class # => Float
45.23e2.class # => Float
a = 42.to_s
a.class # => String
Арифметические операции:
1 + 1 # => 2
8 - 1 # => 7
10 * 2 # => 20
35 / 5 # => 7
2 ** 5 # => 32
Многие функции сгруппированы в модуле Math:
Math.sqrt(64) # => 8.0
Math.log(8, 2) # => 3.0
Math.sin(Math::PI/2) # => 1.0
Строки
Строки относятся к классу String:
word = "интерполяцию"
string1 = 'допускает экранирование \', но не понимает \n других последовательностей'
string2 = "допускает\nлюбые\tуправляющие последовательности и #{word}"
string3 = %q[Экранирует "двойные" и 'одинарные' кавычки, но не понимает \n других последовательностей]
string4 = %Q[Экранирует "двойные" и 'одинарные' кавычки и допускает\nлюбые\tуправляющие последовательности и #{word}]
string5 = `ls -a` # команда ОС, выведет список файлов в каталоге
Строки можно складывать с другими строками и умножать.
"Brother " + "Louie " * 3 # => Brother Louie Louie Louie
"Ответ на самый главный вопрос... " + 42 # => no implicit conversion of Fixnum into String (TypeError)
Встроенные документы
text = <<MARKER
маркер
может
быть
любым
MARKER
Специальные значения
nil.class #=> NilClass
true.class #=> TrueClass
false.class #=> FalseClass
Символы
Тип данных, похожий на неизменяющиеся строки:
puts :authorized.class # => Symbol
status = :authorized
status == :authorized # => true
status == 'authorized' # => false
status == :guest # => false
Массивы
Массивы в Ruby относятся к классу Array
и могут содержать элементы с разными типами данных. Индексация начинается с нуля.
Создание
my_array = [9, "eight", false, nil, 3.0]
empty_array = Array.new(5) # => [nil, nil, nil, nil, nil]
true_array = Array.new(5, true) # => [true, true, true, true, true]
Узнать длину массива:
my_array.length
my_array.count
my_array.size
Получение элементов
my_array[1] # => eight
my_array.[] 1 # => eight
my_array[3].class # => NilClass
my_array[33].class # => NilClass
my_array.at(4) # => 3.0
my_array[-3] # => false
my_array.last # => 3.0
my_array.first # => 9
Получить диапазон элементов:
my_array[1, 2] # => ["eight", false]
my_array[0..4] # => [9, "eight", false, nil, 3.0]
my_array[0...4] # => [9, "eight", false, nil]
my_array.values_at(1, 4, 1..2) # => ["eight", 3.0, "eight", false]
my_array.take(3) # => [9, "eight", false]
Добавление
test_array = [42]
# в конец
test_array << 43 # => [42, 43]
test_array.push(46) # => [42, 43, 46]
# в начало
test_array.unshift(41) # => [41, 42, 43, 46]
# на любую позицию
test_array.insert(3, 44, 45) # => [41, 42, 43, 44, 45, 46]
Удаление
new_array = [1, 2, 3, 3, 3, 4, 5, nil, nil, 6]
# последнего элемента
last = new_array.pop # => 6
print new_array # => [1, 2, 3, 3, 3, 4, 5, nil, nil]
# первого элемента
first = new_array.shift # => 1
print new_array # => [2, 3, 3, 3, 4, 5, nil, nil]
# с указанной позиции
item = new_array.delete_at(2) # => 3
print new_array # => [2, 3, 3, 4, 5, nil, nil]
# удаление конкретного значения
value = new_array.delete(3) # => 3
print new_array # => [2, 4, 5, nil, nil]
# удаление nil
array_compact = new_array.compact # без изменения исходного массива
print array_compact # => [2, 4, 5]
print new_array # => [2, 4, 5, nil, nil]
array_compact = new_array.compact! # с изменением исходного массива
print array_compact # => [2, 4, 5]
print new_array # => [2, 4, 5]
# удаление повторяющихся значений
double_array = [2, 3, 4, 5, 3, 6, 7, 5, 5]
uniq_array = double_array.uniq # => [2, 3, 4, 5, 6, 7]
Хеши
Структуры данных, состоящие из пар ключ-значение. В качестве ключа обычно выступает строка или символ (с версии 1.9):
hash = {'color' => 'green', 'number' => 5}
hash.keys #=> ['color', 'number']
#хеш с символьными ключами
symbol_hash = { key1: 'value1', key2: 'value2' }
#хеш со смешанными ключами
mixed_hash = { :key1 => 'value1', 'key2' => 'value2' }
Зная ключ, можно получить связанное с ним значение. Если указанного ключа нет, вернется nil
.
hash['color'] #=> 'green'
hash['number'] #=> 5
hash['nothing'] #=> nil
Логические выражения
2 == 1 # => false
[1, 2, 3] == [1, 2, 3] # => true
1 != 1 # => false
2 != 1 # => true
!true # => false
!0 #=> false
1 < 10 # => true
1 > 10 # => false
2 <= 2 # => true
2 >= 2 # => true
1 <=> 1 # => 0, числа равны
1 <=> 2 # => -1, левое число меньше
2 <=> 1 # => 1, левое число больше
Ruby-шпаргалка по функциям
Управляющие конструкции
Условия
if и unless
if условие then
# ...
else
# ...
end
unless условие then
# ...
else
# ...
end
x = if a > 0 then b else c end
x = unless a <= 0 then b else c end
case
period = 2.3
case period
when 0
puts "Beginner"
when 0..1
puts "Junior"
when 1..3
puts "Middle"
when 3..6
puts "Senior"
else
puts "Super!"
end
Циклы
while и until
counter = 1
while counter <= 5
puts "итерация #{counter}"
counter += 1
end
counter = 0
until counter == 5
puts "значение счетчика #{counter}"
counter += 1
end
for
for counter in 1..5
puts "итерация #{counter}"
end
Вместо цикла for
в Ruby удобнее применять итераторы.
Итераторы
Методы чисел
# 3 итерации
3.times do |i|
puts "итерация #{i}"
end
# от 0 до 3
0.upto(3) { |i| puts "значение счетчика #{i}" }
each
Метод each
можно вызвать для массива, хеша или диапазона значений. Он принимает блок кода, который будет выполнен для каждого элемента.
(1..5).each do |counter|
puts "итерация #{counter}"
end
(1..5).each { |counter| puts "итерация #{counter}" }
[1, 2, 3].each { |element| puts "Элемент #{element}" }
{ "age": 18, "name": "John" }.each do |key, value|
puts "Свойство #{key} имеет значение #{value}"
end
Вариация метода each
для учета индексов в массиве – each_with_index
:
["крокодилы", "бегемоты", "обезьяны", "кашалоты"].each_with_index do |element, index|
puts "№ #{index} - #{element}"
end
Другие перебирающие методы
# получение суммы всех элементов
(5..10).reduce(:+) # => 45
(5..10).inject { |sum, n| sum + n } # => 45
# создание массива
(1..4).map { |i| i*i } # => [1, 4, 9, 16]
(1..4).collect { "cat" } # => ["cat", "cat", "cat", "cat"]
Обо всех доступных методах перечисляемых объектов (enumerable) можно прочитать в документации.
Функции
Функции всегда возвращают значение последнего вычисленного выражения. При вызове можно не использовать скобки, если выражение однозначно. Параметры разделяются запятой.
def double(x)
x*2 # значение этого выражения будет возвращено
end
double(2) # => 4
double 3 # => 6
double double 4 # => 16
def sum(x, y)
x + y
end
sum 3, 4 # => 7
sum sum(3, 4), 5 # => 12
Чтобы собрать список параметров в один массив, используется splat-оператор (*).
def foo(*array)
print array
end
foo("arg1", 2, false) # => ["arg1", 2, false]
Оператор yield
позволяет передать внутрь функции любой блок кода.
def surround
puts "{"
yield
puts "}"
end
surround { puts 'hello world' }
# => {
# => hello world
# => }
Ruby-шпаргалка по классам
Классы объявляются с помощью ключевого слова class
, принадлежат к типу Class
, а их имена являются глобальными константами.
# ключевое слово class
class Human end
Human.class # => Class
Переменные
- Переменные класса начинаются с
@@
. - Переменные экземпляров – с
@
.
Доступ к переменным возможен только через методы. Можно создавать геттеры и сеттеры вручную или воспользоваться встроенными акцессорами:
class Human
@@species = "H.sapiens" # переменная класса
NAME = "Human Class" # константа класса
def initialize(name, age=0)
@name = name # переменная экземпляра
@age = age
end
def species # геттер для переменной класса
@@species
end
def name=(name) # сеттер для @name
@name = name
end
def name # геттер для @name
@name
end
attr_reader :name, :age # геттеры можно задать так
attr_writer :name, :age # а сеттеры так
attr_accessor :name, :age # или все сразу
end
Методы
Модификаторы:
public
;private
;protected
.
Модификатор влияет на все перечисленные или объявленные после него методы.
Методы класса должны начинаться с self
. Вызвать их можно только из самого класса.
class Human
# ...
def self.say(message) # метод класса
puts "#{message}"
end
def method1
# ...
end
def method2
# ...
end
def method3
# ...
end
private :method1, :method2 # приватные методы
protected :method3 # защищенный метод
public # все нижележащие методы публичные
def method4
# ...
end
end
Экземпляры классов
john = Human.new("John Dow", 30)
john.species # => "H. sapiens"
john.name # => "John Doe"
john.name = "John William Doe"
john.name # => "John William Doe"
Human.say("Hello") # => "Hello"
Наследование
Класс-наследник получает доступ ко всем методам и переменным класса родителя. Методы родителя могут перекрываться одноименными методами наследника. Но к ним можно обратиться с помощью ключевого слова super
.
class Doctor < Human
def examinePatient # собственный метод класса
# ...
end
def method1 # метод перекрывает родительский
super.method1()
# ...
end
end
doc = Doctor.new("Gregory House")
puts doc.species # H. Sapiens, переменная класса-родителя
Множественное наследование в Ruby отсутствует, вместо него следует использовать примеси.
Модули
Модули в Ruby очень похожи на классы, но не могут наследоваться или создавать экземпляры. Их используют в основном для создания примесей или пространств имен.
module ModuleExample
def foo
'foo'
end
end
Если подключить модуль с помощью include
, его методы добавятся экземплярам класса. Если воспользоваться оператором extend
– самому классу.
class Person
include ModuleExample
end
class Book
extend ModuleExample
end
Person.foo # => NoMethodError: undefined method `foo' for Person:Class
Person.new.foo # => 'foo'
Book.foo # => 'foo'
Book.new.foo # => NoMethodError: undefined method `foo'
Полезные ресурсы
-
- Программирование на языке Ruby, Фултон Хэл
- Официальный сайт сообщества Ruby
- Компактная шпаргалка по основам языка
- Подборка материалов по Ruby и Ruby On Rails
- Подборка интерактивных курсов по Ruby и Python
Комментарии