gpt4 book ai didi

ruby-on-rails - 如何通过验证预先加载 fields_for

转载 作者:行者123 更新时间:2023-12-04 06:27:57 24 4
gpt4 key购买 nike

我的表单中有这个 fields_for :

= f.fields_for :parts do |builder|
= builder.input :body, label: builder.object.another_relation.description, required: false

在主模型中,我有这个验证:
validates_associated :parts

在零件模型中,我有这个验证:
validates :body, presence: true

这很好用。当我将某些部分留空并尝试创建模型时,表单会再次重新显示并显示正确的错误消息。

但是在日志中我看到标签正在查询每个部分的数据库,所以我需要预先加载它。

如何?

这是我的尝试:
= f.fields_for :parts, f.object.parts.includes(:question_part) do |builder|
= builder.input :body, label: builder.object.another_relation.description, required: false

这种渴望成功加载关系,但是当我将某些字段留空并尝试创建模型时,表单会重新显示,所有部分都为空且没有错误。我认为这是正常的,因为我正在强制 fields_for 从我正在传递的那个集合中加载字段。

有谁知道如何解决这个问题?

最佳答案

这是一种方法。

想象一下这 4 个模型,与 StackOverflow 等问答网站相关,所以每个人都知道我们在说什么 :)

enter image description here

所以,一个问题有 N 个部分,也有 N 个答案。而一个答案属于一个问题,并且有 N 个部分。最后,答案部分属于问题部分。

class Question
has_many :parts, class_name: 'QuestionPart', dependent: :destroy
accepts_nested_attributes_for :parts, allow_destroy: true
has_many :answers, dependent: :destroy

# ...
end

class QuestionPart
belongs_to :question

# ...
end

class Answer
belongs_to :question
belongs_to :user
has_many :parts, class_name: 'AnswerPart', dependent: :destroy
accepts_nested_attributes_for :parts, allow_destroy: true

# ...
end

class AnswerPart
belongs_to :answer
belongs_to :question_part

validates :body, presence: true

# ...
end

我们来看看应答 Controller :
class AnswersController < ApplicationController
def new
@question = Question.find(params[:question_id)
@answer = @question.answers.new
@question.parts.each { |p| @answer.parts.build(question_part: p) }
end

def edit
@answer = Answer.find(params[:id])
@answer_parts = @answer.parts.includes(:question_part)
end

def create
@question = Question.find(params[:question_id])
@answer = current_user.answers.build(answer_params.merge(question: @question))

if @answer.save
redirect_to @question, notice: 'The answer was successfully created.'
else
render :new
end
end

def update
#@answer = Answer.find(params[:id])
@answer = Answer.where(id: params[:id]).includes(parts: [:question_part]).first

if @answer.update(answer_params)
redirect_to @answer.question, notice: 'The answer was successfully updated.'
else
render :edit
end
end

private

def answer_params
params.require(:answer).permit(:body, parts_attributes: [:id, :question_part_id, :body])
end
end

请注意我如何在更新方法中检索答案。我已经注释掉了标准方式,同时我正在使用自定义查询检索它(应该移到 Answer 模型中)。这是我遇到麻烦的地方。 如果有人知道更好的方法,请发表评论或添加新答案。

现在是模板:
# new.html.erb
...
<%= form_for [@question, @answer] do |f|
<%= render 'form', f: f, parts: @answer.parts
<% end %>

# edit.html.erb
...
<%= form_for [@answer] do |f|
<%= render 'form', f: f, parts: @answer_parts || @answer.parts
<% end %>

# _form.html.erb
...
<%= f.fields_for :parts, parts do |builder| %>
<%= builder.text_field :body, label: builder.object.question_part.description, required: false
<%= builder.hidden_field :question_part_id %>
<% end %>

关于ruby-on-rails - 如何通过验证预先加载 fields_for,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24629368/

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