【Railsでアプリ開発中】プログラミング初心者の勉強ブログ #31
こんにちは。
31日目。RailsのコントローラーからJavaScriptにインスタンス変数を渡す方法について。scriptタグ内に値を渡すために「gon」というGemを使う。
学習内容
【オリジナルアプリ開発「免許学科試験学習アプリ」】
- Gem「gon」を用いたJSへの変数の渡し方。
- 「一問一答機能」に正誤判断を持たせる。
感想
今回も「一問一答機能」やっていきます。
前回(【Rails】モーダルウィンドウを1から理解して実装する【DIVE INTO CODE】)あたりから自分の力ではどーにもこーにもならなくなってしまったので、今回はDICメンターさんの力を借りることに。
どーにもこーにもならなくなってしまった事項は2つ。
- 問題があっていたら「正解」、間違っていたら「不正解」の表記をモーダル上に出す機能。
- 「次の問題に進む」をクリックして、10問連続で問題を画面遷移することなく表示すること。
この2点、解決しなければならない共通の問題があります。
それが冒頭に書いた通り、
「Rails内でのScriptタグ内外へ変数を行き来する方法を理解すること」
です。
jQueryを実装していくにあたり、<script>タグにコーディンングしますが、
Railsコントローラーで生成したインスタンス変数を<script>タグ内で直接使用することができないことを知りました。
「正解」「不正解」を出すにしても、問題を連続で表示するにしても、
変数や値を、<script>タグ内外へ行き来させる必要があります。
今回はとりあえず、controllerで生成したインスタンス変数をscriptタグ内で使用したかったので、
一番簡単な「gon」というGemを使ってみることに。
「gon」の実装
1、「gon」のインストール
Gemfile内に、
gem 'gon'
を記入し、ターミナルで、「bundle install」。
2、設定の追記
app/assets/javascripts/(jsファイル)
<head> <%= include_gon %> </head>
これでコントローラー内で生成したインスタンス変数が使用可能になります。
ただし、必ず頭に「gon」をつけた変数を定義する必要があります。
3、実際にコントローラーに書いたコーディング
今回コントローラーに書いたものが以下になります。
class ItimonIttousController < ApplicationController def index @questions = Question.all #html.erb用 @sample = @questions.sample(5) #html.erb用 gon.questions = @questions #js用 gon.sample = @sample #js用 @count = 0 #html.erb用 gon.count = @count #js用 end end
「@questions」と「@sample」、「@count」はhtml.erb用です。普通にviewに渡したい分です。
「gon.questions」と「gon.sample」、「gon.count」は<script>タグ内使用分です。
こんな感じで二つに分けないとそれぞれで変数を使用できませんでした。
「gon」はあくまでjsでのみ使える変数でした。
4、<script>タグ内のコーディング
前回のモーダルのコーディングもまた少しいじり、
今はこんな感じです。
<script> $(function(){ $('.modal-open2').click(function(){ $('body').append('<div class="modal-overlay2"></div>'); $('.modal-overlay2').fadeIn(); var modal2 = $(this).attr('data-target'); var sample_answer = Boolean($(this).attr('value')); var collect_answer = gon.sample[gon.count].answer if (sample_answer === collect_answer){ $('#con2').append('<div class="seikai">正解!</div>') }else{ $('#con2').append('<div class="seikai">不正解</div>') }; modalResize(); $(modal2).fadeIn(); $(window).on('resize', function(){ modalResize(); }); function modalResize(){ var w = $(window).width(); var h = $(window).height(); var x = (w - $(modal2).outerWidth(true)) / 2; var y = (h - $(modal2).outerHeight(true)) / 4; $(modal2).css({'left': x + 'px','top': y + 'px'}); } }); }); </script>
実際に「gon」を使っている部分が、
var sample_answer = Boolean($(this).attr('value')); #◯ボタンを押したらtrue、×だとfalseが返りそれをsample_answerに格納。 var collect_answer = gon.sample[gon.count].answer #問題の答えをcollect_answerに格納。 if (sample_answer === collect_answer){ $('#con2').append('<div class="seikai">正解!</div>') }else{ $('#con2').append('<div class="seikai">不正解</div>') }; #sample_answerとcollect_answerを比較し、一致していたら「正解!」、不一致で「不正解」を表示。
ここです。
var collect_answer = gon.sample[gon.count].answer
「gon.sample[]」という問題が入った配列に、に「gon.count」でインデックス番号を指定し、
問題の答えのみを「collect_anser」という変数に格納してます。
ちゃんと機能してます。
問題があっていたら「正解」、間違っていたら「不正解」の表記をモーダル上に出す機能。
こっちはクリアです。
「次の問題に進む」をクリックして、10問連続で問題を画面遷移することなく表示すること。
次回はこっちをやっていきたいと思います。
多分AjaxやらJson形式やらを勉強します。
今回のは正直どちらかというと強引というか。
今やっていることはフロントエンドの延長線上の部分であり、
「railsコントローラーによって生成された、一枚のHTMLをどう表示するか」
をゴリゴリ進めていっている感じだと思います。
非同期通信ではなく、全く通信をしていない状況です。
すでに生成されたもののみを使って、表示の仕方にアレンジを加えているだけです。
今回くらいの実装であったらこれで通るのかもしれませんが、
今後より複雑な実装をする場合、Ajaxでの非同期通信はやっぱ勉強するしかないなと。
以上ありがとうございました。