5
8

More than 3 years have passed since last update.

Railsでajaxを実装する。基本の構造から、controller・jbuilderの書き方など。[Rails]

Last updated at Posted at 2020-01-27

前提

Railsでajaxの復習をする機会ができたので、忘れないように手順をメモします。
こんな感じの、作品一覧ページ(work#index)から、各作品(work#show)の情報を非同期通信で読み込んで、モーダルウィンドウに表示します。(今回の記事にはモーダルウィンドウの実装は含んでいません)
Image from Gyazo

「カテゴリー:」の記述がおかしなことになっていますが、、、次回直します。

基本の構造

今回作成したajaxの構造はこのような形です。

work_show.js
$('.work__img').on('click', function(e){
    e.preventDefault();
    var $workId = $(this).data('id');

    $.ajax({
      type: 'GET', // HTTPメソッド
      url: '/works/' + $workId, // type(GET)でアクセスしたいURL
      data: { id: $workId }, // urlに送りたいデータ
      dataType: 'json'  //データの型, textなどもある
      })
      .done(function (data) {
        // 成功した時の処理
      })
      .fail(function (){
        // 失敗した時の処理
      });
  });

画像(.work__imgというクラスが付与してある)をクリックすると、イベントが発火します。
そのままだと、次の画面(work#showで表示される画面)に画面が遷移してしまうので、e.preventDefault();デフォルトのアクション(画面の遷移)を止めます。

上記のコードでは、GET/works/:idを訪問することで、work#showアクションを表現しているのですが、各作品(work)のidは、作品一覧ページ(work#index)のどこにも出てきません。

カスタムデータ属性

そこで、カスタムデータ属性を利用して、ビューにwork.idを埋め込み、jQuery(今回はwork_show.js)で作品のidを扱えるようにします。

▼そのコードがこちら

views/works/index.html.haml
= image_tag work.images[0].url, class: "works__img", data: {id: work.id }

このコードをHTMLで書くとこうなります。

<img src="#" class="works__img" data-id="3">

この、data-id="3"の部分がカスタムデータ属性で、こうすることで、JSでは$('img').data('id');などの形で作品のIDが利用できます。

▼カスタムデータ属性についてはこちらの解説が丁寧で役立ちました
jQueryのdata()で属性を取得・設定・変更する方法まとめ!

▼hamlでの書き方に関してはこちら
haml に HTML5 のカスタムデータ属性(data-*) を定義する方法

コントローラーの編集

そして、今回は通常の場合(HTML)と非同期通信(ajax)でコントローラーの処理を分けるので、コントローラーに情報を追記しました。

works_controller.rb
def show
    @work = Work.find(params[:id])
    respond_to do |format|
      format.html
      format.json
    end
end

上記の例だと、work/showアクションが呼ばれた時、何も処理を書かないとデフォルトのHTMLのフォーマットが、json形式で呼ばれた場合には、jsonのフォーマットが呼ばれます。

この時の、json形式のフォーマットはjbuilderで定義します。この辺りは理解が曖昧なのですが、フォーマットはviewみたいなもの?と考えれば良いようで、今回のwork#showのフォーマットの場合は、views/worksの中に、show.json.jbuilderというファイルを作成し、jsonの値を定義します。

▼この辺りの文も参照しました
respond_toを初心者向けに完全分解

jbuilderの記述

jsonデータはjbuilderで作成しました。

views/works/show.json.jbuilder
json.id  @work.id
json.name  @work.name
 ...
json.language @work.language
json.softwear @work.softwear
json.description @work.description

この辺りはもう少しスマートな書き方がありそうで、近々リファクタリングしてみたいですが、上記の形でjson形式のデータが作成できます。

▼この記事が丁寧に解説してくれていたので、あとで見直してみます
Railsのjbuilderの書き方と便利なイディオムやメソッド

viewへの反映(完成したviewとjQueryのコード)

views/works/index.html.haml
.row.d-flex.justify-content-center
  %main.works#works
    - @works.each do |work|
      = link_to work_path(work.id), class: 'works__frame' do
        = image_tag work.images[0].url, class: "works__img", data: {id: work.id }

#modal-outer.modal-outer
  .modal-window
    #modal
work_show.js
$(document).on('turbolinks:load', function(){
  function buildHtml(data){
    var workContainer = `<main class="work row">
    ~ 中略 ~
    <h3 class="work__info__title">${data.name}</h3>
    ~ 中略 作品画像や説明など色々な要素をここで記述しています~
    </main>`;
    return workContainer;
  };

  $workImg.on('click', function(e){
    var $workId = $(this).data('id'); //カスタムデータ属性”data-id”の値を取得
    e.preventDefault(); //画面の遷移を止める
    $.ajax({
      type: 'GET',
      url: '/works/' + $workId, // アクションを投げるURL
      data: { id: $workId },
      dataType: 'json'  //json形式指定
      })
      .done(function (data) {
        var showWork = buildHtml(data); // buildHtml関数を呼び出す
        $modal.empty(); // #modal の中身は一度空に
        $modal.append(showWork); // #modalの中にビルドしたHTMLを入れる
      })
      .fail(function (){
        console.log("失敗しました");
      });
  });
});

以上、スクールでは散々苦労したajaxですが、なんとか自力で実装できるようになりました。次は「いいね!」機能もつけてpostメソッドで試したいです。

▼全体的にこの記事を参考にさせていただきました。
【Railsで非同期通信】RailsでAjaxを利用する時にjQueryを使う方法

▼その後、全く別の形ですが、Ajaxのいいね!機能も作ったので紹介します
RailsでAjaxで「いいね!」機能を実装する。

5
8
1

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
8