# Это комментарий=begin
Это многострочный комментарий
Никто их не использует
И они не рекомендуются к использованию
=end# Первое и самое главное: Всё является объектом.# Числа это объекты3.class#=> Fixnum3.to_s#=> "3"# Немного простой арифметики1+1#=> 28-1#=> 710*2#=> 2035/5#=> 7# Арифметика -- это синтаксический сахар# над вызовом метода для объекта1.+(3)#=> 410.*5#=> 50# Логические величины -- это объектыnil# Здесь ничего нетtrue# истинаfalse# ложьnil.class#=> NilClasstrue.class#=> TrueClassfalse.class#=> FalseClass# Операция равенства1==1#=> true2==1#=> false# Операция неравенства1!=1#=> false2!=1#=> true!true#=> false!false#=> true# nil -- имеет такое же логическое значение, как и false!nil#=> true!false#=> true!0#=> false# Больше операций сравнения1<10#=> true1>10#=> false2<=2#=> true2>=2#=> true# Строки -- это объекты'Я строка'.class#=> String"Я тоже строка".class#=> Stringplaceholder="использовать интерполяцию строк""Я могу #{placeholder}, когда создаю строку с двойными кавычками"#=> "Я могу использовать интерполяцию строк,# когда создаю строку с двойными кавычками"# печатать в стандартный выводputs"Я печатаюсь!"# Переменныеx=25#=> 25x#=> 25# Присваивание значения возвращает то самое присвоенное значение.# Это позволяет делать множественные присваивания:x=y=10#=> 10x#=> 10y#=> 10# По соглашению, используйте snake_case для имён переменныхsnake_case=true# Используйте подробные имена для переменных# Но не переборщите!path_to_project_root='/good/name/'path='/bad/name/'# Идентификаторы (тоже объекты)# Идентификаторы -- это неизменяемые, многоразовые константы. # Для каждого идентификатора (кроме текста) сохраняется цифровой хэш.# При последующем использовании идентификатора, заместо создания нового объекта,# будет найден уже существующий по цифровому хэшу.# Они часто используются вместо строк для ускорения работы приложений:pending.class#=> Symbolstatus=:pendingstatus==:pending#=> truestatus=='pending'#=> falsestatus==:approved#=> false# Массивы# Это массивarray=[1,2,3,4,5]#=> [1, 2, 3, 4, 5]# Массив может содержать различные типы значений[1,"hello",false]#=> [1, "hello", false]# Значение в массиве можно получить по индексу с левой границыarray[0]#=> 1array[12]#=> nil# Как и арифметика, доступ к значению в массиве# это синтаксический сахар над вызовом метода для объектаarray.[]0#=> 1array.[]12#=> nil# Также, можно получить по индексу с правой границыarray[-1]#=> 5# С заданными левой и правой границами индексовarray[2,4]#=> [3, 4, 5]# Или с использованием диапазона значенийarray[1..3]#=> [2, 3, 4]# Вот так можно добавить значение в массивarray<<6#=> [1, 2, 3, 4, 5, 6]# Хэши -- это массив пар "ключ => значение".# Хэши объявляются с использованием фигурных скобок:hash={'color'=>'green','number'=>5}hash.keys#=> ['color', 'number']hash.values#=> ['green', 5]# Значение в хэше легко может быть найдено по ключу:hash['color']#=> 'green'hash['number']#=> 5# Поиск по ключу, которого в хэше нет вернёт nil:hash['nothing here']#=> nil# начиная с Ruby 1.9, существует специальный синтаксис # при использовании идентификаторов как ключей хэша:new_hash={defcon:3,action:true}new_hash.keys#=> [:defcon, :action]# Массивы и Хэши -- перечисляемые типы данных# У них есть много полезных методов, например: each, map, count и другие# Управление ходом выполнения (Управляющие структуры)iftrue"Если истина"elsiffalse"Иначе, если ложь (опционально)"else"Во всех других случаях"endforcounterin1..5puts"итерация #{counter}"end#=> итерация 1#=> итерация 2#=> итерация 3#=> итерация 4#=> итерация 5# Однако, никто не использует "for" для циклов.# Вместо него Вы должны использовать метод "each" вместе с блоком кода.## Блок кода -- это один из вариантов создания замыканий (лямбды,# анонимные функции).# Блок может только передаваться методу, сам по себе он существовать не может.# "for" не имеет своей области видимости и все переменные, объявленные в нём# будут доступны отовсюду. "each" вместе с блоком создаёт свою область видимости# Метод "each" для диапазона значений запускает блок кода один раз# для каждого из значений диапазона# Блок передаёт счётчик (counter) в качестве параметра.# Вызов метода "each" с блоком выглядит следующим образом:(1..5).eachdo|counter|puts"итерация #{counter}"end#=> итерация 1#=> итерация 2#=> итерация 3#=> итерация 4#=> итерация 5# Вы также можете ограничивать блоки фигурными скобками:(1..5).each{|counter|puts"итерация #{counter}"}# Содержимое структурных данных также можно перебирать используя "each":array.eachdo|element|puts"#{element} -- часть массива"endhash.eachdo|key,value|puts"#{key} -- это #{value}"endcounter=1whilecounter<=5doputs"итерация #{counter}"counter+=1end#=> итерация 1#=> итерация 2#=> итерация 3#=> итерация 4#=> итерация 5grade='B'casegradewhen'A'puts"Так держать, детка!"when'B'puts"Тебе повезёт в следующий раз"when'C'puts"Ты можешь сделать лучше"when'D'puts"Выскоблил последнее"when'F'puts"Ты провалился!"elseputs"Альтернативная система оценок, да?"end# Функцииdefdouble(x)x*2end# Функции (и все блоки) неявно возвращают значение последней операцииdouble(2)#=> 4# Скобки необязательны, если возвращаемый результат однозначенdouble3#=> 6doubledouble3#=> 12defsum(x,y)x+yend# Аргументы метода разделены запятойsum3,4#=> 7sumsum(3,4),5#=> 12# yield# Все методы имеют неявный, опциональный параметр,# который может быть вызван с помощью инструкции "yield"defsurroundputs"{"yieldputs"}"endsurround{puts'hello world'}# {# hello world# }# Определение класса с помощью ключевого слова "class"classHuman# Переменная класса, она является общей для всех экземпляров класса@@species="H. sapiens"# Базовый метод-конструкторdefinitialize(name,age=0)# Присвоить аргумент "name" переменной "name" экземпляра класса@name=name# Если аргумент "age" не задан,# мы используем значение по умолчанию из списка аргументов@age=ageend# Базовый метод установки значения для переменной (setter)defname=(name)@name=nameend# Базовый метод получения значения переменной (getter)defname@nameend# Метод класса определяется с ключевым словом "self",# чтобы можно было отличить его от метода экземпляра класса.# Он может быть вызван только на уровне класса, но не экземпляра.defself.say(msg)puts"#{msg}"enddefspecies@@speciesendend# Создание экземпляра классаjim=Human.new("Jim Halpert")dwight=Human.new("Dwight K. Schrute")# Давайте вызовем несколько методовjim.species#=> "H. sapiens"jim.name#=> "Jim Halpert"jim.name="Jim Halpert II"#=> "Jim Halpert II"jim.name#=> "Jim Halpert II"dwight.species#=> "H. sapiens"dwight.name#=> "Dwight K. Schrute"# Вызов метода классаHuman.say("Hi")#=> "Hi"# Область видимости переменной определяется тем, как мы даём имя переменной.# Переменные, имя которых начинается с "$" имеют глобальную область видимости$var="I'm a global var"defined?$var#=> "global-variable"# Переменная экземпляра класса, она видна только в экземпляре@var="I'm an instance var"defined?@var#=> "instance-variable"# Переменная класса, видна для всех экземпляров этого класса и в самом классе@@var="I'm a class var"defined?@@var#=> "class variable"# Имена переменных с большой буквы используются для создания константVar="I'm a constant"defined?Var#=> "constant"# Класс тоже объект в Ruby. Класс может иметь переменные экземпляра.# Переменная класса доступна в классе, его экземплярах и его потомках.# Пример классаclassHuman@@foo=0defself.foo@@fooenddefself.foo=(value)@@foo=valueendend# Производный класс (класс-потомок)classWorker<HumanendHuman.foo# 0Worker.foo# 0Human.foo=2# 2Worker.foo# 2# Переменная экземпляра класса недоступна в потомках этого класса.classHuman@bar=0defself.bar@barenddefself.bar=(value)@bar=valueendendclassDoctor<HumanendHuman.bar# 0Doctor.bar# nilmoduleModuleExampledeffoo'foo'endend# Включение модулей в класс добавляет их методы в экземпляр класса# Или в сам класс, зависит только от метода подключенияclassPersonincludeModuleExampleendclassBookextendModuleExampleendPerson.foo# => NoMethodError: undefined method `foo' for Person:ClassPerson.new.foo# => 'foo'Book.foo# => 'foo'Book.new.foo# => NoMethodError: undefined method `foo'# Коллбэки при подключении модуляmoduleConcernExampledefself.included(base)base.extend(ClassMethods)base.send(:include,InstanceMethods)endmoduleClassMethodsdefbar'bar'endendmoduleInstanceMethodsdefqux'qux'endendendclassSomethingincludeConcernExampleendSomething.bar# => 'bar'Something.qux# => NoMethodError: undefined method `qux'Something.new.bar# => NoMethodError: undefined method `bar'Something.new.qux# => 'qux'