RubyOnRailsでAjaxの実装

また備忘録的に書いていこうかなと。

 

今回はAjaxの実装について。

まずAjaxとはなんぞやと。

 

Ajax(Asynchronous JavaScript + XML)とは

ウェブブラウザ内で非同期通信を行いながらインターフェイスの構築を行うプログラミング手法である[4]XMLHttpRequestHTTP通信を行うためのJavaScript組み込みクラス)による非同期通信を利用し、通信結果に応じてダイナミックHTML (DHTML) で動的にページの一部を書き換えるというアプローチを取る[5]

(引用:https://ja.wikipedia.org/wiki/Ajax)

 

やっぱり文章にするとわかりづらいよね。

自分が調べていてイメージしやすいなと思ったのはグーグルマップかな。

ドラッグすると現在表示されている画面から、滑らかにスライドするように地図表示情報が見えてくると思ういます。

これが昔はドラッグして違う画面を見ようと思ったら、その度にページ読み込みをしていたので滑らかに見ることができなかったのです。

(自分はギリギリそんな過去があったなと思えるんだけど、知らない世代は知らないかも・・)

 

やっぱり使用感として使い心地が全然違うよねって話

 

今回はRailsでどうやって実装していくかについて簡単にまとめようかと思うよ。

ちなみに今回はツイートに対してコメントをした場合に、コメントが非同期通信で表示されるという機能をテーマに書いていきます。

 

1.まずはGemを導入。Gemfileに書いたら忘れずにbundle installを。

Gemfile

  ///
 (中略)
 
 
 (中略)
///
 

 

 

2.フォームが送信されたらイベントが発火するようにする

javascripts階層にcomment.jsを作成して、下記の通りコードを記載。

この時、フォームにID名(もしくはクラス名)をつけ忘れないように

app/assets/javascripts/comment.js

$(function(){
  $('#new_comment').on('submit', function(e){
    e.preventDefault();
    var formData = new FormData(this);
  })
})

 

3.非同期通信でコメントが保存されるようにする

上記コードに非同期通信をする上での詳しいオプションを書いていきます。

フォームの送信が行われた場合にcreateアクションを動かします。

この時のdata形式ではjsonを指定しています。

app/assets/javascripts/comment.js

$(function(){
  $('#new_comment').on('submit', function(e){
    e.preventDefault();
    var formData = new FormData(this);
    var url = $(this).attr('action')
    $.ajax({
      url: url,
      type: "POST",
      data: formData,
      dataType: 'json',
      processData: false,
      contentType: false
    })
  })

 

 

4.コメントを保存し、respond_toを使ってHTMLとJSONの場合で処理を分ける

responto_to do を使用し、リクエストされたformatによって処理を分けるようにしています。

フォーマットがjsonの場合、jbuilderを使ってJavaScriptに返すデータを作成します。

app/controllers/comments_controller.rb

class CommentsController < ApplicationController
 def create
   @comment = Comment.create(text: comment_params[:text], tweet_id: comment_params[:tweet_id], user_id: current_user.id)
   respond_to do |format|
format.html { redirect_to tweet_path(params[:tweet_id]) }
format.json
end
end

private
def comment_params
params.permit(:text , :tweet_id)
end
end

 

 

5.jbuilderを使用して、作成したメッセージをJSON形式で返す

jbuilderでは、[j.son.KEY VAKUE] という形で書くことができます。

こうすることにより、JavaScriptファイルに帰ってきたデータをjbuilderで定義したキーとバリューの形で呼び出して使うことができます。

app/views/comments/create.json.jbuilder

json.text @comment.text
json.user_id @comment.user.id
json.user_name @comment.user.nickname

 

 

6.帰ってきたJSONをdoneメソッドで受け取り、HTMLを作成する

function buildHTMLではHTMLを追加しています。

.done以降では非同期通信に成功した時の記述をしています。function(data)となっていますが、非同期通信に成功した時の第一引数にはサーバから返されたデータが入っています。

この場合ではcreate.json.jbuilderのデータです。

app/assets/javascripts/comment.js

$(function(){
 function buildHTML(comment){
   var html = `<p>
            <strong>
              <a href=/users/${comment.user_id}>${comment.user_name}</a>
              :
            </strong>
             ${comment.text}
          </p>`
    return html;
}
 
$('#new_comment').on('submit', function(e){
   e.preventDefault();
  var formData = new FormData(this);
  var href = window.location.href + '/comments'
   $.ajax({
     url: href,
     type: "POST",
     data: formData,
     dataType: 'json',
     processData: false,
     contentType: false
  })
 
   .done(function(data){
    var html = buildHTML(data);
    $('.comments').append(html)
    $('.textbox').val('')
    })
  })
});

 

7.エラー時の処理を行う

通信に失敗した場合、アラートを出します。

 

app/assets/javascripts/comment.js

(省略)
.done(function(data){
var html = buildHTML(data);
$('.comments').append(html)
$('.textbox').val('')

.fail(function(){
alert('error');
})
(省略)

 

大まかな流れはこんなところかな。