尽管传递给构造函数的值正确,但是nil值达到ActiveRecord验证

时间:2014-05-05 15:57:15

标签: ruby validation activerecord ruby-on-rails-4

对模型对象的验证失败,尽管我认为正确的参数值在控制器中列入白名单并传递给模型的构造函数。我做错了什么?

OuterModel has_one Location通过locatable。后者是使用accepts_nested_attributes_for创建的,仅验证:country属性:

(编辑:我发现了错误,它被代码隐藏了,我最初在代码中省略了这些以简化。请参阅下面的答案)

class OuterModel < Parent
  has_one :location, as: locatable
  accepts_nested_attributes_for :location
end

class Parent < ActiveRecord::Base
  after_create :create_location
end

class Location < ActiveRecord::Base
  belongs_to :locatable, polymorphic: true
  validates :country, inclusion: {in: ["US", "CA"]}
end

控制器:

class OuterModelsController < ApplicationController
  def create
    @outer = OuterModel.new(outer_params)
    if @outer.save 
      byebug #debug here
      redirect_to outer_path(@outer)
    end
  end

  def outer_params
    params.require(:outer).permit(:name, :type, 
      location_attributes: [:country, :state, :city])
  end
end

使用byebug我看到@outer.save调用已满足,但由于验证错误,嵌套的位置对象未被保留:

(byebug) @outer.persisted? #true
(byebug) @outer.location.persisted? #false
(byebug) @outer.location.valid? #false
(byebug) @outer.location.country #nil
(byebug) @outer.id #6372
(byebug) @outer.location.errors
<ActiveModel::Errors:0x007f1f33c1eae0 
  @base=#<Location id: nil, city: nil, country: nil, state: nil, locatable_id: 6732, locatable_type: "OuterModel", created_at: nil, updated_at: nil>, 
  @messages={:country=>["is not included in the list"]}>

但是,控制器outer_params方法似乎正在向OuterModel.new发送正确的哈希:

{"name"=>"A name",
 "type"=>"OuterModel", 
 "location_attributes"=>{
    "city"=>"South Deionview", "country"=>"US", "state"=>"IL"
 }
}

为什么调用save之后Location.country值为nil,为什么验证失败?

编辑:logfile(简化)pastebin here。似乎正确的值是作为SQL

的一部分发送的

1 个答案:

答案 0 :(得分:0)

答案在于OuterModel的父级,它具有after_create钩子来创建位置。将父类添加到上面的源中。

最初由accepts_nested_attributes_for正确创建了Location对象(根据日志记录中的所有证据),但是after_create挂钩将其替换为验证失败的空Location对象。