Unexpected token when sending nested params to worker – Rails 6

I have a Sidekiq worker to which I send my controller params. My controller params look like this.

def my_params
  params.require(:users).permit(employees: [:param1, param_requested_attributes: [:attribute]])
end

So when I send my JSON to the controller and check with byebug, params are correctly formatted, but when I send them to the worker like:

MyWorker.perform_async(my_params)

I iterate over each “employee” as:

my_params.each do |employee|
  data = JSON.parse(raw_data.gsub('=>', ':')) # to correctly format my json data
end

and I get an “unexpected token error” because ‘params_requested_attributes’ looks like:

"params_requested_attributes"=>[<ActionController::Parameters> {"attribute"=>"value"} permitted: true> ]

My question is, how can I avoid this “ActionController::parameters” when trying to JSON.parse my params? It only happens when I try to use these nested_attributes. I just want a raw json, but for some reason I get this “action controller params”.

Answer

Your problem is that my_params:

def my_params
  params.require(:users).permit(...)
end

gives you an instance of ActionController::Parameters and the params_requested_attributes inside that is another instance of ActionController::Parameters. Then you enqueue a job with:

MyWorker.perform_async(my_params)

which has to serialize my_params into a database and that serialization isn’t handling the inner ActionController::Parameters the way you want it to.

You could convert the parameters to a nested hash yourself:

MyWorker.perform_async(my_params.to_h)

to get rid of the the ActionController::Parameters and end up with plain hashes and arrays in your job.

If you really want JSON that your job manually unpacks then you’ll have to massage my_params a little more. Perhaps you’d want to my_params.to_h and then JSON encode then nested params_requested_attributes. This sounds like a solution in search of a problem, I think passing my_params.to_h to the job is where you want to go.