嵌套表单未知属性错误 [英] Nested Form Unknown Attribute Error

查看:39
本文介绍了嵌套表单未知属性错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试构建一个小额费用跟踪应用.使用nested_form gem 添加行项目.有一个接受嵌套属性的费用模型.项目属于费用.

班级费用

物品模型:

class Item 

控制器创建动作动作如下:

class ExpensesController <应用控制器定义新@expense = Expense.new结尾定义创建@expense = Expense.new(expense_params)如果@expense.saveflash[:notice] = "费用报告已提交"重定向到@expense别的呈现新"结尾结尾私人的定义费用_参数params.require(:expense).permit(:department_id, :expense_type_id, :notes, items_attributes: [:id, :description, :amount, :issue_date, :_destroy])结尾结尾

新的费用表格如下所示:

<%= nested_form_for (@expense) do |f|%><% if @expense.errors.any?%><div id="error_explanation"><h2><%=pluralize(@expense.errors.count, "error") %>禁止节省的费用:<ul><% @expense.errors.full_messages.each do |msg|%><li><%=msg%></li><%结束%>

<%结束%><div类行"><div class="col-md-8"><div class="form-group"><%= f.label :department_id %><br><%= f.collection_select(:department_id, Department.all, :id, :department_name, prompt: true, class: "dropdown-menu") %>

<div class="form-group"><%= f.label :expense_type_id %><br><%= f.collection_select(:expense_type_id, ExpenseType.all, :id, :expense_name, prompt: true, class: "form-control") %>

<%= f.fields_for :items do |i|%><div class="form-group"><%= i.label :description%><%= i.text_field :description, class: "form-control" %>

<div class="form-group"><%= i.label :amount%><%= i.text_field :amount, class: "form-control" %>

<div class="form-group"><%= i.label :issue_date%><%= i.date_select :issue_date, class: "form-control" %>

<%= i.link_to_remove "删除",类:"btn btn-default" %><%结束%><div><p><%= f.link_to_add "Add Expense", :items, class: "btn btn-default" %></p></div><div class="form-group"><%= f.label :notes %><%= f.text_area :notes, class: "form-control" %>

<%= f.submit "Submit", class: "btn btn-primary" %><%结束%>

在添加嵌套属性之前,我能够节省开支.这样做之后,每当我点击提交按钮时,我都会在 ExpensesController#create 错误中收到 ActiveRecord::UnknownAttributeError.看到未知属性很奇怪:费用_id.我在这里错过了什么吗?

解决方案

嵌套表单

据我所知,nested_form gem 基本上只是创建了一个 fields_for 表单实例.如果是这种情况(或多或少必须),那么您需要考虑几个问题

顺便说一下,查看 nested_form 文档,它似乎主要是为 Rails 3 设计的.当它提到 attr_accessible 时,现在意味着专注于 strong_params(当然如果你使用 Rails 4)

--

构建

正如Mandeep 所提到的,您需要确保为您的表单构建正确的ActiveRecord 对象.form_for 通过获取一个 ActiveRecord 对象 &用自己的属性填充各种属性等.

这就是 Rails 如何用这个功能创造持久性的假象——它需要 ActiveRecord &递归填充相同的数据

为了让fields_for工作(这是nested_attributes的基础,你需要在action中build关联的ActiveRecord对象它呈现 form_for(在你的例子中是 new):

#app/controllers/expenses_controller.rb类 ExpensesController <应用控制器定义新@expense = Expense.new@expense.items.build #->fields_for 需要工作结尾结尾

请记住,nested_form gem 并不神奇——它本质上只是一个 javascript 插件,用于复制已经在表单中呈现的 fields_for 元素,然后将它们附加到DOM.

它本质上使用child_index:Time.now.to_i技巧"来克服增量idisue

--

属性

其次,您需要意识到您收到的错误

expense_id 可以是 items_attributes 对象中的一个属性.我没有在纯 Rails 中看到过这种情况,但也许 nested_form gem 将特定属性附加到对象或其他东西

无论哪种方式,我相信问题将是如何将您的 items 对象 与您的父 Expense 对象相关联.为此,我将执行以下操作:

<块引用>

  1. 检查您的 params 哈希值(查看 expense_id 的传递位置)
  2. 更新您的 strong_params 以允许 expense_id

我知道问题所在

<块引用>

DATABASE - 您可能在 items 表中没有 expense_id

<小时>

修复

您需要创建一个迁移来放置 expense_id foreign_key进入您的 items

为此,您应该打开 CMD 并执行以下操作:

$ rails 生成迁移 AddExpenseIDToItems

然后您可以将迁移更改为具有以下行:

add_column :expense_id, :items

然后你只需要:

$ rake db:migrate

这应该可以解决您的问题

I'm trying to build a small expense tracking app. Using the nested_form gem to add line items. There is an Expense model which accepts nested attributes. Items belong to expenses.

class Expense < ActiveRecord::Base
    belongs_to :organization
    belongs_to :department
    has_many :expense_types
    has_many :items

    accepts_nested_attributes_for :items
end

The items model:

class Item < ActiveRecord::Base
    belongs_to :expense
end

The controller create action action looks like:

class ExpensesController < ApplicationController
    def new
        @expense = Expense.new
    end
    def create
            @expense = Expense.new(expense_params)
            if @expense.save
                flash[:notice] = "Expense Report Submitted"
                redirect_to @expense
            else
                render 'new'
            end
        end

        private
        def expense_params
            params.require(:expense).permit(:department_id, :expense_type_id, :notes, items_attributes: [:id, :description, :amount, :issue_date, :_destroy])
        end
    end

The new expense form looks like:

<%= nested_form_for (@expense) do |f| %>    
    <% if @expense.errors.any? %>
      <div id="error_explanation">
        <h2><%= pluralize(@expense.errors.count, "error") %> prohibited
          this expense from being saved:</h2>
        <ul>
        <% @expense.errors.full_messages.each do |msg| %>
          <li><%= msg %></li>
        <% end %>
        </ul>
      </div>
    <% end %>
    <div class"row">
        <div class="col-md-8">
            <div class="form-group">
                <%= f.label :department_id %><br>
                <%= f.collection_select(:department_id, Department.all, :id, :department_name, prompt: true, class: "dropdown-menu") %>
            </div>
            <div class="form-group">
                <%= f.label :expense_type_id %><br>
                <%= f.collection_select(:expense_type_id, ExpenseType.all, :id, :expense_name, prompt: true, class: "form-control")  %>
            </div>
            <%= f.fields_for :items do |i| %>
                <div class="form-group">
                    <%= i.label :description%>
                    <%= i.text_field :description, class: "form-control" %>
                </div>
                <div class="form-group">
                    <%= i.label :amount%>
                    <%= i.text_field :amount, class: "form-control" %>
                </div>
                <div class="form-group">
                    <%= i.label :issue_date%>
                    <%= i.date_select :issue_date, class: "form-control" %>
                </div>
                <%= i.link_to_remove "Remove", class: "btn btn-default" %>
            <% end %>
            <div><p><%= f.link_to_add "Add Expense", :items, class: "btn btn-default" %></p></div>
            <div class="form-group">
                <%= f.label :notes %>
              <%= f.text_area :notes, class: "form-control" %>
            </div>
            <%= f.submit "Submit", class: "btn btn-primary" %>
          <% end %>
        </div>
    </div>

I was able to save expenses before adding the nested attributes. After doing that, whenever I hit the submit button, I get the ActiveRecord::UnknownAttributeError in ExpensesController#create error. It's weird to see unknown attribute: expense_id. Did I miss something here?

解决方案

Nested Form

To the best of my knowledge, the nested_form gem basically just creates a fields_for instance for your form. If this is the case (it more or less has to be), then you've got several issues you need to consider

By the way, looking at the nested_form documentation, it seems it was primarily designed for Rails 3. When it mentioned about attr_accessible, it now means to focus on strong_params (if you're using Rails 4 of course)

--

Build

As mentioned by Mandeep, you need to ensure you're building the correct ActiveRecord objects for your form. form_for works by taking an ActiveRecord object & populating the various attributes etc with its own attributes.

This is how Rails creates the illusion of persistence with this functionality -- it takes the ActiveRecord & populates the same data recursively

In order to get fields_for to work (which is the basis of nested_attributes, you need to build the associative ActiveRecord object in the action which renders the form_for (in your case new):

#app/controllers/expenses_controller.rb
Class ExpensesController < ApplicationController
   def new
      @expense = Expense.new
      @expense.items.build #-> required for fields_for to work
   end
end

Remember, the nested_form gem is not magic - it is essentially just a javascript plugin to replicate the fields_for elements rendered in your form already, and then append them to the DOM.

It essentially uses the child_index: Time.now.to_i "trick" to surmount the incremental id isue

--

Attributes

Secondly, you need to appreciate the error you're receiving

expense_id could be an attribute in the items_attributes objects. I've not seen this with pure Rails, but perhaps the nested_form gem appends a particular attribute to the objects or something

Either way, I believe the problem will be how to associate your items objects with your parent Expense object. To do this, I would do the following:

  1. Check your params hash (see where expense_id is being passed)
  2. Update your strong_params to allow the expense_id

I KNOW THE PROBLEM

DATABASE - you likely don't have the expense_id column in the items table


Fix

You need to create a migration to put the expense_id foreign_key into your items table

To do this, you should open your CMD and perform the following:

$ rails generate migration AddExpenseIDToItems

Then you can change the migration to have the following line:

add_column :expense_id, :items

Then you just need to do:

$ rake db:migrate

This should resolve your issue

这篇关于嵌套表单未知属性错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆