嵌套表单未知属性错误

时间:2014-08-09 07:39:56

标签: ruby-on-rails

我正在尝试构建一个小费用跟踪应用。使用nested_form gem添加订单项。有一个Expense模型接受嵌套属性。物品属于费用。

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

    accepts_nested_attributes_for :items
end

项目模型:

class Item < ActiveRecord::Base
    belongs_to :expense
end

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

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

新的费用表格如下:

<%= 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>

我可以在添加嵌套属性之前节省开支。执行此操作后,每当我点击提交按钮时,我都会在ExpensesController中创建ActiveRecord :: UnknownAttributeError #create错误。看到未知属性:expense_id是很奇怪的。我在这里错过了什么吗?

2 个答案:

答案 0 :(得分:3)

嵌套表格

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

顺便说一句,查看nested_form文档,它似乎主要是为 Rails 3 设计的。当它提及attr_accessible时,它现在意味着关注strong_params(如果您当然使用Rails 4)

-

<强>构建

正如Mandeep所述,您需要确保为您的表单构建正确的ActiveRecord对象。 form_for通过获取ActiveRecord对象&amp;使用自己的属性填充各种属性等。

这就是Rails利用此功能创建持久性的错觉 - 它需要ActiveRecord&amp;以递归方式填充相同的数据

为了让fields_for起作用(这是nested_attributes的基础),您需要在动作中构建关联的ActiveRecord对象,该对象呈现{{1} (在您的情况下为form_for):

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 gem并不神奇 - 它本质上只是一个javascript插件,用于复制已在表单中呈现的nested_form元素,然后将它们附加到DOM。

它主要使用fields_for&#34;技巧&#34;超越增量child_index: Time.now.to_i isue

-

<强>属性

其次,您需要了解您接收的错误

id可以是expense_id个对象中的属性。我没有在纯Rails中看到过这个,但是items_attributes gem可能会将特定属性附加到对象或其他东西

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

  
      
  1. 检查您的参数哈希(请参阅Expense传递的位置)
  2.   
  3. 更新expense_id以允许strong_params
  4.   

我知道问题

  

数据库 - 您可能没有expense_id表格中的expense_id


<强>修正

您需要创建迁移,将items foreign_key放入expense_id表格

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

items

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

$ rails generate migration AddExpenseIDToItems

然后你只需要这样做:

add_column :expense_id, :items

这应解决您的问题

答案 1 :(得分:2)

你的控制器新动作应该是这样的

def new
  @expense = Expense.new      
  @item = @expense.items.build
end

如果你使用的是rails 4,那么则你不需要nested_form_for gem 。结帐nested forms。在您的表单中,您只需使用

即可
<%= form_for @expense do |f| %>
  // expense fields
  <%= f.fields_for @item do |e| %>
    // item fields
  <% end %>
  <%= f.submit %>
<% end %>