Ruby
 Computer >> コンピューター >  >> プログラミング >> Ruby

Ruby on RailsでAJAXを使う方法!非同期通信の基本からSJR・remote:trueまで徹底解説

AJAXがなぜ存在するのかを理解すれば、Railsプロジェクトでどう活用すべきかがより明確になります。まずはその背景から見ていきましょう。

Webサイトにアクセスすると何が起こるのか?

サーバーからページが読み込まれます。しかし、新しい情報を確認したいときには、ページを再読み込みして更新するか、リンクをクリックして別のページへ移動するしかありません。

これは同期フロー(synchronous flow)と呼ばれる仕組みです。

新しいデータは、サーバーに新たなページをリクエストしたタイミングでしか表示されません。

でも、考えてみてください…

ページの再読み込みをしたくない場合はどうでしょう?バックエンドからいつでも好きなタイミングでデータを取得し、現在のページの一部だけを更新できたら便利ですよね?

そこで登場するのがAJAXです。

AJAXとは「Asynchronous JavaScript & XML(非同期JavaScriptとXML)」の略称で、非同期通信を実現する技術です。

Webフレームワークに依存しない汎用的な技術ですが、Railsは特にAJAXのサポートが充実しています。本記事で詳しく解説していきます。

なお、アプリにAJAXを導入すると複雑さが増すという点は頭に入れておきましょう。

直接AJAXリクエストを送る方法

AJAXは2つの部分で構成されています。1つはブラウザ側からJavaScriptで送るリクエスト、もう1つはRubyアプリ側で処理するレスポンスです。

AJAXリクエストはプレーンなJavaScriptでも送信できます

ただし、ボイラープレートコード(定型的なコード)が大量に必要になるため、通常はjQueryのようなライブラリを使います。

jQueryでのリクエスト例:

$.get( "/vegetables", function(data) {
  alert("Vegetables are good for you!");
});

ただし、Rails 5.1以降、jQueryはデフォルトでは同梱されなくなりました(後から追加することは可能です)。

注意:jQueryでPOSTリクエストを送ると、InvalidAuthenticityTokenエラーが発生することがあります。これはセキュリティ対策として、現在のページのcsrf-tokenを送信する必要があることを意味します。Rails.ajaxを使えば、この処理は自動的に行われます。

解決策があります!

Railsには独自のAJAX関数が組み込まれています:

Rails.ajax({
  url: "/books",
  type: "get",
  data: "",
  success: function(data) {},
  error: function(data) {}
})

繰り返しますが、これはあくまでリクエスト側、つまりブラウザ側のコードです。つまりこれはJavaScriptのコードだという点に注意してください。

Railsでは、このAJAX機能は「Unobtrusive JavaScript」、略して「UJS」と呼ばれる仕組みによって提供されています。

AJAXでパーシャル(partial)を更新する方法

AJAXで取得したデータを使って、ページの一部だけを更新したい場合、主に2つの選択肢があります。

  1. JavaScript + ERBビューを書き、要素を更新する
  2. コントローラーから新しいHTMLを文字列として含むJSONレスポンスを返し、JavaScriptで要素を更新する

実は3つ目の選択肢もあります。それは、JSON形式のデータのみを返し、そのデータをもとにJavaScriptでHTML要素を生成する方法です。

ここでReactなどのJSフレームワークの出番となりますが、筆者の意見としては、これらのフレームワークは不要な複雑さを招くことが多いと感じています。

プレーンなJavaScriptでも十分対応できます!それが選択肢1と2です。まずはこの2つを見ていきましょう🙂

JavaScriptビューの例:

Rails.$('.random-number')[0].innerHTML = ("<%= j (render partial: 'random') %>")

jescape_javascriptのエイリアスです

jQueryの例:

$('.random-number').html("<%= j (render partial: 'random') %>")

htmlinnerHTMLも、対象要素の中身を丸ごと置き換えます。全体を置き換える代わりに、リストへ新しい要素を追加(append)することも可能です。

このコードは、.js.erbという拡張子のファイルに、現在のアクション名(例:create.js.erb)を付けて、viewsフォルダ内に保存します。

コントローラー側では、他のビューと同じようにこのビューをレンダリングできます。

すると:AJAX呼び出しを行うと、このJavaScriptコードが自動的に実行され、HTMLが更新されます。

次に2つ目の選択肢を見てみましょう。

コントローラーコード:

render json: { html: render_to_string(partial: 'random') }

その後、JavaScriptコード側で:

Rails.ajax({
  url: "/books",
  type: "get",
  success: function(data) { Rails.$(".random-number")[0].innerHTML = data.html; }
})

これがもう1つの実装方法です!

どちらを使うべき?

Railsの生みの親DHHのお気に入りは最初の方法で、彼はこれを「SJR(Server-Generated JavaScript)」と呼んでいます。

Railsが推奨しているのはこちらの方法なのでしょうが、両方(SJRrender_to_string)実際に試してみて、自分のプロジェクトに合った方を選ぶのが良いでしょう。

HAMLをJSビューで使う方法

さて、HAMLユーザーの場合はどうでしょうか?SJRテクニックを使って.js.hamlビューをレンダリングできるのでしょうか?

答えはYes!

:

- content = j (render partial: "random")

Rails.$('.random-number')[0].innerHTML = ("#{content}")

ERB版より少し見た目は劣りますが、問題なく動作します。

フォームをページ遷移なしで送信する方法

フォームをAJAXで送信したい場合、AJAXリクエストのコードを自前で書く必要はありません。Railsが代わりに処理してくれるのです。

どのように?form_forremote: trueオプションを指定するだけです。

:

<%= form_for @fruit, remote: true do |f| %>
  <%= f.label :name, 'Fruit' %>
  <%= f.text_field :name %>

  <%= f.submit 'Create' %>
<% end %>

こうすることで、「Create」ボタンをクリックすると、Railsが自動的にAJAXリクエストを送信し、ページは再読み込みされません。

バリデーションエラーを表示したい場合は、既存のエラー表示を新しいエラーに置き換えるJavaScriptビュー(.js.erbファイル)を作成・レンダリングする必要があります。「AJAXでパーシャルを更新する方法」のセクションの例と同じ要領です。

ちなみに、このremoteオプションはリンクにも使えるため、AJAXによるdeleteリクエストも可能です。

:

<%= link_to "Delete", book_path(book), { method: "delete", remote: true, data: { confirm: "Are you sure?" } }

レスポンスの処理にはJavaScriptビューを使用できます。

HTMLリクエスト(ページ再読み込み由来)とAJAXリクエストの両方に対応したい場合は、respond_toメソッドなどを使います。

:

respond_to do |f|
  f.html { redirect_to :index }
  f.js
end

このようなケースでは、Turbolinksに任せた方が簡単かもしれません。AJAXリクエストを実行し、コントローラーからredirect_toを行えば(respond_toなしでも)、Turbolinksがページを再読み込みせずに内容を差し替えてくれます。

AJAXが動かないときのデバッグのコツ

AJAXリクエストがうまく動作しない場合は、デバッグが必要です。

まず、ブラウザの開発者ツールを開き、コンソールパネルにJavaScriptエラーが表示されていないか確認しましょう。エラーがあれば修正します。

また、指定しているCSSセレクタが正しいか、タイプミスがないかもチェックしてください。

次に、Railsのログにエラーが出力されていないか確認します。そして、正しいビューがレンダリングされているかも見てみましょう。

この手順に従えば、AJAXリクエストが動作しない原因を特定し、修正できるはずです。

まとめ

この記事では、非同期リクエストを可能にするWeb開発技術であるAJAXについて学びました。Railsでの実装方法も理解できたはずです。

忘れてならないのは、通常の(JSフレームワークを使わない)Railsアプリの動作にAJAXは必須ではないという点です。しかし、開発者のツールボックスに入れておくと必ず役立つ技術であることは間違いありません。

最後に、この記事をシェアして、より多くの方の参考になれば嬉しいです🙂

お読みいただきありがとうございました!


  1. RubyのStructとOpenStructの使い方を徹底解説!値オブジェクトを簡単に作る方法

    Rubyには、関連する属性をまとめて保持する「値オブジェクト」を手軽に作れるStructという組み込みクラスが用意されています。本記事では、Structの基本的な使い方から注意点、そしてOpenStructとの違いまで詳しく解説します。 そもそもStructとは何か? StructはRubyに組み込まれたクラスで、新しいクラスを動的に生成し、値オブジェクト(Value Object)を作成するために使われます。値オブジェクトとは、関連性のある複数の属性をひとまとめにして扱うためのオブジェクトです。 具体例を挙げてみましょう。 2つの座標(xとy)を持つPointというデータを表したい場合、この

  2. RailsアプリでTwitterログインを実装する方法:OmniAuth-Twitter完全ガイド

    このチュートリアルでは、RailsアプリケーションのユーザーがTwitterアカウントを使ってログインできるようにする方法を解説します。OAuthなどのツールのおかげで、この実装はとても簡単に行えるようになりました。 今回は、OmniAuth用のTwitterストラテジーを含む「OmniAuth-Twitter」を使用します。 それでは始めましょう! はじめに:プロジェクトの準備 まずはRailsアプリケーションを生成します。ターミナルで以下のコマンドを実行してください。 rails new Tuts-Social -T 次にGemfileを開き、bootstrap gemを追加します。