複数回答のアンケートのRailsアプリ

前回は

単一回答のアンケートの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

前回と同様にレイアウトや文言など見栄えを洗練する必要がありますが、機能としては完成しました。



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