Статьи

Фабрика роботов — часть вторая

Асинхронное добавление и удаление ресурсов в Синатре

В первой части этого урока мы рассмотрели, как добавлять и удалять роботов в базе данных. В этом уроке я покажу, как вы можете использовать XMLHttpRequest для выполнения действий в фоновом режиме без необходимости обновления страницы. Это верно — мы собираемся зарядить приложение турбомотором с помощью Ajax! Если вы не прятались в пещере в течение последних пяти лет, вы, вероятно, слышали об Ajax — это в основном метод публикации и извлечения данных в фоновом режиме, который обычно используется для обновления частей веб-страницы без выполнения полной обновление страницы.

Тот факт, что код из первой части Robot Factory работает до добавления Ajax, является хорошей вещью, поскольку это означает, что он будет работать для любых браузеров, в которых не включен JavaScript или которые не поддерживают XMLHttpRequest (современные дети называют это прогрессивное улучшение ). Добавление Ajax в основном состоит из трех этапов:

  1. Остановить фактический запрос, чтобы страница не перезагружалась
  2. Вставьте HTML-код для нового ресурса на страницу, возможно, с каким-то фантастическим эффектом
  3. Сохраните новый ресурс в базе данных в фоновом режиме

Я собираюсь использовать фантастическую JavaScript-библиотеку RightJS, чтобы помочь позаботиться об Ajax.

Для начала нам нужно включить необходимые файлы JavaScript в наш макет:

script src="http://cdn.rightjs.org/right.js"
  script src="/application.js"

Далее нам нужен маршрут, указывающий, что JavaScript будет записан в том же файле:

 get('/application.js') { content_type 'text/javascript' ; render :str, :javascript, :layout => false }

И наконец, нам нужно место для размещения пользовательского JavaScript, который мы будем добавлять. Это идет под всеми другими представлениями внизу страницы:

 @@javascript
// javascript goes here

Удаление с помощью Ajax

Мы делаем это, добавляя немного JavaScript. Мы можем написать это как еще одно встроенное представление под всем остальным кодом представления. Фактический необходимый JavaScript не очень большой, но он опирается на некоторую магию RightJS. Начнем с того, что сделаем запрос на удаление немного более резким:

 @@javascript

"form.destroy".onSubmit(function(event) {

   this.parent().fade();

   event.stop();

   this.send();

 });

Этот бит JavaScript использует удивительный синтаксис UJS, который RightJS использует для поиска всех элементов, соответствующих правилу css `form.destroy` (т.е. все формы с классом ‘destroy’ — кнопки удаления на каждом роботе). Затем он динамически добавляет следующие события:

  1. this.parent().fade(); Родительский узел (то есть сам робот) будет исчезать и исчезать, используя приятный эффект исчезновения, встроенный в RightJS.
  2. event.stop(); Фактическое действие формы будет остановлено, поэтому оно не будет отправлено обычным способом.
  3. this.send(); Это отправит форму, используя Ajax.

Хорошим преимуществом RightJS является то, что эта функция применяется ко всем формам с классом уничтожения — даже к тем, которые создаются на лету после загрузки файла JavaScript, как мы будем делать в следующем разделе. Прежде чем сделать это, мы должны рассмотреть, что происходит, когда Sinatra получает запрос на удаление асинхронно. На данный момент наш обработчик выглядит так:

 delete '/delete/robot/:id' do

 Robot.get(params[:id]).destroy

 redirect to('/')

end

Это нормально, за исключением того, что мы на самом деле не хотим обновлять страницу, делая перенаправление, если мы используем Ajax. В Синатре есть отличный метод (ну, на самом деле он из Rack ), который называется request.xhr? который вернет true, если запрос является Ajax-запросом, и false в противном случае. Мы можем использовать это, чтобы остановить перенаправление, когда используется Ajax:

 delete '/delete/robot/:id' do

 Robot.get(params[:id]).destroy

 redirect to('/') unless request.xhr?

end

Добавление с помощью Ajax

Теперь давайте посмотрим на создание робота с использованием Ajax. Следующий JavaScript идет под предыдущим блоком кода:

 "form.build".onSubmit(function(event) {

 event.stop();

 this.send({

   onSuccess: function(xhr) {

   $('robots').insert(xhr.responseText);

  }

 });  

});

Это работает аналогично функции удаления выше. Это применяется ко всем формам с классом ‘build’ (то есть с большой кнопкой Build A Robot). Сначала он останавливает отправку формы, а затем отправляет ее с помощью Ajax. Эта функция также содержит обратный вызов, который происходит, когда запрос Ajax был выполнен успешно. Он говорит, чтобы вставить текст ответа в список с идентификатором «роботы». В основном это добавит нового робота в конец списка. Чтобы это работало, нам нужно убедиться, что робот возвращен. На данный момент обработчик выглядит так:

 post '/build/robot' do
 robot=Robot.create
 redirect to('/')
end

Это просто создает нового робота. Нам нужно сделать что-то немного иначе, если там робот создан с использованием Ajax, поэтому мы снова дойдем до request.xhr? метод:

 post '/build/robot' do

 robot=Robot.create

 if request.xhr?

   slim :robot, { :layout=> false, :locals => { :robot => robot } }

 else

   redirect to('/')

 end

end

После того, как робот был создан и сохранен в базе данных, мы проверяем, является ли запрос Ajax-запросом. Если это то, что является результатом представления робота, которое мы создали ранее (сказали, что это будет полезно). Мы включили несколько дополнительных параметров, чтобы убедиться, что мы не включаем макет в этот фрагмент ( :layout=>false:locals => { :robot => robot } Если это не Ajax-запрос, мы просто делаем то же самое, что и раньше, — перенаправляем обратно на домашнюю страницу, и новый робот в любом случае будет отрисован, когда этот запрос будет обработан.

Вращаясь вокруг

Осталось только добавить один из тех крутых блесен Ajax, которые показывают, что что-то действительно происходит в фоновом режиме. Зайдите на http://www.ajaxload.info/ и создайте GIF вашего любимого дизайна блесны. Сохраните его в папке public в том же каталоге, что и код Sinatra, затем внесите следующие изменения в свой код. В представлениях добавьте изображение на страницу индекса (убедитесь, что вы даете ему запоминающийся идентификатор, я использую «ожидание»):

 @@index

…

img#waiting src="https://s3.amazonaws.com/daz4126/waiting.gif"

Add some css, so that the spinner is not displayed by default:

@@styles#waiting{display:none;position:absolute;left:200px;top:100px;}

Затем в JavaScript сообщите RightJS идентификатор счетчика:

 @@javascript

Xhr.Options.spinner = 'waiting';

...

Вот и все! Мы сделали интерфейс намного более быстрым, используя вызовы Ajax, и избежали необходимости перезагружать страницу каждый раз, когда мы добавляем и удаляем робота. Это также означает, что к базе данных не так часто обращаются, чтобы получить массив @robots. Страница также выглядит намного лучше, а исчезающий эффект добавляет дополнительный блеск в приложение. Конечно, вы могли бы легко сделать это в одной из многих других фреймворков JavaScript, но я чувствую, что RightJS предлагает очень сжатый и прямой способ работы с Ajax. Я хотел бы услышать любые мысли об этом, а также ваш опыт использования Ajax в веб-приложениях в комментариях.

Вы можете увидеть полный код на github и поэкспериментировать с моей версией .

Наслаждайтесь созданием роботов!