前提
Railsでajaxの復習をする機会ができたので、忘れないように手順をメモします。
こんな感じの、作品一覧ページ(work#index)から、各作品(work#show)の情報を非同期通信で読み込んで、モーダルウィンドウに表示します。(今回の記事にはモーダルウィンドウの実装は含んでいません)
「カテゴリー:」の記述がおかしなことになっていますが、、、次回直します。
基本の構造
今回作成したajaxの構造はこのような形です。
$('.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を扱えるようにします。
▼そのコードがこちら
= 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)でコントローラーの処理を分けるので、コントローラーに情報を追記しました。
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で作成しました。
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のコード)
.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
$(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で「いいね!」機能を実装する。