'Rails 7 How do I allow the user to create a new instance of a question from their given poll?

I have a poll and a poll has questions. These are the models:

class poll < ApplicationRecord
  validates_presence_of :user, :title, :URL, :poll_type, :start_date, :end_date
  belongs_to :user
  has_many :questions, dependent: :destroy
end

class Question < ApplicationRecord
  validates_presence_of :poll_id, :question_type, :title
  belongs_to :poll
end

The schema for polls is as follows

create_table "polls", force: :cascade do |t|
    t.bigint "user_id", null: false
    t.string "title"
    t.text "description"
    t.text "URL"
    t.string "poll_type"
    t.datetime "start_date"
    t.datetime "end_date"
    t.boolean "weighted_voting"
    t.boolean "show_results"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
    t.index ["user_id"], name: "index_polls_on_user_id"
  end

The schema for quesitons

create_table "questions", force: :cascade do |t|
    t.bigint "poll_id", null: false
    t.string "question_type"
    t.string "title"
    t.text "description"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
    t.index ["ballot_id"], name: "index_questions_on_ballot_id"
  end

my routes.rb

resources :users do
    resources :polls do
      resources :questions do
        resources :options
      end
    end
  end

How can the user create a new instance of a question from their assigned given poll?

Currently the field poll_id in the questions form is empty. I can't figure out how to get this id populate. the polls form gets the user_id from devise's current_user.id variable via a form.

Also is doing this via the form the rails correct way of doing it?


Bonus Question: Would the method be the same for the options model?



Solution 1:[1]

You can do this by nested forms. Details are here

Firstly you should create new pool form. Basically this form must include Poll and Question form fields. You must use fields_for helper to create related forms for specific model.

poll form

  <%= form_for @poll do |poll| %>
      Poll name: <%= poll.text_field :poll_name%>
   
    
      <%= fields_for :question, @poll.questions do |question_fields| %>
            Question 1  : <%= question_fields.text_field :question_1 %>
            Answer 1    : <%= question_fields.check_box :answer_1 %>
            Answer 2    : <%= question_fields.check_box :answer_2 %>
            Answer 3    : <%= question_fields.check_box :answer_3 %>
      <% end %>
    
      <%= poll.submit %>
    <% end %>

in model file

class Poll < ApplicationRecord
  validates_presence_of :user, :title, :URL, :poll_type, :start_date, :end_date
  belongs_to :user
  has_many :questions, dependent: :destroy
  accepts_nested_attributes_for :questions
end

in poll controller permit the question attributes

questions_attributes: [
          :id,
          :question_text,
          :answer_1,
          :answer_2,
          ...
          :poll_id]

poll controller new action

5.times { @poll.questions.build } 

info about routes

Rails docs says: Resources should never be nested more than 1 level deep.

You can solve your problem with only

resources :polls

All you need to do inject current_user to poll controller when saving form. You don't need to another resources for questions. You can show all questions under the poll show page.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1