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

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

新規登録して質問してみよう
ただいま回答率
85.46%
Ruby on Rails

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

データベース

データベースとは、データの集合体を指します。また、そのデータの集合体の共用を可能にするシステムの意味を含めます

Q&A

1回答

916閲覧

railsでDB内のキーワードとビューに入力した文字列の照合について

ro-ze1106

総合スコア4

Ruby on Rails

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

データベース

データベースとは、データの集合体を指します。また、そのデータの集合体の共用を可能にするシステムの意味を含めます

0グッド

0クリップ

投稿2021/11/16 09:58

編集2021/12/05 08:43

現在クイズ系のアプリを制作しています。
そこで、このような流れで考えています。
・クイズの問題や答えをDBに保存する
・DB情報をビューに取得する。ただし答えはテキストエリアにする
・入力したテキストエリアの答えとDB内の答えの情報を照合する
・答えが一致した場合と不一致した場合のフラッシュメッセージを出す
大雑把ですが、このように出来ればと思っています。

自分でも調べましたが、「入力したテキストエリアの答えとDB内の答えの情報を照合する」と言う部分がどうしてもヒットしません。
そもそもビュー内のテキストエリアにテキストを入力してDB内の情報と照合できるのかが分からないのでご教示して頂きたいです。
初めてアプリを制作いているので、行き詰まっています。
もし、他のやり方で似たような事ができるのであれば、そちらの方もご教示して頂けたら幸いです。
どうかお力を貸してください。

補足データ
rails 6.14
ruby 3.0.2
macOS 11.6

追記コード

ruby.controller def update @question = Problem.find(params[:id]) if @question.answer == params[:problem][:answer] flash[:notice] = "大正解" else flash[:notice] = "はずれ" end render :show end
ruby.show.html <% provide(:title, "問題出題") %> <div class="container"> <div class="row"> <%= form_with model: @question, url: {contller: 'question', action: 'update'} do |f| %> <h1>問題</h1> <ul class="problems"> <%= @problems.html_safe %> </ul> <div class="ans"> <h2>答え</h2> < %= f.text_field :answer%> </div> <%= f.submit "回答", class: "btn btn-primary" %> <% end %> </div> </div>
routes get '/question', to: 'question#show' patch '/question', to: 'question#update'

ログ
question GET /question(.:format) question#show
PATCH /question(.:format)  question#update

再追記コード

ruby.controller def show @problems = Problem.offset( rand(Problem.count)).limit(1).pluck(:study_type, :explanation_text, :problem_text).join("<br>") end

変更したコード

rubycontroller

1 2class QuestionController < ApplicationController 3 before_action :logged_in_user 4 5 def show  6 @question = Problem.find_by(params[:id])⇦追加しました 7 @problems = Problem.offset(rand(Problem.count)).limit(1).pluck(:study_type, :explanation_text, :problem_text).first  ⇦ここが変わっています 8 end 9 10 def update                                   ↓ここが変わっています 11 @question = Problem.find_by(params[:id]) 12 13 if @question.answer == params[:problem][:answer] 14 flash[:notice] = "大正解" 15 else 16 flash[:notice] = "はずれ" 17 end 18 19 render :show 20 end 21end

rubyview

1<% provide(:title, "問題出題") %> 2<div class="container"> 3 <div class="row"> 4 <%= form_with model: @question, url: {contller: 'question', action: 'update'} do |f| %> 5 <h1>問題</h1> 6 <ul class="problems"> 7ここが変わっています⇨ 教科:<%= raw(@problems.map{|i| h(i)}.join("<br><br>")) %> </ul> 8 <div class="ans"> 9 <h2>答え</h2> 10 <%= f.text_field :answer%> 11 </div> 12 <%= f.submit "回答", class: "btn btn-primary" %> 13 <% end %> 14 </div> 15</div> 16

追記コード3

problemscontroller

1class ProblemsController < ApplicationController 2 before_action :logged_in_user 3 before_action :correct_user, only: %i[edit update] 4 5 def show 6 @problem = Problem.find(params[:id]) 7 end 8 9 def new 10 @problem = Problem.new 11 end 12 13 def create 14 @problem = current_user.problems.build(problem_params) 15 @problem.picture.attach(params[:problem][:picture]) 16 if @problem.save 17 flash[:success] = '問題が作成されました!' 18 redirect_to problem_path(@problem) 19 else 20 render 'problems/new' 21 end 22 end 23 24 def edit 25 @problem = Problem.find(params[:id]) 26 end 27 28 def update 29 @problem = Problem.find(params[:id]) 30 if @problem.update(problem_params) 31 flash[:succcess] = '問題情報が更新されました!' 32 redirect_to @problem 33 else 34 render 'edit' 35 end 36 end 37 38 def destroy 39 @problem = Problem.find(params[:id]) 40 if current_user.admin? || current_user?(@problem.user) 41 @problem.destroy 42 flash[:success] = '問題が削除されました' 43 redirect_to request.referer == user_url(@problem.user) ? user_url(@problem.user) : root_url 44 else 45 flash[:danger] = '別アカウントの問題は削除できません' 46 redirect_to root_url 47 end 48 49 def rand 50 @problem = Problem.order("RAND()").take 51 end 52 end 53 54 private 55 56 def problem_params 57 params.require(:problem).permit(:study_type, :title, :explanation_text, :problem_text, :answer, :problem_explanation, :taget_age, :reference, :picture) 58 end 59 60 def correct_user 61 # 現在のユーザーが更新対象の問題を保有しているかどうか確認 62 @problem = current_user.problems.find_by(id: params[:id]) 63 redirect_to root_url if @problem.nil? 64 end 65end

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

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

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

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

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

guest

回答1

0

単純に文字列を比較したいのであれば == で比較できます。

  • PATCH /quizzes/:id で答え合わせをする(フォームの送信先)
  • quiz の answer に答えが文字列で入っている
  • 送信されてくる回答は params[:quiz][:answer] に入っている

上記のような状態のときは以下のようなコードになります。

ruby

1def update 2 @quiz = Quiz.find(params[:id]) 3 4 if @quiz.answer == params[:quiz][:answer] 5 flash[:notice] = "大正解" 6 else 7 flash[:notice] = "はずれ" 8 end 9 10 render :show 11end

ただし、 == での比較は完全に一致しないと false になるので、
答えを平仮名で用意し回答も平仮名で入力させる、事前に空白を取り除くなどの処理が必要になるでしょう。

ruby

1"三毛猫" == "ミケ猫" # => false 2"三毛猫" == " 三毛猫 " # => false 3"三毛猫" == "三毛" # => false

投稿2021/11/16 20:52

neko_daisuki

総合スコア2090

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

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

ro-ze1106

2021/11/20 09:55

ご回答ありがとうございます。 こちらを参考に制作します。
ro-ze1106

2021/11/28 06:50

かなり時間が経ってしまいましたが、質問してもよろしいでしょうか?
ro-ze1106

2021/11/28 10:28

ありがとうございます。 こちらのコードを参考に制作している途中で、Routing Errorでハマっています。 内容としましてNo route matches [POST] "/question"のエラー内容になります。 関連すると思うコードとログを載せるので見てください。
neko_daisuki

2021/11/28 11:16

def show も追記してください
ro-ze1106

2021/11/28 11:37

追記しました。
neko_daisuki

2021/11/28 11:53

@question はどうなっていますか? form_with は model に指定した値が保存済みか未保存かで POST か PATCH か変わります。
ro-ze1106

2021/11/28 12:27

このやり方が合ってるか分かりませんが、saved_changes?で確認して見た所、falseだったので未保存だと思います。 未保存だとPOSTなると言う事ですか?
neko_daisuki

2021/11/28 12:39

未保存だとPOSTになるはずです。 ただ、一般的なルーティングとは異なっているのと、 url を指定しているので、断言はできません。 明日時間があれば試してみます。 保存済みかどうかは persisted? で確認してみてください。
ro-ze1106

2021/11/28 13:42

よろしくお願いします。 先程モデル.persisted? をコンソールで確認してみましたが、undefined method `persisted? のエラー出て確認が取れません。
neko_daisuki

2021/11/28 22:03

メソッドは model の状態で決まる。 パスは model_path で決まる。url の指定がある場合そちらが優先される。 なので model の状態と、パスの指定に食い違いがあった場合は No route matches になります。
neko_daisuki

2021/11/28 22:05

Question.new.persisted? # => false <%= form_with model: Question.new %> この method は POST Question.find(1).persisted? # => true <%= form_with model: Question.find(1) %> この method は PATCH
neko_daisuki

2021/11/28 22:12

persisted? が undefined method になる理由は どのように確認したのか分からないので分かりません。 def show に @question がないので、before_action でセットしているのかと思いましたが、 もし何もしていないなら <%= form_with model: nil %> ということになり、 この method は POST でパスはそのままになるみたいです。
ro-ze1106

2021/11/29 02:10

細かく説明して頂きありがとうございます。 今はquestionコントローラー内にproblemモデルのデータが入っていない、もしくは繋がっていないという状態で合っていますか?
neko_daisuki

2021/11/29 03:26

いえ、合っていません。 問題になっているのは @question で problem は今はルーティングに関係ありません。
neko_daisuki

2021/11/29 03:33

繋がりというのがリレーションのことならば、以下のコードはランダムに Problem を取得しているので Question とは繋がりはありません(ただしそれが原因でエラーになっているわけではない)。 @problems = Problem.offset( rand(Problem.count)).limit(1).pluck(:study_type, :explanation_text, :problem_text).join("<br>")
ro-ze1106

2021/11/29 05:30 編集

見当違いですいません。 def show に@questionを入れたら、とりあえずRouting Errorは抜けましたが、undefined method `map' for nil:NilClassのメソッドエラーが出ました。 XSS対策で先程、少しコードを変えてしまったので、もしかするとそれが原因になっているかもしれません。 変更コードを載せるので見てください。
neko_daisuki

2021/11/29 07:23

@problems が nil になっていませんか?
ro-ze1106

2021/11/30 09:51

仰る通りだったので、questionコントローラーのupdateに @problems = Problem.offset(rand(Problem.count)).limit(1).pluck(:study_type, :explanation_text, :problem_text).first を書いた所、エラーは解消されました。 しかし、viewの答えのtext_fieldの中に2が常に表示されるバグ?みたいなものが発生しました。 こちらは、<div class="ans"> <h2>答え</h2> <%= f.text_field :answer%> のコードが原因でしょうか?
neko_daisuki

2021/11/30 09:57

@question の answer に 2 が保存されているのでは。
neko_daisuki

2021/11/30 10:06

正解が answer、ユーザーが入力する値も answer なので問題が起きてます。 とりあえずユーザーが入力する値を response にするとか・・・
neko_daisuki

2021/11/30 10:10

もしくは、以下のように value を指定して空にするとかでしょうか <%= f.text_field :answer, value: ""%>
ro-ze1106

2021/12/01 09:42 編集

valueを指定を空にする事で2は消えました。 しかし、2以外を入力すると全てハズレになっていしまいます。
neko_daisuki

2021/12/01 09:44

@question.answer が 2 なのだから、ハズレになるのが正常なのでは?
ro-ze1106

2021/12/01 09:53

すいません質問内容が良くありませんでした。 例えば、answerが3だった場合のレコードが表示されたとします。そこで、3と入力するとハズレになり、2と入力すると正解になります。
neko_daisuki

2021/12/01 09:57

@question = Problem.find_by(params[:id]) としているところが二か所ありますが、 params[:id] の値は確認できますか? 一般的に params[:id] はパスの一部になります。 (/questions/3 なら params[:id] は 3) しかし、ルーティングがそうなっていないので、show のときと update のときの値を確認した方が良いです。 また、パスも確認してください。
ro-ze1106

2021/12/01 10:15

showの時のパスは/questionのみでupdateの時は/question?contller=questionのパスが表示されます。
neko_daisuki

2021/12/01 10:20

いま気づきましたが find_by の使い方が間違ってます。 Problem.find_by(id: params[:id]) のようにカラムの指定が必要です。 たぶん今は Problem.find_by(nil) になってます。 こうすると Problem の最初のひとつをもってきてしまうようです。 Problem.find(params[:id]) としてください。 こうすると存在しない Problem を引数に渡されたときエラーを表示してくれます。
neko_daisuki

2021/12/01 10:24

ルーティングも一般的な形に沿った方が良いと思います。 以下を消して get '/question', to: 'question#show' patch '/question', to: 'question#update' 以下を追加 resources :questions, only: [:show, :update] そうすると次が定義されるはずです(bin/rails routes で確認してください) get /questions/:id questions#show patch /questions/:id questions#update
ro-ze1106

2021/12/02 09:55 編集

表示されるレコードと入力した答えが一致して、正しいフラッシュが表示されるようになりました。 しかし、同じパスで違うレコードが表示されます。 例 questions/1 の時に 1+1= と言う問題文が表示されますが 再読み込みのボタンを押すと 同じquestions/1 なのに 12+6= と言う問題文が出てきます。 それぞれ正しい答えを入力すれば正しいフラッシュが返ってきます。
neko_daisuki

2021/12/02 10:06

@question と @problems がまったく独立しているからじゃないでしょうか。 問題をランダムに取り出したら答えもランダムになり @question の answer と @problems の答えが一致しません。
neko_daisuki

2021/12/02 10:15 編集

Question と Problem が別のモデルになっている理由はあるのでしょうか? Question に必要なカラム(:study_type, :explanation_text, :problem_text)を持たせて 問題をランダムに表示したいのなら Question をランダムに取り出せば良いのでは。 具体的には以下のようなコードになるでしょう。 routes.rb get "/questions/rand", to: "questions#rand" questions_controller.rb def rand @question = Question.order("RAND()").take end rand.html.erb <%= form_with model: @question do |f| %> <%= f.hidden_field :id %> <div><%= @question.study_type %></div> <div><%= @question.explanation_text %></div> <div><%= @question.problem_text %></div> <%= f.text_field :answer, value: "" %> <% end %>
ro-ze1106

2021/12/03 10:10

Problemモデルの方に書いて見た所、上手く行かなかったので別のモデルを作成しました。 Problemモデルに書いた方が良いですか?
neko_daisuki

2021/12/03 10:16

何を書いたのでしょうか?
ro-ze1106

2021/12/04 20:59

def r @problems = Problem.offset( rand(Problem.count)).limit(1).pluck(:study_type, :explanation_text, :problem_text).join("<br>") end と書いて表示させて見た所、 こちらのコードが対象の def show @problem = Problem.find(params[:id]) end Couldn't find Problem with 'id'=rand というrandと言うidはありません?みたいなエラーが出てきました。
neko_daisuki

2021/12/04 21:04

get "/questions/:id", to: "questions#show" の :id の部分に rand がマッチし params[:id] が rand になっています。 Railsのルーティングは、ルーティングファイルの「上からの記載順に」マッチします。 get "/questions/rand", to: "questions#r" を get "/questions/:id", to: "questions#show" より上に書いてください。
ro-ze1106

2021/12/04 21:38

すいません。 先程質問はProbelmモデルの方に書いた物で、Questionモデルに書いたものではありません。 既存のProbelmと新規のQuestion モデルだと、どちらの方が書きやすいですか?
neko_daisuki

2021/12/05 00:09

Problem を取り扱うなら Problemコントローラーに書きます。
ro-ze1106

2021/12/05 01:42

そうですよね。ありがとうございます。 なので、先程書いてもらったコードをProblem仕様に変更しました。 routes.rb get "/problems/rand", to: "problems#rand" problems_controller.rb def rand @problem = Problem.order("RAND()").take end rand.html.erb <%= form_with model: @problem do |f| %> <%= f.hidden_field :id %> <div><%= @problem.study_type %></div> <div><%= @problem.explanation_text %></div> <div><%= @problem.problem_text %></div> <%= f.text_field :answer, value: "" %> <% end %> こちらを表示させた所 undefined method `study_type' for nil:NilClass と言うエラーが出ました。 スペルミスもないと思うのですが、なぜですか?
neko_daisuki

2021/12/05 01:57

@problem が空みたいです。 Problem.count == 0 なんじゃないかと思います。
ro-ze1106

2021/12/05 02:12

コンソールで調べて見た所、countは11件ありました。
neko_daisuki

2021/12/05 02:33

この rand.html.erb は app/views/problems/ にありますか?
ro-ze1106

2021/12/05 02:41

problemsのコントローラーのコードも載せますか?
neko_daisuki

2021/12/05 06:41

Problem にレコードが存在するなら、 Problem.order("RAND()").take が nil になることはないと思います。 コントローラーと、エラーになった時のログを載せてください。
ro-ze1106

2021/12/05 08:40

エラーのログはこちらになります。 Started GET "/problems/rand" for ::1 at 2021-12-05 17:36:02 +0900 (2.2ms) SELECT sqlite_version(*) (0.7ms) SELECT "schema_migrations"."version" FROM "schema_migrations" ORDER BY "schema_migrations"."version" ASC Processing by ProblemsController#rand as HTML User Load (1.3ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT ? [["id", 1], ["LIMIT", 1]] ↳ app/helpers/sessions_helper.rb:16:in `current_user' Rendering layout layouts/application.html.erb Rendering problems/rand.html.erb within layouts/application Rendered problems/rand.html.erb within layouts/application (Duration: 7.6ms | Allocations: 2981) Rendered layout layouts/application.html.erb (Duration: 7.9ms | Allocations: 3075) Completed 500 Internal Server Error in 46ms (ActiveRecord: 1.8ms | Allocations: 14837) ActionView::Template::Error (undefined method `study_type' for nil:NilClass): 1: <%= form_with model: @problem do |f| %> 2: <%= f.hidden_field :id %> 3: <div><%= @problem.study_type %></div> 4: <div><%= @problem.explanation_text %></div> 5: <div><%= @problem.problem_text %></div> 6: <%= f.text_field :answer, value: "" %> app/views/problems/rand.html.erb:3 app/views/problems/rand.html.erb:1 コントローラーは編集して追記コードで載せます。
neko_daisuki

2021/12/05 09:34

def destroy の中に def rand がありますね。 def rand の前に end を追加してください。
ro-ze1106

2021/12/05 10:21

エラーは解消されました。 しかし、再読み込みのボタンを押しても表示されるレコードが変わりません。
neko_daisuki

2021/12/05 11:26

sqlite は RAND() できないのかも 試したらこちらの環境ではエラーが出ました。 なぜエラーが出ないのか謎ですが、RANDOM() としてみてください。
ro-ze1106

2021/12/05 11:36

すいません、RAND()でエラーが出たので、勝手にRANDOM()に変更しました。 そうしたら、再読み込みのボタンを押しても表示されるレコードが変わらない事になりました。
neko_daisuki

2021/12/05 11:42

コンソールで Problem.order("RANDOM()").take を何度か実行しても同じ結果が返ってきますか?
ro-ze1106

2021/12/05 11:48

はい。同じ結果が返ってきます。
neko_daisuki

2021/12/05 12:01

では Problem.offset( rand(Problem.count)).take に変更してみるとか
neko_daisuki

2021/12/05 12:01

ふと思ったのですが、 Question の answer は Problem に移動させたのでしょうか?
ro-ze1106

2021/12/05 12:13

コンソールでは、違う結果が返ってきますが、表示したらエラーが出ました。 エラーのログはこちらです。 Started GET "/problems/rand" for ::1 at 2021-12-05 21:09:59 +0900 Processing by ProblemsController#rand as HTML (0.1ms) SELECT sqlite_version(*) ↳ app/helpers/sessions_helper.rb:16:in `current_user' User Load (0.3ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT ? [["id", 1], ["LIMIT", 1]] ↳ app/helpers/sessions_helper.rb:16:in `current_user' (0.1ms) SELECT COUNT(*) FROM "problems" ↳ app/controllers/problems_controller.rb:61:in `rand' Completed 500 Internal Server Error in 30ms (ActiveRecord: 2.1ms | Allocations: 10931) ArgumentError (wrong number of arguments (given 1, expected 0)): app/controllers/problems_controller.rb:60:in `rand' app/controllers/problems_controller.rb:61:in `rand'
ro-ze1106

2021/12/05 12:21

Question の answer というのは、questions.contollerの def update @question = Problem.find(params[:id]) if @question.answer == params[:problem][:answer] flash[:notice] = "大正解" else flash[:notice] = "はずれ" end render :show end のコードのことですか?
neko_daisuki

2021/12/05 12:27

引数の数が違う(0なのに1渡された)というエラーですが、原因は分かりません。 qustions テーブルの answer カラムです。 problem をランダムに表示しても答えが導け出せないので前と同じになります。
ro-ze1106

2021/12/05 12:56 編集

Problem.offset( rand(Problem.count)).takeにインスタンス変数を書くのを忘れていたので書いてみましたが、変わらずエラーが出ました。 qustions テーブルはありません。 answerカラムは、problems テーブルの中にあります。
ro-ze1106

2021/12/08 01:58 編集

def randを def randomに変更し、それに応じてビューのファイル名やrouteを変更した所、ビューが表示されました。 再読み込みのボタンを押したら、レコードが変わるので問題ないと思います。 しかし、回答ボタンを作成して答えを入力したところ、問題出題のidと答えのidが一致しなくて困っています。 また力を貸してください。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

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

ただいまの回答率
85.46%

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

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

質問する

関連した質問