Rails 4 嵌套属性不保存 [英] Rails 4 nested attributes not saving

查看:26
本文介绍了Rails 4 嵌套属性不保存的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我似乎无法获取嵌套属性以保存到数据库.我正在使用 Rails 4.

这是我的模型:

class 答案 <ActiveRecord::Base归属地:问题结尾课堂问题<ActiveRecord::Basehas_many :answers归属地:调查accepts_nested_attributes_for :answers, allow_destroy: true结尾班级调查ActiveRecord::Basehas_many :问题validates_presence_of :nameaccepts_nested_attributes_for :questions结尾

这是控制器:

def 创建@survey = Survey.new(survey_params)response_to do |格式|如果@survey.saveformat.html { redirect_to @survey,注意:'调查已成功创建.'}format.json { 渲染动作:'show',状态::已创建,位置:@survey }别的format.html { 渲染动作:'新' }format.json { 渲染 json:@survey.errors,状态::unprocessable_entity }结尾结尾结尾定义调查参数params.require(:survey).permit(:name, questions_attributes:[:content, :id, :survey_id,answer_attributes:[:content, :id, :questions_id]])结尾

最后,这里是表单本身.我试过同时使用 f.fields_for 和只使用 fields_for

<%= form_for(@survey) do |f|%><% if @survey.errors.any?%><div id="error_explanation"><h2><%=pluralize(@survey.errors.count, "error") %>禁止保存此调查:</h2><ul><% @survey.errors.full_messages.each do |msg|%><li><%=msg%></li><%结束%>

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

<%= 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 %><%结束%><%结束%><div class="actions"><%= f.submit %>

<%结束%>

调查好保存到数据库,问题和答案不会放.我查看了我能找到的所有资源,似乎我的做法是正确的,所以这真的让我发疯了.

这个例子只是一个快速的脚手架,所以我有一些代码要粘贴,但我似乎无法让它在其他任何地方工作.

将我的新操作更改为这样的内容:

def new@survey = Survey.new@survey.questions.build结尾

成功了!

请参阅 TEEGS 答案以获取解决方案

这是我使用的新表格,仍然只保存调查名称

 <%= f.fields_for :question do |question_builder|%><%= form_for(@survey) 做 |f|%><% if @survey.errors.any?%><div id="error_explanation"><h2><%=pluralize(@survey.errors.count, "error") %>禁止保存此调查:</h2><ul><% @survey.errors.full_messages.each do |msg|%><li><%=msg%></li><%结束%>

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

<%= 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 %><%结束%><%结束%><div class="actions"><%= f.submit %>

<%结束%>

解决方案

看起来您使用了错误的表单构建器对象.将问题部分更改为如下所示:

<%= 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 %><%结束%><%结束%>

最初您使用 f.fields_for :answers... 行中的 f 表单构建器,但是给定您的模型代码,因为它是一个 问题 accepts_nested_attributes_forAnswer,我们只需将表单构建器对象交换为用于question 部分的对象.

注意:为了清楚起见,我更改了构建器对象的名称.

更新

为了建立像这样的深度嵌套关系,您必须遍历构建"关联(在本例中为questions),然后再次调用build在它的 has_many 关联上.所以离开 gabrielhilal 的回答,你会这样做:

def new@survey = Survey.new@survey.questions.build@survey.questions.each 做 |问题|问题.答案.构建结尾结尾

注意,在您的情况下,由于您只明确创建一个问题,因此您可以在技术上改为执行此操作(而不是循环):

@survey.questions.first.answers.build

免责声明:如果有更干净、更符合 Rails 标准的方法来做到这一点,我很遗憾没有意识到.

I cannot seem to get nested attributes to save to the database. I am using 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

<%= 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.

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. So going off of gabrielhilal's answer, you would do this:

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 4 嵌套属性不保存的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
其他开发最新文章
热门教程
热门工具
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆