Alter Rails Params Hash from Rack Middleware

Alter Rails params hash from Rack middleware

The docs for Rack::Request#params say:

Note that modifications will not be persisted in the env. Use update_param or delete_param if you want to destructively modify params.

When you use the line

request.params['portal_id'] = portal_id

you add the new parameter to the hash created for that instance of Rack::Request, but the env that is passed on to rails isn’t modified. To make the new value available further down the Rack stack use update_param as the docs suggest:

request.update_param('portal_id', portal_id)

Replace the params in the Rack middleware

Try,

request.params.clear
request.params[:new] = "hi"
p request.params

Rails/Rack: retrieving request params from within canonical_host middleware

Specify a parameter for this block

Rails.application.config.middleware.use Rack::CanonicalHost do |params|
puts "PATH_INFO #{params['PATH_INFO']}"
end

Rails params method: Why can it be accessed like a hash?

You are correct that params is a method, but here the params method returns an instance of ActionController::Parameters and we call hash accessor method #[] on it.

This is a common pattern in ruby to call methods on the returned object. Let's see it by a simple example:

def params
{
id: 101,
key: 'value',
foo: 'bar'
}
end

params[:id] # => 101
params[:foo] # => 'bar'

As you can see in the example, method params returns a hash object and we call hash accessor method #[] on the returned object.

Reference to rails params method: https://github.com/rails/rails/blob/5e1a039a1dd63ab70300a1340226eab690444cea/actionpack/lib/action_controller/metal/strong_parameters.rb#L1215-L1225

def params
@_params ||= begin
context = {
controller: self.class.name,
action: action_name,
request: request,
params: request.filtered_parameters
}
Parameters.new(request.parameters, context)
end
end

Note for ruby beginners: In ruby, we can call methods without parenthesis. So, above call is equivalent to params()[:id].

How do I access the Rack environment from within Rails?

I'm pretty sure you can use the Rack::Request object for passing request-scope variables:

# middleware:
def call(env)
request = Rack::Request.new(env) # no matter how many times you do 'new' you always get the same object
request[:foo] = 'bar'
@app.call(env)
end

# Controller:
def index
if params[:foo] == 'bar'
...
end
end

Alternatively, you can get at that "env" object directly:

# middleware:
def call(env)
env['foo'] = 'bar'
@app.call(env)
end

# controller:
def index
if request.env['foo'] == 'bar'
...
end
end

calling a controller action with argument from rack middleware

You don't want to put arguments on your action. Middleware should only interact with the request environment, not try to call into the controller directly.

You can pass the same value in the params hash:

# middleware
#
def call(env)
request = Rack::Request.new(env)
request['name'] = get_name
end

and read from the params hash in the controller:

# my_controller.rb
#
def print_name
render :text => "Hello, #{params['name']}!"
end


Related Topics



Leave a reply



Submit