【Rails初心者】Ajaxの実装方法を理解する(非同期通信)

サーバーからのレスポンスを待たずに他の作業ができるようになる素晴らしい通信…それが非同期通信！！
ツイッターの「いいね」なんかは非同期通信で、いいねのデータを保存したりしている間もユーザは投稿を見たりできます。非同期通信を実装できればUXの向上が期待できますね！

私もいいねを非同期にするため試行錯誤したのですが、Ajaxの仕組みがよく分かっておらず、何をやっているのかチンプンカンプンでした…

いろいろ調べてやっと自分なりにAjaxの実装方法が理解できたので、まとめてみようと思います。
仕組みを理解することで、いいねの非同期実装が無事にできました!

#Ajaxを使って動的にタイトルを変更する
Sumrai Blogの[【Rails入門】ajaxの使い方まとめ](https://www.sejuku.net/blog/28967)を参考に学習していきます。

仕組みをちゃんと理解するには、**まずは簡単なものから実装する**べし。ということで、設定したタイトルをフォームに入力した値に変更する、ということを非同期でやってみたいと思います。

<img width="1363" alt="スクリーンショット 2019-08-15 13.11.25.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/373922/549d3fa2-aa7c-f533-e37b-404f078bd477.png">


実装の手順はだいたいこんな感じです。たったの3ステップ！
★がついているところが、ajaxに関する設定です

1.タイトル、フォームといった元となる部分(viewやroute)を整える
2.★フォームのpostリクエストをjs形式にする = **formにremote: trueを追加する**
3.★タイトルをpostで送られてきた値に変更するようjs.erbファイルに書く = **○○.js.erbファイルを作成してJavaScriptを書く**

これで非同期通信ができます!

**リクエストをjs形式にして、○○.js.erbファイルを読み込んでもらう**、というのがざっくりとした説明です。○○.js.erbは「js」の名前の通りjavascriptを実行するファイルなので、処理を設定した部分だけ変更されます。なのでページ遷移をせず内容を変えることができるんですねー。

##1.タイトル、フォームといった元となる部分(viewやroute)を整える
まずはタイトルとフォームを作りましょう。
新しいrailsプロジェクトを作り、データベースを作成してローカルホストでrailsを動かせるようにします。

今回はデータベースにデータを保存しないのでModelは作りません。それでは順番に作業を進めていきます。

1.**Practiceコントローラー**と**indexアクション**を作成する
以下のコマンドを実行しましょう。controllerとviewが生成されます。

```
$ bundle exec rails g controller Practice index 
```

2.routeの設定
トップページを先ほど生成した**practiceのindexファイル**にします。
ローカルホストにアクセスしたらindexファイルが読み込まれるようにしましょう。
また、**フォームが送信(post)**されたら**practiceControllerのindexアクション**ヘいくように設定します。

```config/routes.rb
Rails.application.routes.draw do
  root to: 'practice#index'
  #トップページをindexファイルにする
  post '/', to: 'practice#index'
  # /から来たpostのルーティング設定 practiceのindexコントローラーへ
end
```
3.viewを整える
viewにタイトルとフォームを作ります。
Modelには関連づけないので、`fomr_tag`を使用します。

```html:app/views/practice/index.html.erb
<!-- タイトル -->
<h1>Ajaxの練習</h1>

<!-- フォーム -->
<%= form_tag(url_for(:action => 'index')) do %>
  <%= text_field_tag :title %>
  <%= submit_tag "タイトルを変更する" %>
<% end %>
```
これで元の部分ができました。
<img width="325" alt="スクリーンショット 2019-08-15 13.44.31.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/373922/eb422106-88da-2486-935a-2571f47c66bf.png">

##2.★フォームのpostリクエストをjs形式にする
ここから非同期にするための作業になっていきます。
Railsでは**turbolinks**を使えば、ajaxが自動的に使えます。

〜turbolinksとは〜
ページ遷移をAjaxに置き換え、JavaScriptやCSSのパースを省略することで高速化するgemで、Rails 4からはデフォルトで使用されるようになります。
[Rails 4のturbolinksについて最低でも知っておきたい事](https://kray.jp/blog/must-know-about-turbolinks/)より

**デフォルトで使用されてる、ajaxが使えるようになるgem**っていうことですね。

turbolinksを有効にするには、**postリクエストをjs形式**にすればいいみたいです。
普段link_toやform_forで使っているのはhtml形式のリクエストです。これをjs形式に変更しましょう。
js形式に変更する方法はとても簡単で、フォームに**remote: true**を付け加えるだけです！

```html:app/views/practice/index.html.erb

<!-- フォーム -->
<%= form_tag(url_for(:action => 'index'), :remote => true) do %>
  <%= text_field_tag :title %>             ↑↑↑追加する↑↑↑
  <%= submit_tag "タイトルを変更する" %>
<% end %>
```
js形式に変更すると、値を入れて変更ボタンを押しても何も変化しなくなります。
実際にサーバのlogを確認してみましょう。POSTのリクエストがhtml形式からjs形式に変更されているのが分かります。
<img width="738" alt="スクリーンショット 2019-08-15 14.35.38.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/373922/16708070-6865-1632-9da9-9d45abcd2ad6.png">

では、js形式に変えるとどうなるのでしょうか？
controllerは「app/views/controller名/アクション名.リクエストの形式.erb」というファイルを探しに行きます。
つまり、今回のpostリクエストでいうと、html形式だとapp/views/practice/**index.html.erb**、js形式だとapp/views/practice/**index.js.erb**を読み込みます。
js.erbファイルはjavascriptを実行するので、そこに部分的な変更処理を設定することでページ遷移をせずページの内容を一部変更(=非同期通信)ができるのです！
<img width="599" alt="スクリーンショット 2019-08-15 19.46.56.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/373922/c8b1319d-a87c-ae8e-b7be-f144264e8ecd.png">


html形式とjs形式の違いについては、以下の記事から学びました。理解を深めたい方は是非参考にしてみてください！
[Railsで remote: true と js.erbを使って簡単にAjax(非同期通信)を実装しよう！(いいね機能のデモ付)](https://qiita.com/__tambo__/items/45211df065e0c037d032)

##3.★タイトルをpostで送られてきた値に変更するようJavaScriptを書く
フォームの送信をjs形式にできたので、postをした時に**app/views/practice/index.js.erbファイルが読み込まれる**ように設定できました。

では、**app/views/practice/index.js.erb**ファイルを作成して、タイトルをフォームの値に変更する処理を設定していきましょう。

1.フォームの値をviewへ渡せるようにする
index.js.erbでフォームの値を使用するので、viewに値を渡せるようにcontrollerでフォームの値をインスタンス変数に格納します。

```app/controllers/practice_controller.rb
class PracticeController < ApplicationController
  def index
    @title = params[:title]
    # フォームに入力された値を@titleに入れる
  end
end
```
2.index.js.erbでタイトルをフォームの値に変更する処理を設定する
**app/views/practice/index.js.erbファイルを作成**して、以下のコードを書きます。

```html:app/views/practice/index.js.erb
$('h1').html("<%= @title %>");
<!-- h1(タイトル)を@titleに変更する -->
```
実際にフォームに値を入力して送信してみると、URLを変えずにタイトルだけ変更されると思います。これでめでたく非同期通信デビューです！！

#最後に
今回はAjaxの実装方法をまとめました。Ajaxの仕組みを理解できたので、いいねの非同期もしっかり理解して実装することができました。
いいね以外にもいろいろな通信を非同期にしたいですね！

最後まで読んでくださりありがとうございました!

#参考
学習教材
・[Sumrai Blog:【Rails入門】ajaxの使い方まとめ](https://www.sejuku.net/blog/28967)
Ajax関連
・[Railsで remote: true と js.erbを使って簡単にAjax(非同期通信)を実装しよう！(いいね機能のデモ付)](https://qiita.com/__tambo__/items/45211df065e0c037d032)
・[初心者目線でAjaxの説明](https://qiita.com/hisamura333/items/e3ea6ae549eb09b7efb9)
・[Rails 4のturbolinksについて最低でも知っておきたい事](https://kray.jp/blog/must-know-about-turbolinks/)