前回は
単一回答のアンケートのRailsアプリ(←リンク張ってます)
を作ったので、
今回は複数回答版を作ります。
環境
Ruby 3.3.0
Rails 7.1.3.2
モデルを生成します。
rails new sample_check_qa
cd sample_check_qa
bin/rails g scaffold User name
bin/rails g scaffold Question content
bin/rails g scaffold Check content question:belongs_to
bin/rails g scaffold Answer user:belongs_to question:belongs_to
bin/rails g scaffold Choice answer:belongs_to check:belongs_to
bin/rails db:migrate
質問は複数のチェック(ボックス)を持ちます。
# app/models/question.rb
class Question < ApplicationRecord
has_many :checks
end
質問は複数の選択を持ちます。
質問は選択経由で複数のチェックを持ちます。
class Answer < ApplicationRecord
belongs_to :user
belongs_to :question
has_many :choices
has_many :checks, through: :choices
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|
Check.find_or_create_by!(content: content, question: q1)
end
q2 = Question.find_or_create_by(content: "好きな果物は?")
["いちご", "もも", "みかん", "りんご", "ぶどう"].each do |content|
Check.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_check_boxes :check_ids, @question.checks, :id, :content %>
</div>
今回は質問の編集権限を考えていないので質問の編集リンクと削除ボタンを残しています。
製品では回答のテキストフィールドは不要になります。
回答処理を実装します。
保存後のパスを回答から質問に変更します。
choices_rebuildを呼んで選択を再構築します。
# 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
private
def answer_params
params.require(:answer).permit(:user_id, :question_id, check_ids: [])
end
前回と同様にレイアウトや文言など見栄えを洗練する必要がありますが、機能としては完成しました。
▼この記事がいいね!と思ったらブックマークお願いします