我似乎无法获取嵌套属性来保存到数据库中。我正在使用Rails 4。
以下是我的模特:
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
这是控制器:
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
最后,这是表单本身。我尝试过使用f.fields_for和field_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 %>
调查可以很好地保存数据库,不会提出问题和答案。我看过我能找到的每一种资源,似乎我正确地做到了这一点,所以这真让我疯狂。
这个例子只是一个快速的脚手架,所以我有一些代码可以粘贴,但我似乎无法让它在其他任何地方工作。
修改: 将我的新动作更改为:
def new
@survey = Survey.new
@survey.questions.build
end
工作!
请寻求解决此问题的解答
以下是我正在使用的新表单,仍然只保存调查名称
<%= 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 %>
答案 0 :(得分:7)
看起来你正在使用错误的表单构建器对象。将问题部分更改为以下内容:
<%= 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 %>
最初您使用f
行中的f.fields_for :answers...
表单构建器,但是根据您的模型代码,因为它是Question
accepts_nested_attributes_for
{{1} },我们只需将表单构建器对象替换为用于Answer
部分的表单。
注意:为了清楚起见,我更改了构建器对象的名称。
<强>更新强>
为了构建这样一个深层嵌套的关系,你必须遍历你的“构建”关联(在这种情况下为question
),并在questions
上再次调用build
关联。所以关于gabrielhilal的答案,你会这样做:
has_many
注意在您的情况下,由于您只是明确地创建了一个问题,因此您可以在技术上改为(而不是循环):
def new
@survey = Survey.new
@survey.questions.build
@survey.questions.each do |question|
question.answers.build
end
end
免责声明:如果有更干净,更多的Rails-y方式,我很遗憾没有意识到这一点。
答案 1 :(得分:4)
在您的控制器中,您有questions_id
:
def survey_params
params.require(:survey).permit(:name,
questions_attributes: [
:content, :id, :survey_id,
answers_attributes: [:content, :id, :questions_id]
]
)
end
这是一个错字吗?另请尝试在action_on_unpermitted_parameters
中设置:raise
至development.rb
,以查看您的survey_params
方法中是否遗漏了任何属性。
# In case of unpermitted parameters in the controller raise error.
config.action_controller.action_on_unpermitted_parameters = :raise
答案 2 :(得分:3)
您必须更改new
操作以包含@survey.questions.build
:
def new
@survey = Survey.new
@survey.questions.build
end
但你的表格也是错的。将question
更改为questions
<%= f.fields_for :questions do |builder| %> #questions
<%= builder.label :content %>
<%= builder.text_area :content %>
你必须为答案做同样的事情。