Быстрое знакомство с Ruby 
  Андрей Васильев
  2020
 
Язык Ruby 
Скриптовый (интепретируемый) язык 
Приложение на языке Ruby всегда выполняется с помощью интерпретатора, как во время разработки, так и во время использования конечными пользователями
Объектно-ориентированный язык 
Объект — это базовый элемент приложения, имеющий состояние и методы, использующие данное состояние 
Структура объектов описывается с помощью классов 
Для создания объектов (экземпляров классов) используется метод класса new, конструктор 
 
Динамически типизированный 
Переменные могут содержать в себе ссылки на объекты любых типов
 
Запуск приложений на Ruby 
Для выполнения приложения на языке Ruby потребуется:
Интерпретатор языка Ruby 
Набор библиотек, gems, от которых зависит код приложения 
Код самого приложения 
 
Запуск приложения сводится к вызову интерпретатора Ruby с указанием файла, начинающего исполнение приложения
Актуальные интерпретаторы Ruby 
Переменная PATH 
Во всех операционных системах есть переменная окружения PATH, содержащая набор каталогов, в которых происходит поиск исполняемых файлов
Если каталога с исполняемым файлом нет в PATH, то для его запуска надо указать абсолютный путь
Руководство по настройке PATH 
 
IRB — интерактивный интерпретатор Ruby 
Вместе с обычным интерпретатором языка ruby, предназначенным для выполнения приложений, поставляется также интерактивный интерпретатор irb
Данное приложение работает по следующему принципу:
Пользователь вводит строку на языке Ruby и нажимает Enter 
Приложение считывает данную строку, разбирает и выполняет 
Выполнение выражения изменяет состояние IRB 
Результат выполнения выражения выводится пользователю 
Приложение ожидает ввод от пользователя 
 
IRB позволяет
Быстро проверять свои идеи 
Узнавать детали работы методов 
 
 
Пример из приложения 
Приложение «Музыкальный автомат» должно обрабатывать данные о песнях. Опишем структуру объектов типа «песня» с помощью класса Song:
Создадим две переменные first_song и second_song, запишем в них ссылки на создаваемые объекты
Song .new('Калинка малинка' )Song .new('Смуглянка' ) 
Объекты в Ruby 
У каждого объекта есть уникальный идентификатор, даже если нет данных 
Объекты содержат переменные экземпляра, описывающие его состояние 
Объекты содержат методы, которые могут изменять переменные экземпляра 
Методы могут быть публичными, приватными и защищёнными
Публичные методы могут быть вызваны любыми объектами 
Приватные методы могут быть вызваны только этим объектом 
Защищённые методы могут быть вызваны в рамках дерева наследования 
  
Вызов метода удобно моделировать как отправку сообщения между объектами 
 
Модель вызова метода 
 
Сообщение включает название метода и набор аргументов для него
 
Обработка вызова метода 
При получении сообщения объект начинает поиск метода по имени 
Когда метод найден, ему передаются все аргументы 
 
Если метод не найден или количество аргументов не совпало, то будет выброшено исключение
Более детально логику поиска методов обсудим на следующих занятиях
 
 
 
Примеры вызова методов 
"gin joint" .length"Rick" .index("c" )42 .even?
Часть кода до точки называется получателем 
После точки вводится имя метода 
Аргументы метода передаются в круглых скобках 
Числа в Ruby являются объектами, они содержат методы 
 
 
Базовые элементы языка 
При написании кода на языке Ruby вам всегда будут доступны:
Метод puts модуля Kernel 
puts выводит переданные аргументы на стандартный поток вывода
'Hello, world!' 42 .even?2 **10  
Вывод в Ruby 
puts выводит аргументы на стандартный поток вывода и добавляет перенос на следующую строкуprint не добавляет перенос на новую строкуprintf позволяет выводить информацию согласно формату, как в Сиp выводит информацию в формате, пригодном для отладкиpp выводит информацию для отладки сложных объектов, пригодной для восприятия разработчиком 
 
Простейший метод 
def  say_goodnight(name)"Good night, "  + namereturn  resultend # Вызываем метод "John-Boy" )"Mary-Ellen" )
Выражения на разных линиях не надо разделять с помощью точки с запятой 
Комментарии начинаются с символа # 
При объявлении переменные должны быть инициализрованы 
 
 
Определение метода 
Определение начинается с ключевого слова def 
Затем следует имя метода, слова в названии которого разделены подчёркиваниями 
В круглых скобках перечисляются аргументы 
Тело метода завершается ключевым словом end 
Результат работы возвращается с помощью return 
 
def  say_goodnight(name)"Good night, "  + namereturn  resultend  
Вызов метода 
Передавайте методу столько обязательных аргументов, сколько он ожидает 
При вызове метода можно не указывать круглые скобки: 
 
"John-Boy" )"John-Boy" ))Обычно скобки опускаются только в самых простых случаях:
Если метод не имеет аргументов, не указывайте скобки 
Если метод имеет аргументы, указывайте скобки за исключением стандартных методов вывода информации (puts, print и p) 
 
Также следует использовать соглашения конкретных библиотек
 
Строки 
Для определения строк обычно используются литералы 
Литералы описываются с помощью одинарных и двойных кавычек 
Строки в одинарных кавычках не обрабатываются 
Обработка строк в двойных кавычках
Замена специальных символов (\n, \t) 
Заполнение результатов выражений #{ ... } 
  
В отличие от Java строки можно изменять 
 
Вместо конкатенации строк используйте шаблонные строки
def  say_goodnight(name)"Good night,  #{ name.capitalize} " return  resultend  
Возвращаемое значение 
Для возвращения значения из метода в произвольный момент используется ключевое слово return 
Результат вычисления последнего выражения в методе является его значением 
 
def  say_goodnight(name)"Good night,  #{ name.capitalize} " end return обычно используется когда результат становится известен заранее:
При возникновении ошибочного состояния 
Когда действие не надо выполнять для данных аргументов 
Когда аргументы не прошли проверку 
 
 
Наименования элементов 
Первый символ элемента приложения описывает его назначение
Имена локальных переменных, параметров методов и имена методов должны начинаться со строчной буквы или подчёркивания 
Имена глобальных переменных начинаются со знака $ 
Имена переменных экземпляра, начинаются со знака @ 
Имена переменных класса, начинаются с @@ 
Имена классов, модулей и констант начинаются с заглавной буквы 
Имена методов могут заканчиваться символами ?, !, = 
Слова в именах переменных разделяются подчёркиваниями 
Слова в названиях классов начинаются с заглавной буквы 
 
 
Массивы и ассоциативные массивы 
Массивы являются индексируемыми коллекциями
Обычные массивы индексируются числами 
Ассоциативные массивы — любыми объектами 
  
Коллекции всегда являются динамическими 
В коллекции могут находится любые объекты 
 
Массивы 
1 , 'cat'  , 3.14 ]"Первый элемент  #{ a[0 ]} " # Установим новое значение 3 элементу массива 2 ] = nil "Массив сейчас  #{ a.inspect}  "  
Создание массивов 
Объект nil 
Во многих языках программирования есть понятие «отсутствующего значения», например null в Java 
nil — объект, обозначающий отсутствие значения 
Массивы из строк 
'ant'  , 'bee'  , 'cat'  , 'dog'  , 'elk' ]0 ] # => "ant" 3 ] # => "dog" # Создание такого же массива из строки  %w{ ant bee cat dog elk } 0 ] # => "ant" 3 ] # => "dog"  
Ассоциативные массивы 
Для создания литералов ассоциативных массивов используются фигурные скобки 
Элементами описания являются пары ключ-значение, разделённые «=>»: ключ => значение 
Ключи должны быть уникальными для массива 
Пары разделяются друг от друга запятыми 
 
'cello'  => 'string' ,'clarinet'  => 'woodwind' ,'drum'  => 'percussion' 'cello' ] 
Значение по умолчанию 
Если обратиться к несуществующему элементу, тогда будет возвращено значение nil 
Иногда желательно, чтобы массив возвращал осмысленное значение по умолчанию 
 
# Создаём массив со значением по умолчанию Hash .new(0 )'ruby' ] # => 0 'ruby' ] = histogram['ruby' ] + 1 'ruby' ] # => 1  
Проблема уникальных значений 
Часто при написании приложения нам необходимо описать уникальные значения и обращаться к ним с помощью слов
Для решения этих задач можно прибегнуть либо к константам, либо к строкам
Проблемами использования констант являются:
Мы не можем выполнить обратное преобразование надёжно 
Пользователь может использовать значение вместо константы 
Константы необходимо заранее объявить и подключить объявление во всех местах использования 
 
Проблемой использования строк является то, что под каждую из них необходимо выделить отдельную память
 
Символы в Ruby 
В Ruby есть специальный тип данных Symbol, который позволяет описать уникальное именованное значение
В отличие от констант их не надо определять заранее и они всегда будут уникальны 
В отличие от констант они не имеют связанного с ними значения 
В отличие от строк они не занимают оперативную память при использовании 
В отличие от строк они быстрее сравниваются друг с другом 
В отличие от строк и констант их стоит рассматривать как код, а не как данные 
 
Символы создаются с помощью синтаксиса :north или :"north"
:north )def  walk(direction)if  direction == :north end  
Символы как ключи хешей 
Символы часто используются в качестве ключей хешей
:cello  => 'string' ,:clarinet  => 'woodwind' Поддержка таких хешей добавлена в синтаксис языка
cello: 'string' ,clarinet: 'woodwind'  
Управляющие конструкции 
Ruby поддерживает знакомые вам конструкции
if для описания условной логикиwhile для описания циклических действий 
Time .nowif  today.saturday?"Do chores around the house" elsif  today.sunday?"Relax" else "Go to work" end Блок описания заканчивается ключевым словом end
 
Выражения в условиях 
Любое выражение может являться условием. Ложными значениями являются только false и nil. Все остальные значения являются верными.
while  weight < 100  && num_pallets <= 5 1 end Метод gets получает строку со стандартного потока ввода
При достижении конца потока gets возвращает nil
while  line = getsend  
Модификаторы выражений 
Условные операторы могут выступать в роли модификатора выражения
if  radiation > 3000 "Danger, Will Robinson" end "Danger, Will Robinson"  if  radiation > 3000 Аналогично для операторов цикла
4 while  square < 1000 end while  square < 1000 Однако не стоит таким образом описывать сложные выражения
 
Нумерованные циклы 
В Ruby также существует цикл for, который позволяет выполнить действие для элемента коллекции
for  value in  [1 , 2 , 3 ] do end Однако для выполнения действий несколько раз удобнее воспользоваться методом times у целых чисел:
3 .times do  |value|end  
Регулярные выражения 
Регулярное выражение — способ описать шаблон, которому должна соответствовать строка 
Реализованы как часть языка, а не в виде библиотеки 
Регулярные выражения — объекты 
/Perl|Python/ — либо строка целиком Perl, либо целиком Python/ab+c/ — a, за которым следует несколько b, затем cВыражения можно сравнивать со строками с помощью ~= 
Метод sub строки позволяет заменять подстроки 
 
"Perl and Python are scripting languages" /Perl/ , 'Ruby' )/Python/ , 'Ruby' ) 
Блоки и итераторы 
Вы можете ассоциировать некоторый блок кода с методом 
Блоки могут быть использованы для реализации
Обратных вызовов callbacks 
Передачи управления из метода блоку 
  
Блоки можно сравнить с анонимным методом 
 
Примеры блоков 
"Hello"  } # Для одного выражения do  # Для нескольких выражений end  
Ассоциация блока с методом 
Для ассоциации блока с методом его необходимо описать сразу после вызова метода
"Hi"  }"Dave" ) { puts "Hi"  }Вызов ассоциированного блока кода 
Вызов осуществляется с помощью ключевого слова yeild
def  call_block"Start of the method" yield "End of the method" end "In the block"  } 
Аргументы блоков 
Блокам могут быть переданы аргументы 
Аргументы описываются между вертикальными линиями 
 
def  who_says_whatyield  ("Dave" , "hello" )yield  ("Andy" , "goodbye" )end do  |person, phrase|" #{ person}  says  #{ phrase} " end  
Итераторы 
Итератором называется метод коллекций, принимающий блок
Под коллекцией понимаются как встроенные классы массива и хеша, так и классы, созданные пользователями
Коллекции поддерживают множество итераторов
 %w( ant bee cat dog ) 3 .upto(6 ) { |number| print number }'a' ..'e' ).each { |character| print character } 
Примеры полезных итераторов 
5 , 66 , 13 , 24 , 46 ]# Все элементы с позицией do  |number, index|" #{ index} :  #{ number} " end # Все ли элементы удовлетворяют условию: являются нечётными # Создать новый массив на основе текущего: квадраты чисел 2  }# Посчитать общую характеристику: сумму чисел # Выбрать часть элементов массива 40  } 
Обработка аргументов командной строки 
Доступ к списку аргументов 
Массив ARGV содержит список строк, которые были переданы в виде аргументов командной строки
"You gave   #{ ARGV .size}   arguments" ARGV Обработка файлов, переданных приложению 
Если приложение ориентировано на обработку текстовых файлов, то пути к ним можно передать в качестве аргументов
В приложении к ним можно обратиться как к одному большому файлу через специальный объект ARGF