0

I'm trying to update an object using nested fields and am receiving an Unpermitted parameters error. The field that is causing the error is in itself a relation to another table within the nested table. Below are the specifics:

Doctor class

class Doctor < User
    has_many :professional_licenses, dependent: :destroy
    has_many :states, through: :professional_licenses
    accepts_nested_attributes_for :professional_licenses, allow_destroy: true
   ...
end

Professional License class

class ProfessionalLicense < ApplicationRecord
  belongs_to :doctor
  belongs_to :state

  validates_presence_of :code
end

State class

class State < ActiveRecord::Base
  validates_presence_of :iso_abbr, :name
end

Doctor controller

...
def update
  doctor = @current_user
  params[:doctor][:professional_licenses_attributes].each do |license, index|
    license[:state] = State.find_by_iso_abbr license[:state]
  end
  doctor.update_attributes(doctor_params)
  render json: doctor, status: :ok
end
...
def doctor_params
  params.require(:doctor).permit(:email, :first_name, :last_name, :password, 
  :password_confirmation, professional_licenses_attributes: [:code, :state, :_destroy])
end

The call from the UI looks like this:

{
"doctor":{
    "first_name":"Doctor Postman",
    "professional_licenses_attributes": [
        {
            "code": "NY-1234",
            "state": "NY"
        },
        {
            "code": "MA-1234",
            "state": "MA"
        }
    ]
}
}

When I send the call, the record is being updated and the licenses created. However, the licenses get created with no state because the controller says Unpermitted parameters: state. I have tried different approaches but can't find the way to permit the state. Please help!

4

1 Answer 1

1

In your case the code parameter is expected to be a simple value such as integer or string. But you convert it into an object, which attributes also have to be added to the permitted list.

Try to pass code_id (integer) instead of code (object):

...
def update
  doctor = @current_user
  params[:doctor][:professional_licenses_attributes].each do |license|
    state = State.find_by_iso_abbr(license.delete(:state))
    license[:state_id] = state.id if state
  end
  doctor.update_attributes(doctor_params)
  render json: doctor, status: :ok
end
...
def doctor_params
  params.require(:doctor).permit(:email, :first_name, :last_name, :password, 
  :password_confirmation, professional_licenses_attributes: [:code, :state_id, :_destroy])
end
Sign up to request clarification or add additional context in comments.

4 Comments

Thanks for the response. In this case, :code is a string so I can't pass the id. I have tried to pass just :state and the object and I also get the same error as when I do :state_id
You don't have to pass ID. You pass a string and calculate the ID, based on the string. You also should remove :state from params after you convert it to state_id (I missed this when answered). I updated the answer. Now :state is removed from params after it is converted into state_id
I made the change you suggested and get the same error: "undefined method 'iso_abbr' for nil:NilClass" Here's a gist with the console output. Maybe you can see something I'm not. gist.github.com/davidflores2/ca334be415526fd1c03e874d973980c9
In the gist the code is wrong! You missed license.delete(:state) and if state Copy it from here and use properly.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.