単一回答のアンケートのRailsアプリ

Railsアプリで単一回答のアンケートアプリを作ります。
今回はユーザーが回答する箇所を実装してみます。

環境
Ruby 3.3.0
Rails 7.1.3.2

モデルを生成します。


rails new sample_radio_qa
cd sample_radio_qa
bin/rails g scaffold User name
bin/rails g scaffold Question content
bin/rails g scaffold Radio content question:belongs_to
bin/rails g scaffold Answer user:belongs_to question:belongs_to radio:belongs_to
bin/rails db:migrate

質問は複数の項目を持ちます。


# app/models/question.rb
class Question < ApplicationRecord
  has_many :radios
end

初期データを生成します。
今回はログインユーザーの管理、管理者による質問の編集機能は省きます。


# db/seeds.rb
User.find_or_create_by(name: "ユーザー1")
User.find_or_create_by(name: "ユーザー2")
q1 = Question.find_or_create_by(content: "好きな映画のジャンルは?")
["アクション", "コメディー", "ドラマ", "ホラー"].each do |content|
  Radio.find_or_create_by!(content: content, question: q1)
end
q2 = Question.find_or_create_by(content: "好きな果物は?")
["いちご", "もも", "みかん", "りんご", "ぶどう"].each do |content|
  Radio.find_or_create_by!(content: content, question: q2)
end

bin/rails db:seed

最初の質問を開きます。


bin/rails server
open http://localhost:3000/questions/1

質問の下に回答項目をラジオボタンで表示します。


# app/controllers/questions_controller.rb
  def show
    current_user = User.second # TODO: ログインユーザーを取得する。
    @answer = Answer.find_or_initialize_by(user: current_user,  question: @question)
  end

# app/views/questions/show.html.erb
...
<%= render "answers/form", answer: @answer, question: @question %>

# app/views/answers/_form.html.erb
...
  <div>
    <%= form.collection_radio_buttons :radio_id, @question.radios, :id, :content %>
  </div>

今回は質問の編集権限を考えていないので質問の編集リンクと削除ボタンを残しています。
製品では回答のテキストフィールドは不要になります。

回答処理を実装します。
保存後のパスを回答から質問に変更します。


# app/controllers/answers_controller.rb
  def create
    @answer = Answer.new(answer_params)
    @question = @answer.question
    if @answer.save
      redirect_to @question, notice: "Answer was successfully created."
    else
      render "questions/show", status: :unprocessable_entity
    end
  end
  def update
    @question = @answer.question
    if @answer.update(answer_params)
      redirect_to @question, notice: "Answer was successfully updated."
    else
      render "questions/show", status: :unprocessable_entity
    end
  end

レイアウトや文言など見栄えを洗練する必要がありますが、機能としては完成しました。
以下、項目を選択しなかった場合のエラー表示です。

おまけ
テンプレートが受け取るローカル変数をマジックコメントで定義する。
回答項目で改行する。


# app/views/answers/_form.html.erb
<%# locals: (answer:, question:) -%>
...
    <%= form.collection_radio_buttons(:radio_id, question.radios, :id, :content) do |b| %>
      <%= b.label(style: "display: block") { b.radio_button + b.text } %>
    <% end %>



▼この記事がいいね!と思ったらブックマークお願いします
このエントリーをはてなブックマークに追加