前提・実現したいこと
成績管理アプリを試験的に作っております。
その上で、検索フォームで取得した内容を元に非同期通信でグラフを作成したいと考えております。
大変拙いコードではございますが、お力添えいただければ幸と存じます。
「インスタンス変数に指定のデータを代入してjsに渡したい。」
これが一番実現したいことです。
処理の流れ
①フォームにkeywordを入力。
②検索ボタンクリック。
③jsでscoreアクションへリクエスト。
④keywordを元にDBを検索。
⑤DBから取得したデータをインスタンス変数@scoreに代入。
⑥@scoreをjsに返却。
⑦返却されたデータを元にグラフを描画。
該当のテーブルとカラム
テーブル名:scores
カラム:name、jpn、math、science、social、english
バリデーション:無し
環境
macOS BigSur
rails 6
ruby 2.6.5
chart.js
発生している問題・エラーメッセージ
エラーは特に発生しておりませんが、検索した際のkeywordが正しくコントローラー側へ送られていないようです。それによって正しく検索されず、DB上の全てのデータが@scoresインスタンスに代入されてしまいます。
該当のソースコード
下記はルーティングです。
routes.rb
1resources :scores do 2 collection do 3 get 'search' 4 end 5 end
下記が該当のHTMLです。form_withで取得したkeywordをコントローラへ送信します。
jsで作成したグラフをここで描画します。
test.html.erb
1<div> 2 <%= form_with(url: search_scores_path, method: :get, id: "search-form") do |form| %> 3 <%= form.text_field :keyword %> 4 <%= form.submit "検索", id: "submit-btn" %> 5 <% end %> 6</div> 7<canvas id="myBarChart" width="800" height="400"></canvas>
下記はscoresコントローラのsearchアクションです。
こちらでkeywordを受け取り、SearchScoresServiceモデルのsearchアクションの引数に渡します。検索をかけた後、@scoreに代入し、JavaScriptに返却します。
scores_controller
1def test 2end 3 4def search 5 respond_to do |format| 6 @score = SearchScoresService.search(params[:keyword]) 7 format.json { 8 render json: {score: @score} 9 } 10 end 11end
下記が検索をしてくれるメソッドです。name(受験したテスト名です。)が完全一致した場合に戻り値を返します。
search_scores_serrvice.rb
1class SearchScoresService 2 def self.search(search) 3 Score.where('name LIKE(?)', "%#{search}%") 4 end 5end
下記はコントローラへリクエストを送り、レスポンスを受け取るためのJavaScriptです。
レスポンスされたデータを元に、グラフを作成します。
find
1function findScore(){ 2 const submitBtn = document.getElementById("submit-btn"); 3 submitBtn.addEventListener("click", function(e){ 4 5 const formData = new FormData(document.getElementById("search-form")); 6 const XHR = new XMLHttpRequest(); 7 XHR.open('GET', '/scores/search.json', true); 8 XHR.responseType = "json"; 9 XHR.send(formData); 10 11 XHR.onload = function() { 12 const score = XHR.response.score 13 // 確認用 14 // console.log(score) 15 const jpn = score[0].jpn 16 const math = score[0].math 17 const science = score[0].science 18 const social = score[0].social 19 const english = score[0].english 20 21 const ctx = document.getElementById("myBarChart"); 22 const myBarChart = new Chart(ctx, { 23 type: 'bar', 24 data: { 25 labels: ["国語", "数学", "理科", "社会", "英語"], 26 datasets: [{ 27 label: "成績", 28 backgroundColor: ["#ff7f7f", "#80b3ff", "#80ffb3", "#e6ff80", "#e680ff"], 29 data: [jpn, math, science, social, english] 30 }] 31 }, 32 options: { 33 scales: { 34 yAxes: [{ 35 ticks: { 36 beginAtZero: true, 37 } 38 }] 39 } 40 } 41 }); 42 }; 43 e.preventDefault(); 44 }); 45}; 46 47window.addEventListener("load", findScore);
試したこと
①binding.pryでコントローラへ値が送られているかを確認してみました。
pry(#<ScoresController>)> params[:keyword] #=>nil
全く送られていません。
[1] pry(#<ScoresController>)> @score = SearchScoresService.search(params[:keyword]) Score Load (1.1ms) SELECT `scores`.* FROM `scores` WHERE (name LIKE('%%')) ↳ app/controllers/scores_controller.rb:19:in `search' => [#<Score:0x00007ffaf17d7b18 id: 96, name: "テスト1", jpn: "90", math: "90", science: "90", social: "90", english: "90", text: "wow", created_at: Wed, 27 Jan 2021 12:16:27 UTC +00:00, updated_at: Wed, 27 Jan 2021 12:16:27 UTC +00:00, user_id: 2>, #<Score:0x00007ffaf3246da0 id: 97, name: "テスト2", jpn: "50", math: "60", science: "70", social: "80", english: "90", text: "", created_at: Wed, 27 Jan 2021 13:27:31 UTC +00:00, updated_at: Wed, 27 Jan 2021 13:27:31 UTC +00:00, user_id: 2>, #<Score:0x00007ffaf3246cd8 id: 98, name: "I am Mike", jpn: "50", math: "50", science: "50", social: "50", english: "50", text: "My name is Mike", created_at: Wed, 27 Jan 2021 23:54:29 UTC +00:00, updated_at: Wed, 27 Jan 2021 23:54:29 UTC +00:00, user_id: 2>]
検索したkeywordに完全一致したデータだけが欲しいのですが、全てが代入されてしまっています。
②form_withに「remote: true」を追加してみました。
調べるとform_withはデフォルトがremote: trueなので、特に記述する必要はなかったようです。処理に変化はありませんでした。
③リクエスト時にjsから送るFormDataのインスタンス?の中身を確認してみました。
console.log(...formData.entries());
上記で中身を確認すると
XHR.send(formData[0]); または XHR.send(formData[1]);
と、してみましたがこれもまた特に影響はありませんでした。エラーすら出てくださいませんでした。
以上になります。
ご不明な点、ご指摘等ございましたら、お気軽にお尋ねください。
大変稚拙な質問内容ではございますが、どうかよろしくお願い致します。
補足情報(FW/ツールのバージョンなど)
回答1件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。