I’m under the impression that manipulating the incoming params to Rails controller methods is considered something of a code smell if not an antipattern. Rationales for avoiding this include:

  • Is it really the controller’s job?
  • What about strong parameters?
  • General Hazards of mutability

I can’t do anything about the first one. However, I can readily believe that it may become necessary for Reasons. If you have to, you have to. Below the fold I’ll show a short pattern to deal with the next two.

Without further ado:

context = params.fetch(:context)
context[:subject] ||= ActionController::Parameters.new

context[:subject].merge! { 
  # ...
}

In the first line we make sure any required parent parameters exist, and assign them to a variable for convenience. If they don’t exist, fetch raises an error.

In the second line we use ||= to optionally assign a default Parameters object to the subject which may or may have been submitted.

Lastly, we mutate the subject with derived parameters as necessary (given). This mutates the underlying params object which can then be passed to #create, #update using params.require(:context).permit(:subject) as usual.

Should you do this? Perhaps not if you don’t really, really have to.

But if you do have to, this basic pattern will prevent a lot of problems and let you focus on building the parameters hash used in merge! and I think that’s pretty important.