【问题标题】:Creating a nested two level form in Rails在 Rails 中创建嵌套的两级表单
【发布时间】:2015-07-09 17:05:08
【问题描述】:

我有一个Restaurant 模型,它有很多DishCategory,也有很多DishDishCategory。例如,Dinner 类别将是与其相关联的许多菜肴。为了帮助构建表单,我使用了cocoon gem。

我熟悉为传统的嵌套表单设置视图代码,但现在我要深入一层,我不知道如何编写以及将输入的菜肴放在哪里。我是否在部分内部为dishes 设置另一个simple_fields_for 块?按照文档,这是目前的设置方式:

模型

class Restaurant < ActiveRecord::Base
  has_many :dish_categories, dependent: :destroy
  has_many :dishes, through: :dish_categories, dependent: :destroy

  accepts_nested_attributes_for :dish_categories, :reject_if => :all_blank, :allow_destroy => true
end

class DishCategory < ActiveRecord::Base
  belongs_to :restaurant

  has_many :dishes, dependent: :destroy

  accepts_nested_attributes_for :dishes, :reject_if => :all_blank, :allow_destroy => true
end

class Dish < ActiveRecord::Base
  belongs_to :dish_category
end

餐厅表格

<%= simple_form_for(@restaurant) do |f| %>
  <%= f.error_notification %>

  <div class="form-inputs">
    <%= f.input :name %>
  </div>

  <div class="form-inputs dish-category-inputs">
    <%= f.simple_fields_for :dish_categories do |f| %>
      <%= render 'dish_category_fields', f: f %>
    <% end %>
  </div>

  <div class='add-dish-category'>
    <%= link_to_add_association 'Add a Dish Category', f, :dish_categories %>
  </div>

  <div class="form-actions">
    <%= f.button :submit %>
  </div>
<% end %>

菜品类别字段

<div class="dish-category-form nested-fields">
    <%= f.input :name %>

    <%= link_to_remove_association "Remove Category", f %>
</div>

【问题讨论】:

    标签: ruby-on-rails forms nested-forms cocoon-gem


    【解决方案1】:

    所以看起来我确实需要创建一个额外的部分。据我了解,links_to_add_association 中的第三个参数期望与您希望嵌套的表单的模型相关联。

    菜品类别字段

    <div class="dish-category-form nested-fields">
        <%= f.input :name %>
    
        <%= link_to_remove_association "Remove Category", f %>
    </div>
    
    <div class="form-inputs dish-category-inputs">
      <%= f.simple_fields_for :dishes do |f| %>
        <%= render "dish_fields", f: f %>
      <% end %>
    </div>
    
    <div class='add-dish'>
        <%= link_to_add_association "Add Dish", f, :dishes %>
    </div>
    

    菜场

    <div class="dish-category-form nested-fields">
        <%= f.input :name %>
    
        <%= link_to_remove_association "Remove Dish", f %>
    </div>
    

    注意:

    当涉及到餐厅控制器代码时,它可能会让人们在将您的参数列入白名单方面感到困惑。将dishes_attributes 放在dish_categories_attributes 中很重要,以便正确保存所有内容:

    餐厅管理员

    class RestaurantsController < ApplicationController
      ...
      private
        def restaurant_params
          params.require(:restaurant).permit(:name, dish_categories_attributes: [:id, :restaurant_id, :name, :_destroy, dishes_attributes: [:id, :dish_category_id, :name, :description, :_destroy]])
        end
    end
    

    【讨论】:

      【解决方案2】:

      是的,您需要对部分菜肴使用 simple_fields_for。并且不要忘记在 DishCategory 模型中使用 accept_nested_attributes_for :dishes。

      【讨论】:

        【解决方案3】:

        我也有同样的问题,因为我很难让 cocoon 与两个级别的 has_many 关联一起工作。就我而言,问题最终源于将茧与开拓者的改革表单对象结合使用。如果其他人遇到同样的问题,我会发布答案。

        问题(这里:https://github.com/nathanvda/cocoon/blob/master/lib/cocoon/view_helpers.rb#L95)是 cocoon 将关联对象的嵌套字段基于模型的纯实例,而不是包装在改革表单对象中的模型。 (不是批评,只是它的设计方式。)在您想要为嵌套对象的关联 on 呈现字段之前,这很好,因为嵌套属性的设置是在您的改革表单对象中定义的,不是你的模型。

        本质上,表单中的 f.object 部分是实际模型,而不是表单对象。除非模型本身配置了accept_nested_attributes,否则fields_for 不会将该属性视为nested_attributes_association,并且html 标记不会以reform-rails 可以将它们解析为正确嵌套参数的方式命名字段。

        我的解决方案是使用wrap_object 来确保记录茧使用的是包装在相关表单对象中的模型,如下所示:

        <%= link_to_add_association 'Add Supporting Image', f, :images, partial: 'web_app/report/supporting_image_fields', force_non_association_create: true, wrap_object: Proc.new {|image| Report::WebAppCreation::ImageWithoutHotspotsForm.new(image) } %>
        

        (可能有更好的方法来获取相关的改革表格,但这给出了想法)。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-05-05
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多