Question

Validation on a model object is failing despite what I think is the correct parameter value being whitelisted in the controller and passed to the model's constructor. What am I doing wrong?

OuterModel has_one Location via locatable. The latter is created using accepts_nested_attributes_for and validates only the :country attribute:

(EDIT: I found the error, it was hidden by code that I initially left out of the code here for simplification. See my answer below)

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

Controller:

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

Using byebug I see the @outer.save call is satisfied, but the nested location object is not persisted because of a validation error:

(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"]}>

However, the controller outer_params method appears to be sending the correct hash to OuterModel.new:

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

Why then is the Location.country value nil after the call to save, and why is validation failing?

EDIT: logfile (much simplified) pastebin here. It seems like the correct values are being sent as part of the SQL

Was it helpful?

Solution

The answer lay in a parent of OuterModel that had an after_create hook to create a Location. Added the parent class to the source above.

The Location object was initially created correctly by accepts_nested_attributes_for (as per all evidence from logging) but then the after_create hook replaced it with an empty Location object that failed validation.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top