The docs on parameter wrapping state:
Wraps the parameters hash into a nested hash. This will allow clients to submit POST requests without having to specify any root elements.
It helpfully elides which parameters hash is being wrapped. The Action Controller overview guide gives this run-down:
Rails collects all of the parameters sent along with the request in the
params
hash, whether they are sent as part of the query string or the post body. […] Thequery_parameters
hash contains parameters that were sent as part of the query string while therequest_parameters
hash contains parameters sent as part of the post body. Thepath_parameters
hash contains parameters that were recognized by the routing as being part of the path leading to this particular controller and action.
The fun happens when you use RESTful resources and routes. Say you have a model A which has_many Bs; B thus has a foreign key a_id
.
You POST /as/1/bs
with an empty payload (because B has no other fields). Assuming a_id
is attr_accessible
, one might assume that a_id
would be wrapped in a b
object. Instead you'll see:
Processing by BsController#create as HTML
Parameters: {"b"=>{}, "a_id" => "1"}
No such luck. It turns out that ParamsWrapper
uses request_parameters
and not params
, so not including a_id
in the POST payload means it doesn't get wrapped. This is pretty confusing, because you still see it included in params
, due to URI globbing, and wonder why it got excluded of all things.
Is there any good reason to use request_parameters
and not params
here?
I can understand that, from a "REST philosophy" point of view, it's more pure if we assume that the payload contains the entire object, but that essentially means that the a_id
in the URI is completely ignored, which seems a pity.
tl;dr: ParamsWrapper
uses request_parameters
as the parameter source, so URI-globbed variables are skipped. Is this a Rails bug? Pure REST advocates may say no, but pragmatism suggests yes.