Первые 20 часов. Как быстро научиться… чему угодно Кауфман Джош
r b:3: in '+'
В переводе на понятный человеку язык: нельзя складывать числа со словами, и поэтому компьютер указывает на ошибку. Похоже на деление на ноль: это невозможно, и программа прекращает работу.
Для исправления ошибки в программе нужно либо преобразовать цифру в строку, и тогда метод «+» объединит две переменных, либо изменить программу, чтобы она делала что-то другое.
Вот исправленная программа:
animal = "Zebra"
number = 7.to_s
puts animal + number
Запуская эту программу, мы получаем результат «Zebra7». Встроенный метод .to_s преобразует цифру 7 в строку, чтобы Ruby мог использовать объединение переменных.
Можно также сделать нечто совсем другое, например:
animal = "Zebra"
number = 7
number.times {puts "# {animal}"}
Результат на экране компьютера:
Zebra
Zebra
Zebra
Zebra
Zebra
Zebra
Zebra
Тут мы просто использовали условный цикл, встроенный в Ruby: number.times означает «выполнять это Х раз, где Х равняется значению числовой переменной». Изменив значение animal или number, мы изменим результат. (Да, вы можете модифицировать эту программу так, что она выведет на экран слово «вомбат» миллиард раз.)
Комментарии и отладка
Знакомясь с литературой, я обратил внимание на еще одно фундаментальное свойство языка Ruby — комментарии. Каждую строку программы, начинающуюся с символа #, Ruby интерпретирует как строку комментария и пропускает при выполнении.
Комментарии к программе делают ее понятной, потому что в них вы простым языком объясняете свои действия. Вот как будет выглядеть программа «Животные» с комментариями:
# Назначение переменных
animal = "Wombat"
number = 1000000000
# Цикл вывода
number.times {puts "# {animal}"}
Комментарии также очень полезны для устранения ошибок: вы можете обозначить как комментарии несколько строк программы, чтобы устранить проблемы или ошибки. В сочетании с командами print или puts это позволяет следить за выполнением программы и убедиться, что она работает так, как и планировалось.
Потратив восемь часов на исследования и установку программ, я получил следующий результат: у меня на компьютере последняя версия Ruby, я имею возможность загрузить любую нужную мне библиотеку, и я понимаю, как работают программы, написанные на Ruby.
Теперь давайте разберем более сложные программы.
Тестируем с помощью IRB
Изучая Stack Overflow, я обнаружил онлайновое пособие по Ruby под названием «Сложный способ выучить Ruby» («Learn Ruby the Hard Way») [26], написанное Робом Соберсом и Зедом Шоу. Это пособие иллюстрирует работу Ruby на примерах простых программ, предлагая вам изменить их для получения тех или иных результатов. Если нужный результат не получается, вы должны продолжить эксперимент, пока не решите задачу.
Этот метод — кодируем, тестируем, запускаем, отлаживаем — представляет собой превосходный пример быстрой обратной связи. Когда вы запустите программу, компьютер уже через несколько миллисекунд даст знать, работает она или нет. Если в коде есть ошибка, вы можете исправить ее и запустить программу снова, в течение минуты проверив несколько вариантов.
Первые главы пособия посвящены настройке Ruby, установке текстового редактора и обучению работы с IRB — программой, которая запускает на вашем компьютере программы, написанные на Ruby.
Вот как это делается. Вы набираете программу в текстовом редакторе и сохраняете ее в файле. (Пусть имя файла будет program.rb.) Чтобы запустить ее, нужно набрать команду в окне программы Terminal:
$ irb program.rb
IRB запустит вашу программу и выдаст результат, а также покажет действия, предпринятые компьютером для получения этого результата, что очень удобно для отладки. Если программа некорректна, IRB выведет на экран подробное сообщение об ошибке.
«Сложный способ выучить Ruby» начинается с назначения переменных, выполнения основных арифметических действий, манипулирования строками и составления стандартных условных циклов — аналогично примерам, которые приводились выше.
Первоначально я собирался прочесть «Красноречивый Ruby» и «Программирование на Ruby», выполнить упражнения из «Сложного способа выучить Ruby», а затем попытаться написать первую «настоящую» программу. Однако к десятому уроку я заметил кое-что важное: мне становится скучно, и я теряю интерес.
Причина проста: я копирую чужие программы и решаю задачи, поставленные другими людьми. Иногда эти программы довольно интересны, однако они не решают моих проблем. Программирование из полезного навыка начинает превращаться в научную дисциплину. Мне нужно заканчивать с исследованием и приступать к практике.
Мне не нужно читать все эти книги, инструкции, пособия и другие источники информации, чтобы приступить к программированию. Я должен писать реальные программы, а если возникнут трудности, обращаться к источникам информации.
Пора замарать руки…
Приложение № 1: статический сайт в среде Sinatra
Я уже придумал свою первую интернет-программу: приложение в среде Sinatra, которое служит основным HTML-сайтом. Вот мой целевой уровень мастерства для этого приложения.
1. Создать рабочее приложение в среде Sinatra, способное предоставить простой сайт пользователю (читателю).
2. Проверить приложение на своем компьютере и убедиться в его работоспособности.
3. Разместить это приложение на сервисе Heroku, сделав «живым», чтобы им могли пользоваться реальные читатели.
Вот и все. Никаких изысков. Простое приложение в среде Sinatra, запущенное на сервере общего пользования.
С чего я должен начинать? Обратимся к списку десяти основных принципов приобретения навыка.
1. Выберите привлекательный проект.
2. Сосредоточьтесь на каком-то одном навыке.
3. Определите целевой уровень мастерства.
4. Разбейте навык на элементы.
5. Приготовьте все необходимое для занятий.
6. Устраните препятствия для занятий.
7. Выделите специальное время для занятий.
8. Создайте быстрые петли обратной связи.
9. Занимайтесь по расписанию, короткими интенсивными интервалами.
10. Уделяйте внимание количеству и скорости.
У меня есть один четко описанный проект. Я разбил навык на составляющие и знаю, как будет выглядеть моя программа, когда я закончу работу. Теперь перейдем к необходимым инструментам: нужно ли мне что-то еще для успешного осуществления проекта?
Как выяснилось, нужно. У меня нет учетной записи на Heroku. Но это легко исправить: я захожу на сайт Heroku.com, щелкаю на кнопке Sign Up, ввожу адрес своей электронной почты и придумываю пароль.
Поскольку я уже установил на компьютере Heroku Toolbelt (программу, использовавшуюся для установки git), то библиотека Heroku загружена в мой компьютер, и с этим проблем не будет.
Судя по инструкции, мне нужно сделать еще одну вещь, чтобы связать мой компьютер с Heroku: сгенерировать «SSH key», специальный файл, который, по всей видимости, служит паролем. Получив этот ключ, я должен сообщить его Heroku, чтобы система могла распознать мой компьютер и открыть ему доступ.
К счастью, в Heroku есть указания на то, как это сделать [27]. Я ввожу команду для генерации ключа:
$ ssh-keygen — t rsa
…команду для входа в Heroku:
$ heroku login
…и команду, которая добавляет ключ к моей учетной записи в Heroku:
$ heroku keys: add
Отлично: я в системе. Как мне теперь приступить к написанию программы?
Создание простого приложения
Пришло время просмотреть документацию по сервису Heroku. Отлично: там есть два руководства, которые представляются мне полезными:
«Ruby на Heroku для начинающих» («Getting Started with Ruby on Heroku») [28];
«Развертывание приложений на основе Rack» («Deploying Rack-Based Apps») [29].
Судя по тому, что написано в этой документации, я должен сделать следующее.
1. Создать файлы с программами на своем компьютере.
2. Добавить их в «репозиторий git». (Понятия не имею, что это…)
3. Использовать команду git push heroku master, чтобы отправить готовое приложение на Heroku.
К счастью, в руководстве есть пример, и это приложение, написанное в среде Sinatra! Похоже, все проще, чем я думал…
Я создаю на своем компьютере новую папку. Эта папка называется «корневой», и в ней будут храниться все файлы программы.
Далее я открываю текстовый редактор (я пользуюсь редактором TextMate [30]) и, следуя инструкции, создаю три файла:
application.rb
config.ru
Gemfile
Ядро программы будет находиться в application.rb. Приложения, написанные на языке Ruby, всегда оканчиваются расширением. rb.
В файле config.ru будут храниться параметры конфигурации Rack. Не забывайте, что Sinatra построена над интерфейсом Rack, и поэтому вполне логично, что у него есть отдельный файл конфигурации. Эти файлы оканчиваются расширением. ru.
Gemfile — это место, где указываются библиотеки, используемые программой. Ваша программа может иметь только один такой файл, и поэтому он всегда называется одинаково — «Gemfile». Все довольно просто.
Документация по Heroku рекомендует после создания этих файлов написать простейшую программу «Hello, World!», чтобы проверить настройки. Вот что должно быть в файле application.rb:
require 'sinatra'
get '/' do
"Hello, World!"
end
А так выглядит файл config.ru:
require './application.rb'
run Sinatra:: Application
И наконец, Gemfile:
source 'http://rubygems.org'
gem 'sinatra'
Программа совсем короткая, и понять ее нетрудно.
Gemfile указывает серверу включить библиотеку Sinatra, которая требуется для работы приложения. Библиотека будет загружена с сайта RubyGems.org.
Файл config.ru указывает основное приложение, затем выполняет программу.
После запуска программа будет отображать на экране «Hello, World!», когда кто-либо нажмет «/», что указывает на возврат на главную страницу сайта.
Неужели все так просто?
В руководстве говорится, что я должен сделать еще одну вещь: сохранить файлы в репозитории git (иногда его называют просто «репо»). Я не могу сказать, что означает этот термин, но знаю, что git уже установлен, а необходимые команды есть в руководстве:
$ git init.
$ git add — A
$ git commit — m "Initial Commit"
Первая команда создает новый репозиторий git в папке корневого каталога. Команда add — A добавляет все файлы в папку репозитория. Команда commit — m фиксирует файлы в репозитории вместе с сообщением программиста, что именно фиксируется. (Я пока не очень понимаю разницу между «добавлять» и «фиксировать» и беру этот вопрос на заметку, решив разобраться с ним позже.)
После ввода этих команд компьютер отвечает:
[master (root-commit) 8ed1099] Initial commit
3 files changed, 9 insertions (+), 0 deletions (-)
create mode 100644 Gemfile
create mode 100644 application.rb
create mode 100644 config.ru
Похоже, все получилось! Осталось одно действие: создать новый пустой сервер на Heroku, а затем «поместить» мою программу на этот сервер:
$ heroku create
Я получаю ответ:
Creating shielded-springs-2049… done, stack is stack
is bamboo-ree-1.8.7
http://shielded-springs-2049.heroku.com/ | git@heroku.
com: shielded-springs-2049.git
Git remote heroku added
Получилось! «Stack» указывает программное обеспечение, выполняемое на сервере, и в сообщении прописывается общедоступный URL сервера.
И последняя команда:
$ git push heroku master
Если все пройдет хорошо, то я официально помещу свое первое приложение для выполнения на Heroku.
Вот что я получаю в ответ:
Heroku receiving push
Ruby/Sinatra app detected
Gemfile detected, running Bundler version 1.0.7
Unresolved dependencies detected; Installing…
Using — without development: test
! Gemfile.lock will soon be required
! Check Gemfile.lock into git with `git add Gemfile.lock`
! See http://devcenter.heroku.com/articles/bundler
Fetching source index for http://rubygems.org/
Installing rack (1.4.1)
Installing rack-protection (1.2.0)
Installing tilt (1.3.3)
Installing sinatra (1.3.3)
Using bundler (1.0.7)
Your bundle is complete! It was installed into./.bundle/gems/
Compiled slug size: 500K
Launching… done, v4
http://shielded-springs-2049.heroku.com deployed to Heroku
И теперь. момент истины… Я открываю веб-браузер, перехожу на http://shielded-springs-2049.heroku.com и вижу вот что:
«Hello, World!»
ПОБЕДА!
Внимание! Внимание!
Программа заработала, но я также получил предупреждение. Что такое Gemfile.lock?
В документации Heroku’s Ruby указано, что для установки библиотек на Heroku система использует библиотеку под названием bundler [31]. Это библиотека, и поэтому я могу установить ее при помощи следующей команды:
$ gem install bundler
Библиотека bundler необходима потому, что Heroku по умолчанию не устанавливает библиотеки из вашего приложения. Из соображений безопасности Heroku не рисваивает мне такой уровень доступа к серверу, какой есть у меня на моем компьютере, и я не могу выполнить команду gem install sinatra прямо в моей учетной записи.
Вместо того чтобы предоставить мне (и другим пользователям) небезопасный уровень доступа к системе, Heroku использует bundler для установки библиотек, указанных в Gemfile. Отметив, какие библиотеки вы хотите установить в своем приложении, вы набираете команду:
$ bundle install
Эта команда создает в вашей программе новый файл под названием Gemfile.lock. Когда вы загружаете свои файлы в Heroku, система просматривает Gemfile и Gemfile.lock, проверяет их идентичность, после чего загружает библиотеки, а затем устанавливает их для вас.
Если вы посмотрите на ответ системы, когда я размещал программу на Heroku, то увидите, что система устанавливала bundler автоматически, как средство поддержки зависимостей. Вместо того чтобы предусмотреть сообщение об ошибке, инженеры Heroku добавили в программу исключение — вместо аварийного завершения автоматически загрузить отсутствующую программу и отправить предупреждение.
На этот раз система сработала, но в будущем я должен добавить файл Gemfile.lock в репозиторий git, прежде чем размещать приложение. Полезная информация!
На сцену выходит Sinatra
Теперь, когда мое простейшее приложение создано и запущено, я могу наконец начать разбираться, как работает Sinatra. Документация среды программирования Sinatra [32] очень подробна и включает множество примеров, и поэтому я решил начать именно с нее.
Основа приложений Sinatra называется маршрут. Лучше всего объяснить это понятие на примере.
Наше простое приложение Sinatra имеет один маршрут, который содержит «корень» сайта. Пользователи интернета обычно указывают корень сайта как начальную страницу сайта.
Если вы заходите на google.com или на yahoo.com, то браузер посылает запрос на сервер Google или Yahoo. Этот запрос называется GET-запросом, и он просит сервер показать вам, что находится в корневом каталоге сайта. Протокол, или формат, который использует компьютер для отправки запроса, называется HTTP, что расшифровывается как «протокол передачи гипертекста». Именно с этой аббревиатуры начинаются адреса в интернете — «http://».
GET — это самый распространенный из запросов HTTP, но не единственный. Существуют три дополнительных «глагола» HTTP:
POST — отправить ресурс на сервер;
PUT — обновить ресурс на сервере;
DELETE — удалить ресурс с сервера.
Если вы оставляете на сайте комментарии, то ваше остроумное замечание отправляется на сервер командой POST. Если вы сделали ошибку и редактируете комментарий, то обновление выполняется с помощью команды PUT. А если вы решили, что комментарий неудачный и его нужно удалить, браузер посылает команду DELETE.
Маршруты GET, POST, PUT и DELETE — это основа работы приложений Sinatra. Каждый создаваемый вами маршрут является условным: «Делать Х, если команда GET/POST/PUT/DELETE получена на маршруте Y».
Маршруты Sinatra также содержат переменные, которые называются параметрами. Приложения Sinatra обычно используют параметры в качестве входных данных для процесса, содержащегося в каждом маршруте.
Давайте модифицируем наше простое приложение Sinatra «Hello, World!», чтобы оно приветствовало пользователя по имени. Вот маршрут, который это делает:
get '/hello/: name' do
"Hello, # {params [: name]}!"
end
Вы можете увидеть результат на http://first20hours.com/hello/name. Попробуйте заменить «name» своим именем. Работает!
Это приложение позволяет серверу посмотреть, что содержится в параметре маршрута «name», и использовать это значение. Команда маршрута представляет собой простую инструкцию — показать параметр «name» пользователю.
Sinatra позволяет вам дать название параметру (например, name), но также имеет «универсальный» параметр (его также называют «решеткой» (splat)), который может содержать все что угодно. Вот как можно использовать его в нашем модифицированном приложении «Hello»:
get '/hello/*' do
"Hello, # {params [: splat]}!"
end
Это очень удобно. С помощью обычных и универсальных параметров можно прописывать самые замысловатые маршруты. Создаваемые вами маршруты определяют работу приложения Sinatra.
Этих сведений достаточно, чтобы понять, как написать программу, которая удовлетворяет моему целевому уровню мастерства. Поскольку Jekyll создает файлы, которые приложение предоставляет по запросам пользователей GET, мне остается лишь написать несколько маршрутов, которые принимают эти запросы, находят в системе нужные файлы и предоставляют их читателю.
Как указывается в документации на Jekyll, программа помещает законченные веб-страницы в папку под названием «site» в корневом каталоге. Маршрут к этой странице автоматически генерируется Jekyll. Если мы хотим, чтобы наша страница About была доступна на http://example.com/about, мы ставим маршрут /about в файлах Jekyll, и программа создаст файл в _site/about/index.html в корневом каталоге нашего сайта.
Это означает, что я должен создать новый маршрут в Sinatra, чтобы прочесть файл в ответ на запрос пользователя GET. Вот как он будет выглядеть:
# Index handler
get '/?' do
## File.read ("_site/index.html")
end
# Post handler
get '/*/?' do
## File.read ("_site/# {params [: splat]} /index.html")
end
Команда File.read (“”) встроена в Ruby. File — это объект, read — метод. Используется она очень просто: содержимое (“”) указывает на расположение файла, который должна прочитать программа, относительно корневого каталога приложения. Легко.
А что если такого файла нет? В этом случае необходимо исключение, и в Sinatra встроены два основных маршрута ошибок: not_found и error. Давайте сделаем так, чтобы оба маршрута вызывали одну и ту же страницу с сообщением об ошибке:
not_found do
## File.read ("_site/error/index.html")
end
error do