简体   繁体   English

Rails 4嵌套属性不保存

[英]Rails 4 nested attributes not saving

I cannot seem to get nested attributes to save to the database. 我似乎无法获得嵌套属性来保存到数据库。 I am using Rails 4. 我正在使用Rails 4。

Here are my models : 这是我的模特:

class Answer < ActiveRecord::Base
  belongs_to :question
end


class Question < ActiveRecord::Base
  has_many :answers
  belongs_to :survey
  accepts_nested_attributes_for :answers, allow_destroy: true
end

class Survey < ActiveRecord::Base
  has_many :questions
  validates_presence_of :name
  accepts_nested_attributes_for :questions
end

Here is the controller: 这是控制器:

def create

  @survey = Survey.new(survey_params)

  respond_to do |format|
    if @survey.save
      format.html { redirect_to @survey, notice: 'Survey was successfully created.' }
      format.json { render action: 'show', status: :created, location: @survey }
    else
      format.html { render action: 'new' }
      format.json { render json: @survey.errors, status: :unprocessable_entity }
    end
  end
end

def survey_params
  params.require(:survey).permit(:name, questions_attributes:[:content, :id, :survey_id, 
    answers_attributes:[:content, :id, :questions_id]
    ])
end

Finally, here is the form itself. 最后,这是表单本身。 I have tried using both f.fields_for and just fields_for 我尝试过使用f.fields_for和fields_for

<%= form_for(@survey) do |f| %>
  <% if @survey.errors.any? %>
    <div id="error_explanation">
      <h2><%= pluralize(@survey.errors.count, "error") %> prohibited this survey from being saved:</h2>

      <ul>
      <% @survey.errors.full_messages.each do |msg| %>
        <li><%= msg %></li>
      <% end %>
      </ul>
    </div>
  <% end %>

  <div class="field">
    <%= f.label :name %><br>
    <%= f.text_field :name %>
  </div>

  <%= f.fields_for :question do |builder| %>
     <%= builder.label :content %>
     <%= builder.text_area :content %>

       <%= f.fields_for :answer do |builder| %>
         <%= builder.label :content, "Answer" %>
         <%= builder.text_field :content %>
       <% end %>

  <% end %>
  <div class="actions">
    <%= f.submit %>
  </div>
<% end %>

The survey saves fine to the database, put the questions and answers will not. 调查可以很好地保存数据库,不会提出问题和答案。 I've looked at every resource I could find and it seems like I am doing this correctly, so it's really driving me crazy. 我已经查看了我能找到的所有资源,看起来我正确地做到了这一点,所以这真的让我发疯了。

This example is just a quick scaffold so I had some code to paste in, but I can't seem to get it to work anywhere else. 这个例子只是一个快速的脚手架,所以我有一些代码要粘贴,但我似乎无法让它在其他任何地方工作。

edit: changing my new action to something like this : 编辑:将我的新动作更改为以下内容

def new
  @survey = Survey.new
  @survey.questions.build
end

WORKED! 成功了!

SEE TEEGS ANSWER FOR SOLUTION TO THIS 请寻求解决方案以获得解决方案

Here is the new form I am using, still only saving the survey name 这是我正在使用的新表单,仍然只保存调查名称

  <%= f.fields_for :question do |question_builder| %>
  <%= form_for(@survey) do |f| %>
  <% if @survey.errors.any? %>
    <div id="error_explanation">
      <h2><%= pluralize(@survey.errors.count, "error") %> prohibited this survey from being saved:</h2>

      <ul>
      <% @survey.errors.full_messages.each do |msg| %>
        <li><%= msg %></li>
      <% end %>
      </ul>
    </div>
  <% end %>

  <div class="field">
    <%= f.label :name %><br>
    <%= f.text_field :name %>
  </div>

  <%= f.fields_for :question do |question_builder| %>
   <%= question_builder.label :content %>
   <%= question_builder.text_area :content %>

   <%= question_builder.fields_for :answer do |answer_builder| %> 
       <%= answer_builder.label :content, "Answer" %>
       <%= answer_builder.text_field :content %>
   <% end %>

<% end %>

  <div class="actions">
    <%= f.submit %>
  </div>
<% end %>

Looks like you're using the wrong form builder object. 看起来你正在使用错误的表单构建器对象。 Change the question section to something like this: 将问题部分更改为以下内容:

<%= f.fields_for :question do |question_builder| %>
   <%= question_builder.label :content %>
   <%= question_builder.text_area :content %>

   <%= question_builder.fields_for :answer do |answer_builder| %> 
       <%= answer_builder.label :content, "Answer" %>
       <%= answer_builder.text_field :content %>
   <% end %>

<% end %>

Originally you were using the f form builder in the line f.fields_for :answers... , however given your model code, since it is a Question that accepts_nested_attributes_for an Answer , we simply exchange the form builder object for the one used for the question section. 本来你正在使用的f在该行表单生成f.fields_for :answers... ,然而,考虑模型的代码,因为它是一个Questionaccepts_nested_attributes_forAnswer ,我们只是交换表单生成器对象用于对一个question部分。

Note: I changed the names of the builder objects for clarity. 注意:为清楚起见,我更改了构建器对象的名称。

Update 更新

In order to build a deeply nested relationship like this, you will have to loop through your "built" association ( questions in this case), and invoke build again on its has_many association. 为了构建这样一个深层嵌套的关系,你必须遍历你的“构建”关联(在这种情况下是questions ),并再次在其has_many关联上调用build So going off of gabrielhilal's answer, you would do this: 所以关闭gabrielhilal的答案,你会这样做:

def new
  @survey = Survey.new
  @survey.questions.build
  @survey.questions.each do |question|
      question.answers.build
  end
end

Note that in your case, since you are explicitly creating only one question, you can technically do this instead (instead of the loop): 请注意 ,在您的情况下,由于您只是明确地创建了一个问题,因此您可以在技术上改为执行此操作(而不是循环):

@survey.questions.first.answers.build

Disclaimer: If there is a cleaner, more Rails-y, way to do this, I am sadly unaware of it. 免责声明:如果有更清洁,更多的Rails-y,这样做的方式,我很遗憾没有意识到这一点。

In your controller you have questions_id : 在您的控制器中,您有questions_id

def survey_params
  params.require(:survey).permit(:name, 
    questions_attributes: [
      :content, :id, :survey_id, 
      answers_attributes: [:content, :id, :questions_id]
    ]
  )
end

Is that a typo? 那是一个错字吗? Also try setting action_on_unpermitted_parameters to :raise in you development.rb to see if there is any attribute that you' re missing in your survey_params method. 还可以尝试将action_on_unpermitted_parameters设置为:raise在您的development.rb :raise ,以查看您的survey_params方法中是否存在任何缺少的属性。

# In case of unpermitted parameters in the controller raise error.
config.action_controller.action_on_unpermitted_parameters = :raise

You must change your new action to include @survey.questions.build : 您必须更改new操作以包含@survey.questions.build

def new
  @survey = Survey.new
  @survey.questions.build
end

But your form is wrong as well. 但你的形式也是错的。 Change the question to questions question更改为questions

 <%= f.fields_for :questions do |builder| %> #questions
   <%= builder.label :content %>
   <%= builder.text_area :content %>

You must do the same thing for answers. 你必须为答案做同样的事情。

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

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