Simple_form_for多对多验证



设置

我在Submit和通过SubmitAnswer的Answer之间有一个简单的多对多关系。

答案按一个问题分组(在我的情况下,每个问题有三个答案(——把它想象成一个多选测验。

我一直在尝试使用SimpleFormFor制作一个表格,该表格呈现一组预先确定的问题,其中每个问题都有一组预先确定的答案

类似这样的东西:

#form
<%= simple_form_for Submit.new, url: "/questionnaire" do |f| %>
<% @questions.each do |question| %>
<%= f.association :answers, collection: question.answers %>
<% end %>
<%= f.submit :done %>
<% end %>
#controller
def create
@submit = Submit.new(submit_params)
@submit.user = current_user
if @submit.save
redirect_to root_path
else
render :new
end
end
def submit_params
params.require(:submit).permit(answer_ids: [])
end

当我提交表单时,Rails会自动创建联接表SubmitAnswers。

因此,问题的关键在于:重新呈现表单、错误和所有问题(如果不是所有问题(的最简单方法是什么,即如果@submit.answers.length != @question.length

我可以使用errors.add(:answers, 'error here')添加自定义错误,但当我重新呈现时,正确选择的答案不会重新填充,这是次优的。

对于完整的sacke,以下是我的模型:

class Submit < ApplicationRecord
belongs_to :user
has_many :submit_answers
has_many :answers, through: :submit_answers
end
class SubmitAnswer < ApplicationRecord
belongs_to :submit
belongs_to :answer
end
class Answer < ApplicationRecord
has_many :submit_answers
has_many :submits, through: :submit_answers
end

好吧,经过一番挖掘,我们确实找到了使表单工作的答案,尽管我们预计简单的多对多会带来更多的痛苦。

#model
class Submit < ApplicationRecord
belongs_to :user
has_many :submit_answers
has_many :answers, through: :submit_answers
accepts_nested_attributes_for :submit_answers
end
#controller
def new
@submit = Submit.new  
@questions.count.times { @submit.submit_answers.build }
end
def create
@submit = Submit.new(submit_params)
@submit.user = current_user
if @submit.save
redirect_to root_path
else
render :home
end
end
def submit_params
params.require(:submit).permit(submit_answers_attributes:[:answer_id])
end
#form
<%= simple_form_for @submit do |f| %>
<%= f.simple_fields_for :submit_answers do |sa| %>
<%= sa.input :answer_id,  collection: @answers[sa.options[:child_index]], input_html: { class: "#{'is-invalid' if sa.object.errors.any?}"}, label: @questions[sa.options[:child_index]].name %>
<div class="invalid-feedback d-block">
<ul>
<% sa.object.errors.full_messages.each do |msg| %>
<li> <%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<%= f.submit :done %>
<% end %>

解决方案是使用simple_fields_for/fields_for。请注意,<%= sa.input :answer_id %>必须是:answer_id,而不是:answer——这是我以前尝试过的。

还必须允许accepts_nested_attributes_for :submit_answers,其中:submit_answersjoin_table

我这样预构建我的SubmitAnswers:@questions.count.times { @submit.submit_answers.build },它为每个问题生成一个输入字段,所有这些都保存在表单submit上,这是一个la构建。

对于strong_params,需要允许传入的id:params.require(:submit).permit(submit_answers_attributes:[:answer_id]),因此在这种情况下submit_answers_attributes:[:answer_id]

对于任何想知道参数是什么样子的人:

{"authenticity_token"=>"[FILTERED]",
"submit"=>
{"submit_answers_attributes"=>
{"0"=>{"answer_id"=>""}, "1"=>{"answer_id"=>""}, "2"=>{"answer_id"=>""}, "3"=>{"answer_id"=>""}, "4"=>{"answer_id"=>""}, "5"=>{"answer_id"=>""}, "6"=>{"answer_id"=>""}}},
"commit"=>"done"}

至于错误,我相信可能有更好的方法,但目前我只是用input_html: { class: "#{'is-invalid' if sa.object.errors.any?}"}手动添加了它们。

最后,sa.object # => SubmitAnswer允许我检索模型、该模型的错误或其他任何可能需要的信息。

相关内容

  • 没有找到相关文章

最新更新