简体   繁体   English

Rails中的嵌套模型表单

[英]Nested model form in Rails

I am trying to create a web app that could be used for submitting answers to quizes. 我正在尝试创建一个可用于提交测验答案的Web应用程序。 And I am having troubles creating the view files. 而且我在创建视图文件时遇到了麻烦。

The submission form should look like this (sorry, SO does not allow me to insert images in the body of the question). 提交表单应如下所示 (很抱歉,SO不允许我在问题正文中插入图片)。

It is a case of nested model forms discussed by Ryan Bates in Railscasts, but there is an important difference. 这是Ryan Bates在Railscasts中讨论的嵌套模型形式的情况,但是有一个重要的区别。 In Ryan Bates' case there is a simple chain of associations: a Survey model has many Questions, and each Question has many Answers. 在瑞安·贝茨(Ryan Bates)的案例中,有一条简单的关联链:一个调查模型有很多问题,而每个问题有很多答案。

What I am planning, though, is a bit more complex. 不过,我计划的要复杂一些。 In my case, a Quiz has many Questions, and a Question has many Answers, but what a user is presented with is a model called Submission. 在我的情况下,测验有许多问题,而一个问题有许多答案,但是向用户展示的是一个称为“提交”的模型。 A Submission is associated with the User model and the Answer model, and it also has some additional information. 提交与用户模型和应答模型相关联,并且还具有一些其他信息。 Schematically, my associations look like this : 在示意图上,我的关联如下所示

So I need to create a form that will combine a model (Submission) with many unassociated models (Questions) and many associated models (Answers). 因此,我需要创建一个将模型(提交)与许多未关联的模型(问题)和许多关联的模型(答案)结合在一起的表格。 All I could think of for my new/edit view file is this: 我可以为我的新/编辑视图文件想到的是:

Controller: 控制器:

  # GET /tests/:test_id/submissions/new
  def new
    @quiz = Quiz.find(params[:quiz_id])
    # the next four lines of code are to select a subset of questions
    variant = choose_variant(@quiz)
    @submission = Submission.new
    @submission.variant = variant
    @questions = Question.where (variant: variant)
    @questions.each {|question| quiestion.answers.build}
  end

View: 视图:

= form_for [@quiz, @submission]  do |f|

    = f.fields_for :answers do |builder|
      = @questions.each do |question|
      %p
        = @question.text
       = builder.label :answer_text, "Your answer"
       = builder.text_area :answer_text

But it doesn't look right: there is no association between the @submission, the @question and the answers. 但这看起来并不正确:@ submission,@ question和答案之间没有关联。 Could you please suggest how to solve this problem if there is no direct association between the Submission and the Question model? 如果提交与问题模型之间没有直接关联,请提出如何解决此问题的建议?


UPDATE: 更新:

I can now create a form in the view: 我现在可以在视图中创建一个表单:

= form_for [@quiz, @submission]  do |f|

    - @questions.each do |question|
      %p
        = question.text
      = f.fields_for :answer, question.answers.first do |builder|
        = builder.label :text, "Answer"
        = builder.text_area :text

The trouble is, on submit the last answer overwrites all the privious answers, and in the params I get only: 麻烦的是,提交时,最后一个答案将覆盖所有不明确的答案,并且在参数中我只能得到:

"submission"=>{"answer"=>{"text"=>"Answer to the last question"}}


UPDATE 2: 更新2:

To Marcelo Risoli (sorry, I haven't got the hang of StackOverflow behavior, and it doesn't allow me to write another comment). 对于Marcelo Risoli(对不起,我没有StackOverflow行为的烦恼,它不允许我写其他评论)。 I apologize, I did not quite understand your suggestion at first. 抱歉,起初我不太了解您的建议。 Your line @questions.each { |q| @submission.answers.build question_id: q.id } 您的一行@questions.each { |q| @submission.answers.build question_id: q.id } @questions.each { |q| @submission.answers.build question_id: q.id } is pure genius: it associates answers with the submission in the controller instead of in the view, as I initially tried to do. @questions.each { |q| @submission.answers.build question_id: q.id }是个天才:它将answers与控制器中的submission (而不是视图中的submission相关联,就像我最初尝试的那样。 Will try do go through with your suggestion and will write back. 会尝试通过您的建议并写回。 But it seems like this line will solve all my problems :-) 但是似乎这条线可以解决我所有的问题:-)

Use appropriate join tables. 使用适当的联接表。 Suggest you use an 'answer' table for the actual answer that a user makes. 建议您使用“答案”表作为用户的实际答案。 Use question_options and option_groups for the possible answers for a question. question_optionsoption_groups用于可能的问题答案。

Suggest you consider basing it on https://stackoverflow.com/a/5858666/631619 建议您考虑基于https://stackoverflow.com/a/5858666/631619

Just substitute 'survey' for 'quiz' 只是用“调查”代替“测验”

在此处输入图片说明

I did something very similar, I can give you some suggestions: 我做了一些非常相似的事情,我可以给你一些建议:

First, I'd advise you use cocoon , nested form is not being updated anymore, and I found cocoon to be much easier to deal with. 首先,我建议您使用cocoon ,嵌套形式不再被更新,并且我发现cocoon更加容易处理。

Second, the submission does not need association with the question, if necessary you can access a question with a given submission with the a has_many: :through association. 其次,提交不需要与问题相关联,如果有必要,您可以通过has_many::through关联来访问给定提交的问题。

When you use fields_for :answers in a form_for submission means the newly created submission_id will be input into the answers, now all you need is to input the question_id, you can do that through a hidden input, just do the following in your controller: 当您在form_for提交中使用fields_for:answers时,意味着新创建的submission_id将被输入到答案中,现在您只需要输入question_id,就可以通过隐藏的输入来做到这一点,只需在控制器中执行以下操作即可:

@questions.each { |q| @submission.answers.build question_id: q.id }

then add = builder.input :question_id, as: :hidden to your form 然后将= builder.input :question_id, as: :hidden添加= builder.input :question_id, as: :hidden到表单中

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM