Ajax

Ajaxってよく聞くけどどういうものなのか、かなりざっくりした説明になってしまいますが自分なりにまとめてみました。

同期通信と非同期通信

Ajaxを知るためにまずは非同期通信、そして対になる同期通信について知る必要があります。

  • 同期通信

通常の通信方法。
ページをまるごと遷移するためレスポンスが返ってくるまで他の処理はできません。

  • 非同期通信

ページまるごと更新するのではなく、
必要な部分だけ更新するため画面遷移がありません。

Ajaxとは

既存の技術を組み合わせたアプローチで、簡単にいうと、JavaScriptで非同期通信することです。

何ができる?

  • 検索フォームに文字を入力すると候補が表示される。

  • Google Mapsのように、ドラッグで地図の表示範囲をスクロールしたり、縮尺を変えたりできる。

  • SNSなどでいいねボタンを押すと色が付く

もっとたくさんありますがこのような機能を画面遷移することなく使えるようになり、ユーザーにとって使いやすいサービスを提供してくれ、通信量も削減できるためサーバーへの負担も軽くなります。

いいね機能

今回、作成中のアプリケーションのいいね機能をAjax化したので簡単に流れを残しておこうと思います。

link_toの通信方法

link_toメソッドのデフォルトの通信方法は同期通信です。

オプションにremote: trueを渡してAjaxに対応させます。

# like.html.erb

<%= link_to board_likes_path(board), 
            method: :post,
            id: "like-button-#{board.id}",
            remote: true do %>
  <i class='far fa-star'></i>
<% end %>
# unlike.html.erb

<%= link_to board_likes_path(board),
            method: :delete, 
            id: "like-button-#{board.id}",
            remote: true do %>
  <i class='fas fa-star'></i>
<% end %>

これにより、ブラウザからHTML形式ではなくJS形式でリクエストが送られ、

最終的に出力されるファイルがhtml.erbではなくjs.erbになります。

js.erbファイルを作成

呼び出されるのはapp/views/コントローラ名/アクション名.js.erbです。

いいねの追加と解除の機能を付けたいので

  • likes/create.js.erb

  • likes/destroy.js.erb

の2つを作成しましょう。

# create.js.erb

$("#like-button-<%= @board.id %>").replaceWith("<%= j(render('boards/unlike', board: @board)) %>");
# destroy.js.erb

$("#like-button-<%= @board.id %>").replaceWith("<%= j(render('boards/like', board: @board)) %>");

"#like-button-<%= @board.id %>"の部分はlink_toメソッドで指定したidと紐づいています。

replaceWithは要素を置き換えるjQueryのメソッドで、

$(置換対象).replaceWith(置き換え後の要素)となります。

よくわかりませんよね。

今回のcreate.js.erbで言うと、

$("#like-button-<%= @board.id %>")はidで紐づいているlink_toメソッドで囲った要素、
つまり<i class='far fa-star'></i>の部分(font-awesomeの☆マーク)

レンダリングしている部分 render('boards/unlike', board: @board)、
つまりunlike.html.erbのlink_toメソッドの中の<i class='fas fa-star'></i>(★マーク)

に置き換えている。

つまり、画面遷移なしで☆から★に切り替わる。

というわけです。

コントローラを修正

元々同期通信でいいね機能を実装していたので非同期通信に合うようにコントローラも修正します。

# likes_controller.rb

class LikesController < ApplicationController
  before_action :set_board
  def create
    @bookmark = current_user.likes.create(board_id: params[:board_id])
    # redirect_back fallback_location: boards_url ここを削除
  end

  def destroy
    @bookmark = current_user.likes.find_by(board_id: params[:board_id])
    @bookmark.destroy
    # redirect_back fallback_location: boards_url ここを削除
  end

  private

  def set_board
    @board = Board.find(params[:board_id])
  end
end

いいねした後に元のページに戻るよう、redirect_backしていましたが、これがあるとページ遷移してしまうので削除します。

他にも必要な知識はあるでしょうが僕はこれでいいね機能をAjax化できました。

最後に

RailsガイドやいろんなQiita記事、技術ブログを参考になんとかまとめた、という感じなので間違いや足りてない情報があるかもしれません。 この記事も参考程度に見ていただければと思います。
JavaScriptはprogateで1周しただけで全然わかってないので余裕があるときにもう少し触ってみたいですね。 最後まで見てくださり、ありがとうございました。