Добро пожаловать во вторую часть нашего учебника из двух частей. В прошлый раз мы установили Ruby on Rails, сгенерировали приложение для сокращения URL-адресов и создали для него модель.
Теперь мы собираемся создать Controller для нашего приложения, написать View и посмотреть, сможем ли мы заставить приложение работать. Возможно, вы захотите просто быстро просмотреть, где мы были в первой части , а затем продолжить.
Создание вашего первого контроллера
Теперь, когда мы создали нашу модель (с Rails, заботящейся о постоянстве и валидации), пришло время написать контроллер. Часть Controller ваших приложений обрабатывает ввод данных (например, данные из URL или тела запроса в случае POST и PUT), а затем взаимодействует с моделью, а также настраивает данные для части представления.
Контроллеры RESTful
По умолчанию Rails подчеркивает подход «RESTful»; то есть он использует заданный HTTP-глагол (например, GET, POST, PUT, DELETE) и хорошо организованные URL-адреса для представления ресурсов, что приводит к общей структуре, в которой код используется для операций над объектом. Он предоставляет инструменты для обработки основных действий CRUD (создание, чтение, обновление, удаление) над вашими данными. В терминологии Rails действия обычно следующие:
-
index
— действие, которое возвращает список всех ресурсов; например,GET /urls
действие index на контроллере URL, перечисляя известные URL. -
show
— действие, которое выполняет операцию чтения для одного ресурса; например,GET /urls/1
попадет на шоу на контроллере URL, показывая детали URL с идентификатором 1. -
new
— действие, чтобы показать новую форму объекта, в нашем случае, новую форму URL; например,GET /urls/new
выполнит действие new на контроллере URL и покажет форму нового URL. -
create
— действие после публикации, чтобы извлечь данные формы из нового действия и попытаться создать запись; например,POST /urls
будет выполнять действие create на контроллере URL, как правило, с некоторыми связанными данными формы. -
edit
покажет форму для редактирования определенного ресурса; например,GET /urls/1/edit
выполнит действие edit на контроллере URL и покажет форму для редактирования URL с идентификатором 1. -
update
попытается обновить данный ресурс; например,PUT /urls/1
выполнит действие обновления на контроллере URL и попытается обновить URL с идентификатором 1. -
destroy
попытаться уничтожить данный ресурс; например,DELETE /urls/1
выполнит действие уничтожения на контроллере URL и попытается уничтожить URL с идентификатором 1.
Генерация нашего контроллера
В нашем примере мы собираемся сократить его от полноценного контроллера CRUD и реализовать три основных действия: new
, create
и show
. Когда пользователь нажимает new
действие, он отображает новую форму URL. Это, в свою очередь, коснется действия create
когда мы отправим форму и попытаемся создать объект URL.
Наконец, когда пользователь нажимает действие show
, мы перенаправляем его на сохраненный URL-адрес.
Итак, используйте опцию «Командная строка с Ruby и Rails» в меню «Пуск», чтобы открыть командную строку и перейти в каталог, где вы сохранили свой код. Мы создадим новый контроллер URL с одним новым действием, выполнив:
rails generate controller urls new
Причина, по которой мы передали только new
действие (вместо new
, create
и show
), заключается в том, что Rails автоматически генерирует фиктивное представление для каждого действия, включенного в вызов генератора. В этом случае нам нужно только фиктивное представление для new
действия, поэтому мы исключаем другие.
Выполнение команды должно было создать файл app/controllers/urls_controller.rb
файл app/views/urls/new.HTML.erb
, а также несколько тестовых файлов. На данный момент откройте файл Controller, и вы увидите нечто похожее на:
class UrlsController < ApplicationController def new end end
И, если вы откроете config/routes.rb
, вы также увидите, что он добавил фиктивный маршрут для нас:
get "urls/new"
Чтобы начать, оставаясь в config/routes.rb
, замените строку выше:
resources :urls, :only => [:show, :new, :create]
Сохраните файл, вернитесь в командную строку и запустите rake routes
. Это распечатает список всех наших маршрутов. Как видите, Rails автоматически устанавливает для нас три URL-адреса: GET /urls/new
, GET /urls/:id
и POST /urls
указывающие на действия new
, show
и create
соответственно.
Если мы запустим сервер (используя rails server
) и нажмем на URL для нового действия в браузере ( http://localhost:3000/urls/new
), вы должны увидеть страницу-заполнитель, похожую на изображение ниже.
Написание логики нашего контроллера
В этом случае логика нашего контроллера будет очень простой:
- Когда пользователь
@shortened_url
на новую страницу, он устанавливает@shortened_url
экземпляра@shortened_url
в новый несохраненный объект URL (в качестве переменной экземпляра мы используем@shortened_url
вместо@url
, поскольку последняя используется внутри Rails). - Когда пользователь отправляет новую форму, мы должны попытаться создать новый URL. Если он действителен и сохраняет, мы установим сообщение, сообщающее пользователю URL-адрес его сокращенной ссылки, а затем снова перенаправим обратно на страницу Сокращения.
- Если URL-адрес недействителен, мы повторно отобразим новую форму, на этот раз с ошибками.
- Когда пользователь нажимает на действие show, мы перенаправляем его на URL.
Итак, теперь, когда в вашем редакторе открыт appcontrollersurls_controller.rb
, замените весь код на:
class UrlsController < ApplicationController def new @shortened_url = Url.new end def create @shortened_url = Url.new(params[:url]) if @shortened_url.save flash[:shortened_id] = @shortened_url.id redirect_to new_url_url else render :action => "new" end end def show @shortened_url = Url.find(params[:id]) redirect_to @shortened_url.url end end
Сохраните файл. Здесь важно отметить один важный момент: наш выбор названия модели — Url — привел к потенциально запутанным маршрутам (например, new_url_url
). Чтобы понять, что именно это означает, нам просто нужно запомнить вывод rake routes
. Там мы увидели маршрут с именем new_url
(среди прочих). Rails автоматически предоставляет нам метод new_url_url
(если наши ресурсы вызывают в config/routes.rb
:posts
вместо :urls
new_post_url
вместо него будет new_post_url
), а также эквивалент _path
; например, new_url_path
. Разница между ними заключается в том, что варианты _url
включают хост, порт и протокол, тогда как варианты _path
включают только путь и строку запроса.
В приведенном выше коде контроллера вы могли заметить строку, содержащую:
flash[:shortened_id] = @shortened_url.id
Если вы ранее использовали такой язык, как PHP, где у вас есть сеанс для хранения данных, вам будет приятно узнать, что Rails также поддерживает сеанс для обмена данными между запросами. Вдобавок к этому у этого также есть вторая особенность — вспышка — которая является сеансом, который автоматически заканчивает записи. Когда мы храним данные во флэш-памяти (например, идентификатор нашего сокращенного URL-адреса выше), они будут удалены после обращения к ним. Это особенно полезно для таких задач, как передача сообщений об ошибках и состояниях (в отличие от URL), так как они будут показаны один раз и исчезнут при последующих загрузках страниц.
После всего этого нам нужно сделать одну небольшую корректировку: мы хотим сделать так, чтобы, если пользователи переходили на корневую страницу нашего приложения (например, http://localhost:3000/
), они автоматически перенаправлялись на Новая форма URL. В этом случае довольно просто сделать две вещи:
- Удалите файл
public/index.html
. Это просто страница «Welcome to Rails» по умолчанию, но когда она присутствует, она переопределяет наш корень, показывая каждому пользователю страницу «Welcome to Rails». - В
config/routes.rb
добавьте новую строку ниже нашего вызова ресурсов.
Строка, которую мы добавим, должна выглядеть так:
root :to => redirect('/urls/new')
Это говорит Rails, что когда мы нажимаем на корневой URL (эквивалент get '/'
в нашем файле маршрутов), он должен автоматически перенаправить на новое действие URL.
Чтобы попробовать, вернитесь к терминалу, перезапустите сервер Rails, если вы его закрыли, а затем укажите в браузере http://localhost:3000/
. Если все прошло как ожидалось, ваш браузер должен был автоматически перенаправиться на http://localhost:3000/urls/new
.
Написание вашего взгляда
Когда контроллер и модель для Shorty готовы к использованию, пришло время добавить последний слой: представление.
Вид — это та часть, которая фактически отображается пользователю. По умолчанию наши представления написаны на ERb: внедренный ruby. ERb позволяет нам вставлять биты ruby в наш HTML для создания динамических страниц. Например, чтобы показать значение атрибута URL в объекте URL, мы использовали бы что-то вроде этого в нашем представлении:
<%= @shortened_url.url %>
Затем во время выполнения Rails интерпретирует часть ruby для генерации нашего HTML. Поскольку наше приложение очень простое, нам нужно отредактировать только два представления: файл app/views/urls/new.html.erb
и наш макет app/views/layouts/application.html.haml
.
Редактирование вашего макета
Макеты — это Rails-способ определения общей структуры или макета страницы. В то время new.html.erb
файл new.html.erb
используется для HTML, специфичного для нашего действия (то есть, например, новое действие на другом контроллере будет использовать другой шаблон), макеты обычно повторно используются в нескольких или во всех действиях. Они обычно используются для настройки общей структуры страницы; например, верхние колонтитулы, меню, нижние колонтитулы и т. п., в то время как специфичные для страницы вещи переходят в обычный вид.
В этом случае наш application.html.erb
умолчанию выглядит так:
<!DOCTYPE html> <html> <head> <title>Shorty</title> <%= stylesheet_link_tag :all %> <%= javascript_include_tag :defaults %> <%= csrf_meta_tag %> </head> <body> <%= yield %> </body> </html>
Это очень простая HTML5-страница, которая делает только представление действия внутри тега body. Единственный аспект, который мы собираемся изменить на этой странице (чтобы сделать его многократно используемым при расширении приложения в будущем), — это когда мы укорачиваем ссылку, мы получаем ссылку на нее в верхней части страницы. Итак, ниже открывая тег и над строкой с
yield
, добавьте следующее:
<% if flash[:shortened_id].present? %> <p class='shortened-link'> The shortened url is available <%= link_to 'here', url_url(flash[:shortened_id]) %>. (Right click and copy link to share it). </p> <% end %>
link_to
в коде - это просто вызов так называемого вспомогательного метода; в этом случае что-то, что Rails определяет для нас, генерирует HTML для ссылки с заданным текстом (в данном примере 'here'
), указывающим на заданный URL (в данном случае что-то вроде http://localhost:3000/urls/1
) когда URL был сокращен. Если во флэш-памяти присутствует значение no :shortened_id
, ничего не будет показано, но если оно присутствует, оно выведет ссылку на него внутри тега абзаца.
Редактирование вашей формы
После того, как макет обновлен, чтобы показать сокращение ссылки, нам нужно настроить нашу форму. Сначала откройте app/views/urls/new.html.erb
в вашем редакторе. По умолчанию это должно выглядеть так:
<h1>Urls#new</h1> <p>Find me in app/views/urls/new.html.erb</p>
Удалите это и замените это:
<h1>Add a new URL</h1> <%= form_for @shortened_url do |form| %> <p> <%= form.label :url, "Your URL:" %> <%= form.text_field :url %> </p> <% if @shortened_url.errors[:url].any? %> <p class='error-messages'> The given url <%= @shortened_url.errors[:url].to_sentence %>. </p> <% end %> <p class='buttons'> <%= form.submit "Shorten my URL" %> </p> <% end %>
При запуске этот код сгенерирует тег формы (с правильным действием и методом) с кучей других HTML-кодов внутри него. Здесь, внутри, он сгенерирует абзац, содержащий метку и текстовый ввод для нашего поля URL. В этом случае мы используем определенный класс помощников через метод form_for
. Это классы, предоставляемые Rails, чтобы упростить создание сложных форм путем обработки генерирующих полей и тому подобного.
Затем мы проверяем, есть ли какие-либо ошибки в поле URL сокращенного объекта URL, и генерируем тег абзаца с error-messages
класса, когда они есть. Если у объекта нет ошибок, он не будет выводить HTML вообще для этой части.
Наконец, мы генерируем тег отправки с текстом «Сократить мой URL», заканчивая нашу форму.
Тестирование
Вернувшись к консоли и снова запустив сервер Rails (если он был остановлен), перезагрузите http://localhost:3000/urls/new
в вашем браузере, и вы должны увидеть следующее.
Если вы щелкнете по Сократить мой URL-адрес, не указав URL-адреса в поле «Ваш URL-адрес», вы получите следующую страницу с ошибкой.
Если вы введете действительный URL-адрес в поле «Ваш URL-адрес» и нажмете «Сократить мой URL-адрес» (например, http://google.com/
), вы увидите следующее изображение.
В качестве бонуса, используя конструктор форм, Rails предоставляет множество дополнительных возможностей. Например, он автоматически устанавливает значение текстового поля, чтобы при повторной отправке (после ошибки) он вставлял специальный токен для предотвращения подделки межсайтовых запросов . В общем, это позволяет очень легко создавать формы.
Завершение всего этого
Как вы уже видели, с очень небольшим количеством кода мы смогли создать элементарное сокращение URL-адресов (насколько короткие URL-адреса на самом деле зависят от вашего домена и входного URL-адреса, но в целом важна идея). Мы только что коснулись того, что вы можете делать с Rails, но нам удалось покрыть приличное количество Rails за короткий промежуток времени.
Конечно, приложение, которое мы создали, не лишено недостатков. Например, пока мы проверяем, что URL действительно задан, мы не проверяем, что это URL (и мы слепо перенаправляем на это значение); следовательно, это не тот код, который вы бы на самом деле развернули. Кроме того, сам рабочий процесс очень элементарный.
Если вы заинтересованы в том, что вы уже сделали, у вас есть хорошая отправная точка, чтобы узнать больше о Ruby on Rails. Например, вы можете добавить улучшенную проверку URL-адресов, добавить способ перечисления всех сокращенных URL-адресов или, что еще лучше, использовать маршруты и настраиваемое действие, которое больше похоже на существующие средства сокращения URL-адресов. Для получения бонусных баллов вы можете переключиться на альтернативный конструктор форм , такой как formtastic , который создаст для нас еще более глубокий HTML- код (избавляя от необходимости выполнять такие задачи, как печать сообщений об ошибках вручную).
Существует много документации для начинающих Rails, некоторые лучше, чем другие, и некоторые из них требуют оплаты. Я настоятельно рекомендую вам начать со следующих ресурсов:
- Официальные путеводители по железным дорогам - бесплатно, много актуальной информации и отличное место для начала.
- API Ruby on Rails - справочник по API для методов, доступных в Rails.
- Railscasts - множество (250 и более) бесплатных коротких скринкастов о выполнении различных задач в Rails.
- PeepCode - платные, но профессионально сделанные скринкасты по темам. Дольше, чем Railscasts и, как правило, более глубоко.
- Rails Tutorial - бесплатная книга (с платными загружаемыми версиями), которая служит подробным руководством по Rails.
Надеюсь, вам понравилось получить краткое представление о способах работы Rails.
Кредит с изображением: http://www.flickr.com/photos/wwworks/2475349116/