首页 > 解决方案 > 错误验证时Rails渲染嵌套属性不显示字段

问题描述

我有一个完全可用的嵌套属性表单。但我的问题是,当验证失败时,渲染后不会显示嵌套的表单字段:

首先

在此处输入图像描述

验证失败后,Location name消失Bin name

在此处输入图像描述

在模型中:

accepts_nested_attributes_for :location, reject_if: proc { |l| l[:name].blank? }

部分的_form.html.erb

<%= form_with(model: inventory_item, local: true) do |form| %>
  <% if inventory_item.errors.any? %>
    <div id="error_explanation">
      <h2><%= pluralize(inventory_item.errors.count, "error") %> prohibited this inventory_item from being saved:</h2>

      <ul>
        <% inventory_item.errors.each do |error| %>
          <li><%= error.full_message %></li>
        <% end %>
      </ul>
    </div>
  <% end %>

  <%= form.fields_for :location do |location| %>
    <div class="field">
      <%= location.label :location_name %>
      <%= location.text_field :name %>
    </div>
      <%= location.fields_for :bins do |bin| %>
        <div class="field">
          <%= bin.label :bin_name %>
          <%= bin.text_field :name %>
        </div>
      <% end %>
  <% end %>

  <div class="actions">
    <%= form.submit %>
  </div>
<% end %>

控制器:

  def new
    @inventory_item = InventoryItem.new
    @inventory_item.build_location.bins.build
  end

  def create
    @inventory_item = InventoryItem.new(inventory_item_params)

    respond_to do |format|
      if @inventory_item.save
        format.html { redirect_to @inventory_item, notice: "Inventory item was successfully created." }
        format.json { render :show, status: :created, location: @inventory_item }
      else
        format.html { render :new, status: :unprocessable_entity }
        format.json { render json: @inventory_item.errors, status: :unprocessable_entity }
      end
    end
  end

def inventory_item_params
  params.require(:inventory_item).permit(:location_id, :bin_id, location_attributes:[:name, bins_attributes:[:name]])
end

提前致谢

标签: ruby-on-railsruby

解决方案


问题是您的@inventory_item对象没有location关联的对象。调用新操作时,您可以像这样构建位置对象:

@inventory_item.build_location.bins.build

因此,当出现错误时,您必须对创建操作执行类似的操作。你可以这样做:

  def new
    @inventory_item = InventoryItem.new
    build_location
  end

  def create
    @inventory_item = InventoryItem.new(inventory_item_params)

    respond_to do |format|
      if @inventory_item.save
        format.html { redirect_to @inventory_item, notice: "Inventory item was successfully created." }
        format.json { render :show, status: :created, location: @inventory_item }
      else
        build_location #<----- call the method here and if the location doesn't exist then build a new object
        format.html { render :new, status: :unprocessable_entity }
        format.json { render json: @inventory_item.errors, status: :unprocessable_entity }
      end
    end
  end

  def build_location
    return if @inventory_item.location.present?

    @inventory_item.build_location.bins.build
  end

推荐阅读