LoginSignup
5
2

More than 5 years have passed since last update.

RailsとAjax(たぶんこれが一番単純だとry

Last updated at Posted at 2019-03-19

TL;DR(使いたかっただけ)

Railsで非同期処理を実装するための、Ajax(AsynchronousJAvascript+Xml)対応。
それを超絶シンプルな形で実装/解説してみようと思う。

今回最終的に実装したいのは超簡単ないいねボタン。
(非同期の意味がないとは言わない。まあツイッターの「いいね」も非同期だし…)
Portfolio_—___Rails_portfolio.png
ボタンを押すと
Portfolio_—___Rails_portfolio-2.png
黒くなる。
また押したら白くなる、というボタンを作ります。

早速!

今回のファイル構成

app/
    controllers/
        study_controller.rb

    views/
        study/
            _dislike.html.erb
            _like.html.erb
            ajax.html.erb
            dislike.js.erb
            like.js.erb

config/
    routes.rb

正直今回の機能でルーティングを設定する意味はあまりないんだけど、
俺みたいにprogateで学んでいざやってみたらハマったみたいな人のためにあえてroutes.rbを介してやっていこうと思う。

基本的なHTML、Routes、Controller

ajax.html.erb
<h1>いいねボタン</h1>
<h1><div id="likeBtn"><%= link_to "◯", "/study/like" , remote: true %></div></h1>

Ajax対応させるためには、link_toメソッドにremote: trueを追記するだけで良い。
これだけで「非同期処理」自体は実装できるから、このリンクを押した場合は画面の更新がされない。

routes.rb
Rails.application.routes.draw do
  #TopPage
  root "study#ajax"

  #For Ajax
  get "study/like" => "study#like"
  get "study/dislike" => "study#dislike"
end

まずトップページとしてajax.html.erbにリンクさせておく。

link_toメソッドの"/study/like"study_controller.rblikeアクションにリンクを飛ばすように設定する。
dislikeは後述。

study_controller.rb
class StudyController < ApplicationController
  #TopPage
  def ajax
  end

  #For Ajax
  def like
  end
  def dislike
  end
end

今回は超絶単純なAjaxによる非同期処理を実装/解説するため、無駄な処理はすべて不要!

Ajax機能特有の部分

ここからが本題のAjax機能となるから、詳しく理解していきたい。

まず処理のイメージについて。
Portfolio_—___Rails_portfolio.png
この白い丸のボタン(リンク)を押したら
ajax.html.erb<%= link_to "◯", "/study/like" , remote: true %>が実行される。

/study/likeに飛ぶとroutes.rbの通り
study_controller.rblikeアクションを実行する。

routes.rb
  get "study/like" => "study#like"
study_controller.rb
  def like
  end

非同期処理でなければ(remote: trueがなければ)、通常通りlike.html.erbが呼び出されるのだが、今回はそうしない。というかlike.html.erbがないから呼び出されるものがない。

railsのAjax機能は、呼び出されたactionと同名のJavaScriptを実行する。

よって、ここで呼び出されるのはcontrollerでもhtmlでもなく、以下のファイルとなる。
(もちろん、controllerに処理があればそれも呼び出される)

like.js.erb
$('#likeBtn').html(
  "<%= escape_javascript(render'like') %>"
);

具体的な処理については(いくらでもサンプルがあるので)割愛するが、ここではid="likeBtn"のグループをrenderで再レンダリングしている。

render'like'で呼び出されるのはメソッドの引数であるlikeと同名のhtmlだが、renderメソッドの場合はそのhtml名の頭に_(アンダースコア)をつけたものになる。

それが以下のファイルである。

_like.html.erb
<%= link_to "●", "/study/dislike" , remote: true %>

renderメソッドにより、_like.html.erbが呼び出され、ajax.html.erb(トップページ)の<div id="likeBtn">の中身が_like.html.erbに書き換えられる。

この状態でとりあえずトップページにアクセスして、白いボタンを押してみると……
Portfolio_—___Rails_portfolio-2.png
黒くなった!

このとき、ajax.html.erbは裏で以下のようになっている。

ajax.html.erb
<h1>いいねボタン</h1>
<h1><div id="likeBtn"><%= link_to "●", "/study/dislike" , remote: true %></div></h1>

黒を白に戻す(前項と同じやり方)

ここまでくれば後は同じ手順で黒いボタンを押したときに白くするようにすればいい。

_like.html.erb
<%= link_to "●", "/study/dislike" , remote: true %>

画面の黒いボタンを押すと_like.html.erbの通りroutes.rb/study/dislikeを見に行く。

routes.rb
Rails.application.routes.draw do
  #TopPage
  root "study#ajax"

  #For Ajax
  get "study/like" => "study#like"
  get "study/dislike" => "study#dislike"
end

そしてアクションdislikeと同名のJavaScriptのdislike.js.erbを実行する。

dislike.js.erb
$('#likeBtn').html(
  "<%= escape_javascript(render'dislike') %>"
);

renderメソッドにて_dislike.html.erbajax.html.erb(トップページ)のlikeBtnグループにレンダリングする。

_dislike.html.erb
<%= link_to "", "/study/like" , remote: true %>

これで黒いボタンを押してみると、白に戻ったはずだ。
その上、白のボタンをもう一度押してみると黒くなるし、黒のボタンを押してみると(ry

これにて、たぶんこれが一番単純だと思うAjax機能を用いた実装ができたかなと思います。

まとめ

個人的に最もハマったポイント

railsのAjax機能は、呼び出されたactionと同名のJavaScriptを実行するところ。
色々調べてたんだけど、どれもroutes.rbを仲介しない書き方を使っていてよくわからなかった。
まあ正直今回みたいにcontrollerを介する必要がない(処理がない)場合は、たとえば以下のようにも書くことができる。(というか書いた方がベスト)

ajax.html.erb
<h1>いいねボタン</h1>
<h1><div id="likeBtn"><%= link_to "●", {action: :dislike} , remote: true %></div></h1>
_like.html.erb
<%= link_to "●", {action: :dislike} , remote: true %>
_dislike.html.erb
<%= link_to "◯", {action: :like} , remote: true %>

注意点としては、これだけだと実行されるJavaScriptファイルは上記3ファイルと同じディレクトリにないといけない。
今回の例で言えば/views/study/like.js.erbみたいに。

逆にroutes.rbstudy_controller.rb以外のコントローラーを指定した場合は、その別のコントローラーに対応するディレクトリにJavaScriptファイルを置いてあげる必要がある。

俺はここでめちゃくちゃハマって、時間を無限に溶かしてしまった。

感想

初めてWeb系の技術で書いてみたけど、案の定Too Longになってしまった。(楽しかった)
非同期処理を実装してみたいけどなにもわからない!っていう人がこれをみて、理解の一助になれればと思いました。

以上、ここまで読んでくれてありがとうございました!さらば!

5
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
2