Rails 5 ActiveRecord :: RecordInvalid(验证失败),但我没有验证

时间:2016-05-23 19:21:06

标签: ruby-on-rails activerecord

我正在尝试实现多种形式的has_many :through,但我在向数据库提交时遇到问题。我没有字段验证,这告诉我它抱怨参数哈希的结构比什么都重要。

错误是:

  

ActiveRecord :: RecordInvalid(验证失败:必须存在费用支出类别费用):

参数hash如下所示:

  

参数:{“utf8”=>“✓”,“费用”=> {“日期”=>“2006/12/12”,“金额”=>“234”,“check_number” =>“234”,“debit”=>“0”,“notes”=>“234”,“expense_expense_categories_attributes”=> {“1464029611137”=> {“amount”=>“234” ,“expense_category_id”=>“1”,“_ destroy”=>“false”}}},“commit”=>“创建费用”}

我注意到的一件事是它没有将:expense_id值添加到联结表中。这应该由accepts_nested_attributes_for机制完成,但事实并非如此。我开始认为这是Rails 5的一个问题,因为我有类似的关系和形式这样的结构,工作正常。你们看到我错过了什么吗?

这是我的控制器:

def create 

  @expense = Expense.new(expense_params)
  respond_to do |format|
    if @expense.save!
    @expenses = Expense.all.paginate(:page => params[:page], :per_page => 9).order("created_at DESC")

      format.html { redirect_to @expense, notice: 'Expense was successfully created.' }
      format.js {}
      format.json { render json: @expense, status: :created, location: @expense }
    else
      @expenses = Expense.all.paginate(:page => params[:page], :per_page => 9).order("created_at DESC")
      format.html { render action: "index" }
      format.js {}
      format.json { render json: @expense.errors, status: :unprocessable_entity }
    end
  end
end

def expense_params
  params.require(:expense).permit(:id, :date, :amount, :check_number, :debit, :notes, :amount, :expense_expense_categories_attributes => [:id, :amount, :expense_id , :expense_category_id, :_destroy])
end

以下是我的模特:

费用

class Expense < ApplicationRecord
  has_one :payee
  monetize :amount_cents
  has_many :expense_expense_categories
  has_many :expense_categories, through: :expense_expense_categories, :dependent => :destroy
  accepts_nested_attributes_for :expense_expense_categories,:allow_destroy => true

end

ExpenseCategory:

class ExpenseCategory < ApplicationRecord
  has_many :expense_expense_categories
  has_many :expenses, through: :expense_expense_categories

end

ExpenseExpenseCategory

class ExpenseExpenseCategory < ApplicationRecord
  monetize :amount_cents
  belongs_to :expense
  belongs_to :expense_category

  accepts_nested_attributes_for :expense_category
end

_form.html.erb:

<%= form_for @expense, html: { :class => "ui form segment" }, :remote => true do |f|%>

    <div class="field">

      <%= f.label :date%>
      <div class="ui small input">
      <%= f.date_field :date %>
    </div>
  </div>
  <div class="field">
    <%= f.label :amount %>
    <div class="ui small input">

      <%= f.text_field :amount %>
    </div>

  </div>

  <div class="field">
    <%= f.label :check_number %>
    <div class="ui small input">

      <%= f.text_field :check_number %>
    </div>

  </div>

  <div class="field">
    <%= f.label :debit %>
    <div class="ui small input">
      <%= f.check_box :debit %>
    </div>

  </div>

  <div class="field">
    <%= f.label :notes %>
    <div class="ui small input">
      <%= f.text_area :notes %>
    </div>

  </div>

  <%= f.fields_for :expense_expense_categories do |builders| %>
      <%= render 'expense_expense_category_fields', :f => builders %>
  <% end %>
  <%= link_to_add_fields "Add Category", f, :expense_expense_categories %>

  <%= f.submit class: "ui blue button" %>
  

expense_expense_category_fields.htnl.erb

<div class="field">
  <%=f.label :amount%>
  <%= f.text_field :amount %>
</div>
<div class="field">
  <%=f.label :category%>
  <%= f.select :expense_category_id, ExpenseCategory.all.collect { |p| [p.category, p.id] } %>
</div>
<%= f.hidden_field :_destroy %>

<%= link_to "Remove option", "#", :class => "remove_expense_expense_categories" %>

以下是提交的浏览器的表单数据:

utf8:✓
expense[date]:2016-05-12
expense[amount]:23
expense[check_number]:23
expense[debit]:0
expense[notes]:
expense[expense_expense_categories_attributes][1464030986149][amount]:23
expense[expense_expense_categories_attributes][1464030986149][expense_category_id]:1
expense[expense_expense_categories_attributes][1464030986149][_destroy]:false
expense[expense_expense_categories_attributes][1464030991099][amount]:43
expense[expense_expense_categories_attributes][1464030991099][expense_category_id]:10
expense[expense_expense_categories_attributes][1464030991099][_destroy]:false
commit:Create Expense

2 个答案:

答案 0 :(得分:1)

这是因为Rails在创建费用之前尝试创建ExpenseExpenseCategory。你必须定义; :inverse_of关于协会。

class Expense < ApplicationRecord
  has_one :payee
  monetize :amount_cents
  has_many :expense_expense_categories, inverse_of: :expense
  has_many :expense_categories, through: :expense_expense_categories, :dependent => :destroy
  accepts_nested_attributes_for :expense_expense_categories,:allow_destroy => true

end

class ExpenseCategory < ApplicationRecord
  has_many :expense_expense_categories, inverse_of: :expense_category
  has_many :expenses, through: :expense_expense_categories

end

class ExpenseExpenseCategory < ApplicationRecord
  monetize :amount_cents
  belongs_to :expense, inverse_of: :expense_expense_categories
  belongs_to :expense_category, inverse_of: :expense_expense_categories

  accepts_nested_attributes_for :expense_category
end

http://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html#module-ActiveRecord::Associations::ClassMethods-label-Setting+Inverses

答案 1 :(得分:1)

请检查此链接 https://blog.bigbinary.com/2016/02/15/rails-5-makes-belong-to-association-required-by-default.html

inverse_of对我不起作用,我必须在optional: true关联中使用belongs_to