質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Chart.js

Chart.jsは、多様なグラフを組み込めるJavaScriptのライブラリ。折れ線グラフや棒グラフ、円グラフ、レーダーチャートなどのグラフの種類が用意されています。HTML5のCanvasを用いて描画され、マークアップも分かりやすく、簡単に編集することが可能です。

Ruby on Rails 6

Ruby on Rails 6は、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

Q&A

解決済

1回答

1683閲覧

DBから非同期通信でデータを取得し、グラフを作成したいです。

2DN

総合スコア5

Chart.js

Chart.jsは、多様なグラフを組み込めるJavaScriptのライブラリ。折れ線グラフや棒グラフ、円グラフ、レーダーチャートなどのグラフの種類が用意されています。HTML5のCanvasを用いて描画され、マークアップも分かりやすく、簡単に編集することが可能です。

Ruby on Rails 6

Ruby on Rails 6は、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

0グッド

0クリップ

投稿2021/01/28 05:59

前提・実現したいこと

成績管理アプリを試験的に作っております。
その上で、検索フォームで取得した内容を元に非同期通信でグラフを作成したいと考えております。
大変拙いコードではございますが、お力添えいただければ幸と存じます。

「インスタンス変数に指定のデータを代入して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/ツールのバージョンなど)

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

自己解決

collectionをmemberに変更し、idをparamsで取得することでリソースを識別できるように変更しました。

routes.rb

1resources :scores do 2 member do 3 get 'search' 4 end 5 end

従って、jsのエンドポイントも下記のように変更しました。

// 省略 const formData = new FormData(document.getElementById("search-form1")); const idForParams = formData.get("keyword") const XHR = new XMLHttpRequest(); XHR.open('GET', `/scores/${idForParams}/search`, true); // 省略

投稿2021/02/05 03:50

2DN

総合スコア5

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問