Форма ответа на обзор Rails - PullRequest
0 голосов
/ 10 ноября 2018

У меня есть приложение для опроса, которое я перепутал на последней стороне. Вот свойства модели приложения:

User

- Survey
    user_id

title
- Question
    title
    survey_id
    type: multiple_choice|check_boxes|short_answer
- Option
    title
    question_id

                   (Till here is okay. I can create surveys these includes more nested forms) Issue is after created surveys. (users responses) 

-Response
    user_id
    survey_id
-Answer
    question_id
    response_id
    option_id

Создание опроса с вложенными атрибутами - это нормально. Проблема на Ответной стороне. каким должен быть мой контроллер ответа и форма ответа на Survey show.html.erb?

Ниже приведены вложенные атрибуты контроллера ответа;

  def response_params
    params.require(:response).permit(:id, :user_id, :survey_id, answers_attributes:[:question_id, :response_id, :option_id ] )
  end

Я должен сказать, что опрос может включать в себя несколько вопросов, только с radio_buttons (независимые переключатели - другая проблема)

Этот вопрос заставил меня так устать. Я буду рад, если вы сможете мне помочь. Благодарю. Для исходного кода: Нажмите для исходного кода

обновленные файлы:

Модель ответа:

class Response < ApplicationRecord
    belongs_to :user
  belongs_to :survey
  has_many :answers, dependent: :destroy
  validates :survey, presence: true
  counter_culture :option
  accepts_nested_attributes_for :answers
end

Survey_controller:

def new_response
@survey = Survey.find(params[:id])
@response = @survey.responses.build

    # now, the tricky part, you have to build the Answer objects so you can use the nested form later
    @survey.questions.each do |q|
      @response.answers.build question: q
    end
  end



def create_response
  @survey = Survey.find(params[:id])
  @response = @survey.build(response_params)
  @response.user = current_user
  @response.save
end

Маршруты:

Rails.application.routes.draw do

  devise_for :users
    resources :surveys do 
    member do
      get :new_response
      get :create_response 
    end
        end
  root 'surveys#index'

  end

Форма:

- # surveys/new_response.html.haml
- # You need to define a nested route inside survey resource to create the response
= form_for @response, url: create_response_survey_path(@survey) do |f|
  - # you can iterate over all the answers already initialized
  = f.fields_for :answers do |ff|
    - # get the question from the current answer to show the title and options and a hidden_field with the question id
    - q = ff.object.question

    = q.title
    = ff.hidden_field :question_id

    - # add the radios for each options for the question
    - q.options.each do |option|
      = label_tag do
        = ff.radio_button :option_id, option.id
        = option.title

  = f.submit 'Send'

1 Ответ

0 голосов
/ 10 ноября 2018

Я бы не использовал действие show опроса, чтобы показать форму для создания ответа, я думаю, что лучше подходить к нему как действие new_response, чтобы сделать его чище, и оставить действие show просто для показа. фактический опрос (не отвечать на него). Что-то вроде:

class SurveysController < ApplicationController
  def new_response
    @survey = Survey.find(params[:id])
    @response = @survey.responses.build

    # now, the tricky part, you have to build the Answer objects so you can use the nested form later
    @survey.questions.each do |q|
      @response.anwers.build question: q
    end
  end

Теперь у вас может быть форма для ответа:

- # surveys/new_response.html.haml
- # You need to define a nested route inside survey resource to create the response
= form_for @response, url: create_response_survey_path(@survey) do |f|
  - # you can iterate over all the answers already initialized
  = f.fields_for :answers do |ff|
    - # get the question from the current answer to show the title and options and a hidden_field with the question id
    - q = ff.object.question

    = q.title
    = ff.hidden_field :question_id

    - # add the radios for each options for the question
    - q.options.each do |option|
      = label_tag do
        = ff.radio_button :choice_id, option.id
        = option.title

  = f.submit 'Send'

Ваш response_params должен выглядеть примерно так:

def response_params
  params.require(:response).permit(answers_attributes: [:question_id, :choice_id])
end

обратите внимание, что я удалил :survey_id и :user_id, вы не хотите, чтобы пользователь взломал вашу форму, изменил survey_id или user_id и добавил ответы на другой опрос, проведенный другим пользователем!

и ваше create_response действие:

def create_response
  @survey = Survey.find(params[:id])
  @response = @survey.build(response_params)
  @response.user = current_user
  @response.save
end

Надеюсь, это имеет смысл.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...