Rails: request parameter by post parameter

Suppose you have a url

localhost:3000?a=1 

and in the request you also have the post parameter

 a=2 

What will happen

params[:a] in this case? depends on the HTTP verb?

If it depends on the HTTP verb,

what if your form looks like

 <form method='post' action='/?a=2'> <input type='hidden' name='a' value='3'/> </form> 

what would params[:a] in this case?

UPDATE

So, I just did a little experiment and used Chrome Debugger to add the ?authenticity_token=abc action url. I looked at the server log and I saw that the parameters have authenticity_token => 'abc' . I also believe that in this case the POST method.

Let me know what you guys came up with.

+8
ruby-on-rails ruby-on-rails-3
source share
4 answers

When I tried this in the sample code, what I was able to see is that the request parameters (GET) have priority over the POST body. So, I switched to Rack code that handles HTTP requests in Rails. Here is the code from request.rb

 # Returns the data recieved in the query string. def GET .... end # Returns the data recieved in the request body. # # This method support both application/x-www-form-urlencoded and # multipart/form-data. def POST .... end # The union of GET and POST data. def params @params ||= self.GET.merge(self.POST) rescue EOFError self.GET end 

Here is the method

  • GET - returns request parameters in a hash format
  • POST - returns the message body in a hash format

So, according to the code for params , GET parameters should be overridden by POST parameters in case of identical keys. ( self.GET.merge(self.POST) ). But this is contrary to what I got when I tried it in practice.

So, the only chance that this code is overridden by Rails. When I thought about this, it made sense, since the params hash from Rails will always contain the keys "controller" and "action" , which will be absent in the case of Rack. So, I also looked at the Rails code and found that the params method is really overridden. See request.rb and parameters.rb in Rails source code. In parameters.rb we have:

  # Returns both GET and POST \parameters in a single hash. def parameters @env["action_dispatch.request.parameters"] ||= begin params = request_parameters.merge(query_parameters) params.merge!(path_parameters) encode_params(params).with_indifferent_access end end alias :params :parameters 

and request.rb :

 # Override Rack GET method to support indifferent access def GET @env["action_dispatch.request.query_parameters"] ||= (normalize_parameters(super) || {}) end alias :query_parameters :GET # Override Rack POST method to support indifferent access def POST @env["action_dispatch.request.request_parameters"] ||= (normalize_parameters(super) || {}) end alias :request_parameters :POST 

So here

  • query_parameters - GET alias
  • request_parameters - POST method alias
  • path_parameters - a method that returns the controller and action for the request as a hash Parameters
  • - Alias โ€‹โ€‹for params (it was redefined here)

Note that the GET method and the POST method have also been overridden, mainly to convert the hash returned to the HashWithIndifferentAccess object.

So, looking at the code here ( params = request_parameters.merge(query_parameters) ), it becomes obvious that the POST parameters are overridden by the GET parameters in case of identical keys in Rails. Or, in other words, GET parameters take precedence over POST parameters.

+18
source share

Rails uses Rack::Request for HTTP requests. However, it overrides the Rack params method in ActionDispatch::Http::Parameters (via an alias).

This params method, which returns query parameters, is implemented as:

  # Returns both GET and POST \parameters in a single hash. def parameters @env["action_dispatch.request.parameters"] ||= begin params = request_parameters.merge(query_parameters) params.merge!(path_parameters) encode_params(params).with_indifferent_access end end alias :params :parameters 

Pay attention to the method with the alias parameters .

If not overridden, the parameters from the query string will overwrite the parameters from the POST body.

+6
source share

It will be 2. But for routing, it will match "1".

If you want, you can use request.GET and request.POST to access the get and post windows.

+1
source share

No, it does not depend on the HTTP verb, but you can have different actions for processing GET and POST , or it can be the same and you will get `params [: a] in both cases.

+1
source share

All Articles