【问题标题】:Rails 5, Cocoon Gem - nested form inside nested formRails 5,Cocoon Gem - 嵌套表单内的嵌套表单
【发布时间】:2016-11-04 00:47:13
【问题描述】:

我正在尝试使用 cocoon gem 来构建嵌套表单。

我有 Organisation、Package::Bip 和 Tenor 的模型。

关联是:

组织

has_many :bips, as: :ipable, class_name: Package::Bip
    accepts_nested_attributes_for :bips,  reject_if: :all_blank, allow_destroy: true

Package::Bip(多态)

 belongs_to :ipable, :polymorphic => true, optional: true, inverse_of: :bip

  has_one :tenor, as: :tenor
    accepts_nested_attributes_for :tenor,  reject_if: :all_blank, allow_destroy: true

男高音(多态)

belongs_to :tenorable, :polymorphic => true, optional: true

表格有:

在我的组织/_form.html.erb 中,我有:

<%= f.simple_fields_for :bips do |f| %>
      <%= f.error_notification %>
        <%= render 'package/bips/bip_fields', f: f %>

    <% end %>

    <%= link_to_add_association 'Add another intellectual property resource', f, :bips, partial: 'package/bips/bip_fields' %> 

在我的 bip_fields.html.erb 嵌套表单中,我有:

<%# if @package_bips.tenor.blank? %> 
  <%= link_to_add_association 'Add timing', f, :tenor, partial: 'tenors/tenor_fields' %>  
<%# end %>

<%= f.simple_fields_for :tenor do |tenor_form| %>
  <%= f.error_notification %>
    <%= render 'tenors/tenor_fields', f: tenor_form %>
<% end %> 

Javascript

cocoon 文档建议添加一个 js 文件以将关联插入节点指定为函数。在我的 tenor_subform.js 我有:

$(document).ready(function() {
    $(".add_tenor a").
      data("association-insertion-method", 'append').
      data("association-insertion-node", function(link){
        return link.closest('.row').next('.row').find('.tenor_form')
      });
});

控制器

在我的组织控制器中,我有:

def new
    @organisation = Organisation.new
    @organisation.bips
end

注意:我不确定是否需要在新操作中添加另一行来创建 organization.bip.tenor 实例。我也不确定我是否应该通过引用男高音的 organization.rb 上的关联来添加 has_one。

def organisation_params
      params.fetch(:organisation, {}).permit(:title,  :comment,

          bips_attributes:            [:id, :status,  :_destroy,
            tenor_attributes:           [:id,:commencement, :expiry,                      :_destroy]

        ],

在我的男高音控制器中,我有:

def tenor_params
      params.require(:tenor).permit( :commencement, :expiry)
    end

错误

我不确定是否需要将男高音操作添加到组织控制器(bip 的最终父级又是男高音的父级)。

当我保存所有这些并尝试它时,我收到一条错误消息:

unknown attribute 'tenor_id' for Tenor.

当我看到其他 SO 帖子出现此错误时,通常是因为 :id 属性未在父类中列入白名单。我已经做到了。

谁能看到我做错了什么?

男高音控制器

class TenorsController < ApplicationController

  before_action :set_tenor, only: [:show, :edit, :update, :destroy]
  before_action :authenticate_user!
  # after_action :verify_authorized

  def index
    @tenors = Tenor.all
    # authorize @tenors
  end

    def show

  end

  def new
    @tenor = Tenor.new
    # authorize @tenor
  end

  def edit

  end

  def create
    @tenor = Tenor.new(tenor_params)
    # authorize @tenor

    respond_to do |format|
      if @tenor.save
        format.html { redirect_to @tenor }
        format.json { render :show, status: :created, location: @tenor }
      else
        format.html { render :new }
        format.json { render json: @tenor.errors, status: :unprocessable_entity }
      end
    end
  end

  def update
   respond_to do |format|
      if @tenor.update(tenor_params)
        format.html { redirect_to @tenor }
        format.json { render :show, status: :ok, location: @tenor }
      else
        format.html { render :edit }
        format.json { render json: @tenor.errors, status: :unprocessable_entity }
      end
    end
  end

   def destroy
    @tenor.destroy
    respond_to do |format|
      format.html { redirect_to action: :index }
      format.json { head :no_content }
    end
  end

  private
    def set_tenor
      @tenor = Tenor.find(params[:id])
      # authorize @tenor
    end

    def tenor_params
      params.require(:tenor).permit(:express_interest, :commencement, :expiry, :enduring, :repeat, :frequency)
    end

end

【问题讨论】:

  • 该错误表明您在某处指的是tenor_idTenor 对象。我们没有看到足够的代码来查看它在哪里。你的男高音应该有一个 bips_id,但既然你有一个has_one,就不应该有一个tenor_id
  • 不确定你的意思。 Tenor 是多态的,它将持有一个 bips id。我不明白这个建议。您的意思是最终父级 (organisation.rb) 也应该与 Tenor 有关联吗?
  • 我的意思是:错误表明您正在尝试分配一个男高音ID,那么您的代码/表单可能在哪里?你能告诉我们发布到控制器的内容吗?
  • 嗯 - 我在上面添加了我的男高音控制器。也许是因为我的组织控制器没有针对新男高音的新动作(通过 bip 嵌套)。例如:@organisation.bips.tenor - 移除后是否需要嵌套?
  • 你有一个带有嵌套数据的表单,不管有多深。它只发布到一个控制器:顶层(所以组织)。保存表单时,您会收到未知属性tenor_id 的错误(在哪一行?)。 Rails 没有发明要设置的数据,因此发布到控制器的数据(以及表单)都包含一个字段tenor_id,这就是为什么我要求向我们展示发布到控制器的内容(你可以找到这个在您的日志文件中)。在这种情况下,男高音控制器不相关。我会在我的代码中搜索tenor_id 并将其删除:)

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


【解决方案1】:

您的has_one 关系声明错误。因为你说as: :tenor 使它寻找tenor_id

你必须声明如下:

has_one :tenor, as: :tenorable 

【讨论】:

    【解决方案2】:

    您的模型看不到 nested_attr.Add :inverse_of =&gt; #{model} 的 id。

    例子:

    class Tenor < ActiveRecord::Base
      has_many :traps, :inverse_of => :bips
    end
    

    有关更多信息,请查看 thisthis 文档。

    【讨论】:

    • 但是 tenor.rb 是多态的,它有:belongs_to :tenorable, :polymorphic => true, optional: true
    猜你喜欢
    • 2016-04-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-10-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多