加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

ruby-on-rails – 如何通过验证来急切加载fields_for

发布时间:2020-12-17 02:22:50 所属栏目:百科 来源:网络整理
导读:我的形式有这个fields_for: = f.fields_for :parts do |builder| = builder.input :body,label: builder.object.another_relation.description,required: false 在主模型中,我有这个验证: validates_associated :parts 在零件模型中,我有这个验证: valida
我的形式有这个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,required: false

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

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

解决方法

这是一种方法.

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

所以,一个问题有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',allow_destroy: true

  # ...
end

class AnswerPart
  belongs_to :answer
  belongs_to :question_part

  validates :body,presence: true

  # ...
end

我们来看看答案控制器:

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',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 %>

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读