Статьи

Использование ненавязчивого JavaScript и AJAX с Rails 3

Как я упоминал в моем предыдущем учебном пособии по Ruby on Rails , ненавязчивый JavaScript (UJS) — одна из самых крутых новых функций в Rails 3. UJS позволяет сгенерированному на Rails коду быть намного чище, помогает отделить вашу логику JavaScript от ваших HTML-макетов и отсоединить Рельсы из библиотеки прототипов JavaScript. В этом руководстве мы рассмотрим эти функции и узнаем, как их использовать в простом приложении на Rails 3.


Для начала, что именно UJS? Проще говоря, UJS — это JavaScript, который отделен от вашей HTML-разметки. Самый простой способ описать UJS с помощью примера. Возьмите обработчик события onclick; мы могли бы добавить это навязчиво:

1
<a href=’#’ onclick=’alert(«Inline Javscript»)’>Link</a>

Или мы могли бы незаметно добавить его, прикрепив событие к ссылке (используя jQuery в этом примере):

1
2
3
4
5
6
<a href=’#’>Link</a>
<script>
$(‘a’).bind(‘click’, function() {
    alert(‘Unobtrusive!’);
}
</script>

Как упоминалось в моем вступлении, этот второй метод имеет ряд преимуществ, в том числе более простую отладку и более чистый код.

«Rails 3, с другой стороны, не зависит от фреймворка JavaScript. Другими словами, вы можете использовать ваш фреймворк JavaScript по своему усмотрению, если для этого фреймворка существует реализация Rails UJS».

До версии 3 Ruby on Rails генерировал навязчивый JavaScript. Полученный код не был чистым, но, что еще хуже, он был тесно связан с платформой Prototype JavaScript. Это означало, что если вы не создали плагин или не взломали Rails, вам пришлось использовать библиотеку Prototype с вспомогательными методами Rail JavaScript.

Rails 3, с другой стороны, не зависит от фреймворка JavaScript. Другими словами, вы можете использовать предпочитаемую среду JavaScript при условии, что для этой среды существует UJS-реализация Rails. Текущие реализации UJS включают в себя следующее:

Rails 3 теперь незаметно реализует все свои функциональные возможности JavaScript Helper (отправка AJAX, запросы подтверждения и т. Д.), Добавляя следующие пользовательские атрибуты HTML 5 к элементам HTML.

  • data-method — метод REST для использования при отправке формы.
  • data-verify — подтверждающее сообщение для использования перед выполнением какого-либо действия.
  • data-remote — если true, отправьте через AJAX.
  • data-disable-with — отключает элементы формы во время отправки формы

Например, этот тег ссылки

1
<td><a href=»/posts/2″ class=»delete_post» data-confirm=»Are you sure?»

отправит запрос на удаление AJAX после запроса пользователя «Вы уверены?»

Вы можете представить, насколько сложнее было бы это прочитать, если бы весь этот JavaScript был встроенным.

Теперь, когда мы рассмотрели UJS и то, как Rails реализует UJS, давайте настроим проект и рассмотрим некоторые конкретные приложения. В этом уроке мы будем использовать библиотеку jQuery и реализацию UJS.


Поскольку мы создаем новый проект с нуля, первое, что нам нужно сделать, это создать проект, набрав следующее:

1
rails new blog —skip-prototype

Обратите внимание, что я инструктирую Rails пропустить прототип файла JavaScript, так как я собираюсь использовать библиотеку jQuery.

Давайте запустим сервер, чтобы убедиться, что все работает.

И, вуаля!

Теперь, когда мы настроили наш проект, нам нужно добавить jQuery и jQuery UJS в наш проект. Вы можете свободно организовывать свой JavaScript так, как хотите, но соглашение Rails для структурирования ваших файлов JavaScript выглядит следующим образом (все эти файлы находятся в public / javascripts):

  • каркасный файл JavaScript (jquery.js, prototype.js или mootools.js)
  • rails.js — код, реализующий рельсы UJS (для любой платформы, которую вы выбрали)
  • application.js — JavaScript вашего приложения

Если вы еще этого не сделали, скачайте jquery.js (или обратитесь к CDN) и rails.js и включите их в свой каталог public/javascripts .

Последнее, что нам нужно сделать, чтобы начать работу, это сказать Rails, что нужно включать эти js-файлы на каждую из наших страниц. Для этого откройте application.rb в вашем каталоге config и добавьте следующую строку

1
config.action_view.JavaScript_expansions[:defaults] = %w(jquery rails application)

Этот элемент конфигурации говорит Rails включить по умолчанию три файла JavaScript, упомянутых выше.

Кроме того, вы можете получить jQuery из CDN (например, http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js ), вручную добавив тег сценария, указывающий на правильное местоположение. Если вы сделаете это, обязательно удалите «jquery» из элемента конфигурации JavaScript_expansions.


Чтобы продемонстрировать функциональность UJS для rails, сначала нам понадобится некоторый код для работы. Для этой демонстрации у нас будет простой объект Post. Давайте сгенерируем это сейчас

1
rails generate scaffold Post name:string title:string content:text

А затем давайте перенесем нашу базу данных, чтобы создать таблицу сообщений.

1
rake db:migrate

Хорошо, мы в порядке! Если мы перейдем по http://localhost:3000/posts/new , мы должны увидеть форму для создания новой публикации.

Ок, все работает! Теперь давайте углубимся и посмотрим, как использовать функциональность UJS и AJAX, встроенную в Rails.


Теперь, когда все необходимые файлы JavaScript включены, мы можем начать использовать Rails 3 для реализации некоторых функций AJAX. Несмотря на то, что вы можете написать весь пользовательский JavaScript, который вам нужен, Rails предоставляет несколько хороших встроенных методов, которые вы можете использовать для простого выполнения вызовов AJAX и других действий JavaScript.

Давайте посмотрим на пару часто используемых помощников рельсов и генерируемый ими JavaScript

Если мы посмотрим на форму «Сообщения», то увидим, что всякий раз, когда мы создаем или редактируем сообщение, форма отправляется вручную, а затем мы перенаправляемся на просмотр этого сообщения только для чтения. Что, если мы хотим отправить эту форму через AJAX вместо ручной отправки?

Rails 3 позволяет легко конвертировать любую форму в AJAX. Сначала откройте ваш частичный _form.html.erb в app / views / posts и измените первую строку с:

1
<%= form_for(@post) do |f|

в

1
<%= form_for(@post, :remote => true) do |f|

До Rails 3 добавление :remote => true генерировало бы кучу встроенного JavaScript внутри тега формы, но в Rails 3 UJS единственным изменением является добавление пользовательского атрибута HTML 5. Вы можете это заметить?

1
<form accept-charset=»UTF-8″ action=»/posts» class=»new_post» data-remote=»true» id=»new_post» method=»post»>

Атрибут data-remote="true" , и JavaScript Rails UJS связывается с любыми формами с этим атрибутом и передает их через AJAX вместо традиционного POST.

Это все, что нужно для отправки AJAX, но как нам выполнить обратный вызов после возврата вызова AJAX?

Наиболее распространенный способ обработки возврата из вызова AJAX — использование файлов JavaScript ERB. Они работают точно так же, как ваши обычные файлы ERB, но содержат HTML-код вместо HTML. Давайте попробуем это.

Первое, что нам нужно сделать, это сообщить нашему контроллеру, как реагировать на запросы AJAX. В posts_controller.rb (приложение / контроллеры) мы можем указать нашему контроллеру, что он должен ответить на запрос AJAX, добавив

1
format.js

в каждом respond_to block который мы собираемся вызвать через AJAX. Например, мы можем обновить действие создания, чтобы оно выглядело так:

01
02
03
04
05
06
07
08
09
10
11
12
13
def create
    @post = Post.new(params[:post])
 
    respond_to do |format|
      if @post.save
        format.html { redirect_to(@post, :notice => ‘Post created.’) }
        format.js
      else
        format.html { render :action => «new» }
        format.js
      end
    end
end

Поскольку в блоке response_to мы не указали никаких опций, Rails будет отвечать на запросы JavaScript, загружая ERB-файл .js с тем же именем, что и действие контроллера (в данном случае create.js.erb).

Теперь, когда наш контроллер знает, как обрабатывать вызовы AJAX, нам нужно создать наши представления. Для текущего примера добавьте create.js.erb в create.js.erb app/views/posts . Этот файл будет обработан, и JavaScript будет выполнен по завершении вызова. Сейчас мы просто перезапишем тег формы заголовком и содержимым сообщения в блоге:

1
$(‘body’).html(«<h1><%= escape_javaScript(@post.title) %></h1>»).append(«<%= escape_javaScript(@post.content) %>»);

Теперь, если мы создадим новую публикацию, на экране появится следующее. Успех!

Преимущество этого метода заключается в том, что вы можете втиснуть код ruby, который вы установили в своем контроллере, с помощью JavaScript, что позволяет очень легко манипулировать вашим представлением с результатами запроса.

Каждая реализация Rails UJS также предоставляет другой способ добавления обратных вызовов к нашим вызовам AJAX — пользовательские события JavaScript. Давайте посмотрим на другой пример. В нашем индексе сообщений ( http://localhost:3000/posts/ ) мы видим, что каждое сообщение можно удалить с помощью ссылки удаления.

Давайте добавим AJAXify к нашей ссылке, добавив: remote => true и дополнительно присвоив ей класс CSS, чтобы мы могли легко найти этот POST с помощью селектора CSS.

1
<td><%= link_to ‘Destroy’, post, :confirm => ‘Are you sure?’, :method => :delete, :remote=>true, :class=>’delete_post’ %></td>

Который производит следующий вывод:

1
<td><a href=»/posts/2″ class=»delete_post» data-confirm=»Are you sure?»

Каждый вызов рельсов UJS AJAX предоставляет шесть пользовательских событий, которые можно прикрепить к:

  • AJAX: до — прямо перед вызовом AJAX
  • ajax: загрузка — до вызова ajax, но после создания объекта XmlHttpRequest)
  • ajax: success — успешный вызов ajax
  • ajax: сбой — сбой вызова ajax
  • ajax: complete — завершение вызова ajax (после ajax: success и ajax: fail)
  • ajax: after — после отправки вызова ajax (примечание: не после его возврата)

В нашем случае мы добавим прослушиватель событий к событию ajax:success в наших ссылках на удаление и сделаем удаленный пост более плавным, чем перезагрузку страницы. Мы добавим следующий JavaScript в наш файл application.js.

1
2
3
$(‘.delete_post’).bind(‘ajax:success’, function() {
    $(this).closest(‘tr’).fadeOut();
});

Нам также нужно будет сообщить нашему posts_controller, чтобы он не пытался отображать представление после того, как оно завершит удаление сообщения.

1
2
3
4
5
6
7
8
def destroy
  @post = Post.find(params[:id])
  @post.destroy
 
  respond_to do |format|
    format.html { redirect_to(posts_url) }
    format.js { render :nothing => true }
  end

Теперь, когда мы удаляем сообщение, оно постепенно исчезает.


Ну, вот и все. Теперь вы знаете, как совершать AJAX-вызовы с помощью Rails 3 UJS. Хотя приведенные примеры были простыми, вы можете использовать эти же методы для добавления всех видов интерактивности в ваш проект. Я надеюсь, вы согласитесь, что это большое улучшение по сравнению с предыдущими версиями, и что вы попробуете это в своем следующем проекте Rails.

Какие методы вы используете при реализации AJAX в Rails?