Многоступенчатая форма Rails Wicked - параметр отсутствует или значение пусто по сравнению с недопустимыми параметрами

Я следую этому руководству, чтобы создать многоступенчатая форма с использованием драгоценного камня Wicked. У каждого пользователя есть один ответ (модель для хранения ответов на набор вопросов), и у меня есть QuestionnaireController, который проходит через вопросы, на которые пользователь ответит и которые сохранены в ответе. Пока у меня есть только два шага, каждый с одним вопросом (логические столбцы в таблице ответов). Когда я прохожу и отвечаю на каждый вопрос, все работает отлично, однако, когда я отправляю без значения, я получаю:

param отсутствует или значение пустое: ответ

Мой код...

ответ.рб:

class Answer < ApplicationRecord
  belongs_to :user

  cattr_accessor :questionnaire_steps do
    %w(step_one step_two)
  end

  attr_accessor :current_step #stores the current questionnaire step

  validates :user_id, presence: true

  with_options if: -> { required_for_step?(:step_one) } do |step|
    step.validates :question_one, inclusion: [true, false]
  end
  with_options if: -> { required_for_step?(:step_two) } do |step|
    step.validates :question_two, inclusion: [true, false]
  end

  def required_for_step?(step)
    # All fields are required if no questionnaire step is present
    return true if current_step.nil?
    # All fields from previous steps are required if the
    # step parameter appears before or we are on the current step
    return true if self.questionnaire_steps.index(step.to_s) <= self.questionnaire_steps.index(current_step)
  end
end

answer_controller.rb:

class AnswersController < ApplicationController
  before_action :setup

  def setup
    @user = current_user
  end

  def show
    @answer = @user.answer
  end

  def new
    @answer = Answer.new
    @answer = @user.build_answer
    @answer.save(validate: false)
  end

  def create
    @answer = @user.answer
    redirect_to questionnaire_path(@answer, Answer.questionnaire_steps.first)
  end
end

анкета_controller.rb:

class QuestionnaireController < ApplicationController
  include Wicked::Wizard

  before_action :setup

  steps *Answer.questionnaire_steps

  def setup
    @user = current_user
  end

  def show
    @answer = @user.answer
    render_wizard
  end

  def update
    @answer = @user.answer
    @answer.update_attributes(answer_params(step))
    render_wizard @answer
  end

  private

  def answer_params(step)
    permitted_attributes = case step
      when "step_one"
        [:question_one]
      when "step_two"
        [:question_two]
    end

    params.require(:answer).permit(permitted_attributes).merge(current_step: step)
  end
end

step_one.html.erb:

<div id="questionnaire" class="container-fluid well inline-headers">
  <%= form_for @answer, method: :put, url: wizard_path do |f| %>
  <div class="row">
    <% if f.object.errors.any? %>
      <div id="error_explanation" class="alert alert-dismissible alert-danger" >
        <button type="button" class="close" data-dismiss="alert" aria-hidden="true">&times;</button>
        <ul>
          <% f.object.errors.each do |attribute, message| %>
            <%= content_tag :li, f.object.errors.full_message(attribute, message), :id => "error_#{attribute}" %>
          <% end %>
        <ul>
      </div>
    <% end %>
  </div>
  <div class="row">
    <div class="col-md-8 form-group">
      <p>Are you any good at this?</p>
    </div>
    <div class="col-md-4 form-group">
      <%= label_tag(:question_one, "Yes") %>
      <%= f.radio_button :question_one, true %>
      <%= label_tag(:question_one, "No") %>
      <%= f.radio_button :question_one, false %>
    </div>
  </div>
  <div class="row">
    <div class="col-md-4 col-md-offset-8 form-group">
      <p><%= f.submit "Save & Continue", class: "btn btn-warning" %></p>
    </div>
  </div>
  <% end %>
</div>

route.rb (по общему признанию, я пытался быть милым с этим, чтобы замаскировать идентификаторы, не стесняйтесь пристыдить меня, чтобы я сделал это правильно):

resources :answers, only: [:show, :new, :create]
  get 'user/questionnaire', to: 'answers#show'
  get 'user/questionnaire/new', to: 'answers#new'
  post 'user/questionnaire/new', to: 'answers#create'

resources :questionnaire

Когда я выбираю параметр и отправляю, он сохраняется в базе данных и перенаправляется на следующий шаг, однако, если я отправляю без выбора параметра, я получаю ошибку отсутствия параметра, хотя я ожидал получить ошибки проверки. Из журнала сервера:

Обработка с помощью QuestionnaireController#update в виде HTML-параметров: {"utf8"=>"��", "authenticity_token"=>"J45sG/YIqTaBECgBqNLr9Ys3rJewDK78d/cKHWFHYEIzAaOiTXhgH6evPZKl5LhnSAMnQnA94CXonqriy="j0fCQ=","Save & Continue=>"id =>"шаг_один"}

Я пробовал ряд возможных исправлений, в том числе удаление require(:answer) из params.require(:answer).permit(permitted_attributes).merge(current_step: step), что приводит к ошибке проверки, которую я ожидал, но затем не позволяет сохранить действительное значение. В этом случае я все еще получаю ошибку проверки со следующим в журнале сервера:

Запущен PUT "/questionnaire/step_one" для ::1 в 2016-12-08 23:26:14 +0545 Обработка с помощью QuestionnaireController#update as HTML
Параметры: {"utf8"=>"����", " authentication_token"=>"RWAHfu0BE82ik6gTChh3nmtuyOUa5j0qiz4H03ejIkRR78jHVnHa5IQsvYAHLiQMqFpDMNrXc/MUV6cs3NldDw==", "answer"=>{"question_one"=>"true"}, "commit"=>"Сохранить и продолжить", "id"=>"step_one"} .. .SQL... Недопустимые параметры: utf8, _method, authentication_token, answer, commit, id

Заранее спасибо за помощь новичку.

ОБНОВЛЕНИЕ: я изменил свои маршруты, чтобы они соответствовали учебнику (вложенному), думая, что это может иметь какое-то отношение к нему (т.е., возможно, не получить идентификатор ответа), но я все еще получаю сообщение об ошибке отсутствия параметра.

resources :answers, only: [:show, :new, :create] do
    resources :questionnaire, only: [:show, :update], controller: 'questionnaire'
  end
  get 'user/questionnaire', to: 'answers#show'
  get 'user/questionnaire/new', to: 'answers#new'
  post 'user/questionnaire/new', to: 'answers#create'

Я также попытался добавить hidden_field_tag ​​перед отправкой, например:

<%= hidden_field_tag(:answer, @answer) %>

Но потом я получаю:

неопределенный метод `разрешение' для #

Вероятно, потому, что hidden_field_tag ​​передает @answer.attributes в виде строки, когда сильное объявление параметра ожидает хэш. С сервера:

Запущен PUT "/answers/46/questionnaire/step_one" для ::1 в 2016-12-12 13:25:19 +0545 Обработка с помощью QuestionnaireController#update как параметры HTML: {"utf8"=>"����", "authenticity_token"=>"wlLpKoMvqgyfwB5gyP/qubR4ZpZa6jm9KHeMuiwJTc6IOJZi9PgiSegvF+OzlN09ctEuxuxiAuRs+/B2InRGhA==", "answer"=>"{\"id\"=>46, \"user_id\"=>4, \"question_one\"=>nil , \"question_two\"=>nil, \"percentage_complete\"=>#, \"completed\"=>false, \"created_at\"=>Mon, 12 декабря 2016 02:12:31 EST -05:00 , \"updated_at\"=>Пн, 12 декабря 2016 г., 02:12:31 EST -05:00}", "commit"=>"Сохранить и продолжить", "answer_id"=>"46", "id"= >"шаг_один"}

Пожалуйста помоги!


person CChandler81    schedule 08.12.2016    source источник


Ответы (2)


Вопрос еще актуален?

Я хотел написать это в комментарии, но не могу. Думаю проблема в валидации. Он проверяет, ввели ли вы значение в соответствующих полях, и выдает ошибку, если вы этого не сделали. Что произойдет, если вы удалите step.validates из модели?

person Marco    schedule 20.12.2016
comment
Все еще в силе, и я думаю, что решил это. Мне нужны проверки, поэтому я изменил params.require на params.fetch, и это, кажется, работает (проверки запускаются соответствующим образом, и я также могу успешно выполнить шаги с допустимыми значениями). - person CChandler81; 13.01.2017

Я изменил params.require на params.fetch, и это работает (проверки запускаются соответствующим образом, и я также могу успешно выполнить шаги с допустимыми значениями).

person CChandler81    schedule 16.01.2017