Опубликован: 27.01.2016 | Уровень: для всех | Доступ: платный
Лекция 4:

Rails — приправленный Ruby

Тесно связаны с массивами диапазоны, которые проще всего понять посредством преобразования их в массивы, с помощью to_a метода:

>> 0..9
=> 0..9
>> 0..9.to_a              # Упс, вызвали to_a на 9.
NoMethodError: undefined method `to_a' for 9:Fixnum
>> (0..9).to_a            # Использование круглых скобок для вызова to_a на диапазоне.
=> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

Хотя 0..9 и является допустимым диапазоном, второе выражение показывает, что нам нужно добавить скобки для вызова метода на нем.

Диапазоны полезны для вытаскивания элементов массива:

>> a = %w[foo bar baz quux]         # Применение %w для создания массива строк.
=> ["foo", "bar", "baz", "quux"]
>> a[0..2]
=> ["foo", "bar", "baz"]

Особенно полезным трюком является использование индекса -1 в конце диапазона для выборки каждого элемента от заданной точки до конца массива без необходимости явно использовать длину массива:

>> a = (0..9).to_a
=> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>> a[2..(a.length-1)]               # Явное использование длины массива.
=> [2, 3, 4, 5, 6, 7, 8, 9]
>> a[2..-1]                         # Использование трюка с индексом -1.
=> [2, 3, 4, 5, 6, 7, 8, 9]

Диапазоны также работают с буквами:

>> ('a'..'e').to_a
=> ["a", "b", "c", "d", "e"]

Блоки

И массивы и диапазоны отвечают на множество методов, которые принимают блоки, которые одновременно являются и самыми мощными и одними из самых непонятных элементов Руби:

>> (1..5).each { |i| puts 2 * i }
2
4
6
8
10
=> 1..5

Этот код вызывает each метод на диапазоне (1..5) и передает ему блок { |i| puts 2 * i }. Вертикальные линии вокруг имени переменной в |i| являются Ruby синтаксисом для блоковых переменных и это позволяет методу узнать, что делать с блоком; в данном случае диапазонный each метод может обрабатывать блок с одной локальной переменной, которую мы называли i и он просто выполняет блок для каждого значения в диапазоне.

Фигурные скобки это один из способов обозначить блок, но есть также второй способ:

>> (1..5).each do |i|
?>   puts 2 * i
>> end
2
4
6
8
10
=> 1..5

Блоки часто могут быть более чем из одной строки. В Rails Tutorial мы будем следовать общей конвенции использования фигурных скобок только для коротких однострочных блоков и использовать do..end синтаксис для длинных однострочных и многострочных блоков:

>> (1..5).each do |number|
?>   puts 2 * number
>>   puts '--'
>> end
2
--
4
--
6
--
8
--
10
--
=> 1..5

Здесь я использовал number вместо i просто чтобы подчеркнуть, что имя переменной может быть любым.

Если не владеете основами программирования в должной степени, нет короткой дороги к пониманию блоков; просто их нужно много увидеть и, в конечном итоге, вы привыкнете к ним.6С другой стороны, искушенные программисты могут извлечь пользу из понимания, что блоки - это замыкания, объединяющие анонимные функции с внешними, по отношению к этим функциям, данными. К счастью, люди довольно хороши на обобщения на основе конкретных примеров; вот еще несколько блоков, в том числе пара с использованием map метода:

>> 3.times { puts "Betelgeuse!" }   # 3.times принимает блок без переменных.
"Betelgeuse!"
"Betelgeuse!"
"Betelgeuse!"
=> 3
>> (1..5).map { |i| i**2 }          # Нотация ** обозначает 'степень'.
=> [1, 4, 9, 16, 25]
>> %w[a b c]                        # Вспомните что %w создает массив строк.
=> ["a", "b", "c"]
>> %w[a b c].map { |char| char.upcase }
=> ["A", "B", "C"]
>> %w[A B C].map { |char| char.downcase }
=> ["a", "b", "c"]

Как вы можете видеть, map метод возвращает результат применения данного блока для каждого элемента в массиве или диапазоне.

Кстати, теперь мы в состоянии понять строку Ruby, которую я вбросил в Разделе 1.4.4 для генерации случайных субдоменов:

('a'..'z').to_a.shuffle[0..7].join

Давайте построим ее шаг за шагом:

>> ('a'..'z').to_a                     # Массив букв в алфавитном порядке
=> ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o",
"p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z"]
>> ('a'..'z').to_a.shuffle             # Перемешиваем его.
=> ["c", "g", "l", "k", "h", "z", "s", "i", "n", "d", "y", "u", "t", "j", "q",
"b", "r", "o", "f", "e", "w", "v", "m", "a", "x", "p"]
>> ('a'..'z').to_a.shuffle[0..7]       # Вытаскиваем первые восемь элементов.
=> ["f", "w", "i", "a", "h", "p", "c", "x"]
# Объединяем их вместе чтобы сделать одну строку.
>> ('a'..'z').to_a.shuffle[0..7].join
=> "mznpybuj"
Вадим Обозин
Вадим Обозин

Здравствуйте, записался на курс. При этом ставил галочку на "обучаться с тьютором". На email пришло письмо, о том, что записался на самостоятельное изучение курса. Как выбрать тьютора?

Акбар Ахвердов
Акбар Ахвердов
Россия, г. Москва
Артём Зайцев
Артём Зайцев
Украина, ДНР