gpt4 book ai didi

ruby-on-rails - Rails - 如何使用子对象的嵌套属性和强参数填充父对象 id?

转载 作者:行者123 更新时间:2023-12-03 08:17:44 25 4
gpt4 key购买 nike

我遇到的情况很像 Railscast 196-197: Nested Model Form 中介绍的情况.但是,我遇到了这种方法和强参数之间的冲突。我想不出在子对象上填充父记录 id 字段的好方法,因为我不希望它可以通过表单分配(以防止用户将子记录关联到他们不拥有的父记录) )。我有一个解决方案(请参阅下面的代码),但这似乎是 Rails 为我提供的一种聪明、简单的方法。

这是代码...

有一个父对象(称之为 Survey),它有_many 子对象(称之为 Questions):

# app/models/survey.rb
class Survey
belongs_to :user
has_many :questions
accepts_nested_attributes_for :questions
end

# app/models/question.rb
class Question
validates :survey_id, :presence => true
belongs_to :survey
end

有一个表单允许用户同时创建调查和该调查中的问题(为简单起见,下面的代码将调查视为只有问题):
# app/views/surveys/edit.html.erb
<%= form_for @survey do |f| %>
<%= f.label :name %>
<%= f.text_field :name %><br />
<%= f.fields_for :questions do |builder| %>
<%= builder.label :content, "Question" %>
<%= builder.text_area :content, :rows => 3 %><br />
<% end %>
<%= f.submit "Submit" %>
<% end %>

问题是 Controller 。我想通过强参数保护问题记录上的survey_id 字段,但这样做时问题不会通过验证,因为survey_id 是必填字段。
# app/controllers/surveys_controller.rb
class SurveysController
def edit
@survey = Survey.new
Survey.questions.build
end

def create
@survey = current_user.surveys.build(survey_params)
if @survey.save
redirect_to @survey
else
render :new
end
end

private

def survey_params
params.require(:survey).permit(:name, :questions_attributes => [:content])
end
end

我认为解决这个问题的唯一方法是将问题与调查分开构建,如下所示:
def create
@survey = current_user.surveys.build(survey_params)
if @survey.save
if params[:survey][:questions_attributes]
params[:survey][:questions_attributes].each_value do |q|
question_params = ActionController::Parameters.new(q)
@survey.questions.build(question_params.permit(:content))
end
end
redirect_to @survey
else
render :new
end
end

private

def survey_params
params.require(:survey).permit(:name)
end

(Rails 4 测试版 1,Ruby 2)

更新

也许处理此问题的最佳方法是按照 this Code Climate blog post 中的建议提取“表单对象”。 .不过,我将问题悬而未决,因为我对其他观点感到好奇

最佳答案

所以你遇到的问题是子对象没有通过验证,对吗?当子对象与父对象同时创建时,子对象不可能知道其父对象的 id 以通过验证,这是真的。

以下是解决该问题的方法。更改您的模型如下:

# app/models/survey.rb
class Survey
belongs_to :user
has_many :questions, :inverse_of => :survey
accepts_nested_attributes_for :questions
end

# app/models/question.rb
class Question
validates :survey, :presence => true
belongs_to :survey
end

这里的区别是 :inverse_of传递给 has_many关联,并且该问题现在仅在 :survey 上验证而不是 :survey_id .
:inverse_of使得当使用关联创建或构建子对象时,它还接收对创建它的父对象的反向引用。这似乎应该自动发生,但不幸的是,除非您指定此选项,否则不会发生。

正在验证 :survey而不是在 :survey_id是一种妥协。验证不再简单地检查survey_id 字段中是否存在非空白内容;它现在实际上检查关联是否存在父对象。在这种情况下,由于 :inverse_of,它很有帮助。 ,但在其他情况下,它实际上必须使用 id 从数据库加载关联以进行验证。这也意味着与数据库中任何内容都不匹配的 id 将不会通过验证。

希望有帮助。

关于ruby-on-rails - Rails - 如何使用子对象的嵌套属性和强参数填充父对象 id?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16782990/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com