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
Using Rest-Client to Download a File to Disk Without Loading It All in Memory First
How to Refer a Local Gem in Ruby
Which Http Web Server How to Use to Debug Ruby Code Using Rubymine 3.0.1
Rounding a Float to the Nearest Integer in Ruby
Why Is a String Key for a Hash Frozen
Access Translation File (I18N) from Inside Rails Model
Error Nomethoderror: Undefined Method 'Debug_Rjs=' for Actionview::Base:Class
Rails Elasticsearch Aggregation
Sass: Dealing with The Ie 4095 Selectors Per Stylesheet Restriction
Rails Sitemap_Generator Uninitialized Constant
Unwanted Form Parameters Being Appended to Pagination Links
Killing Process Group from Ruby Kills My Whole Computer
Naming Conventions for Boolean Attributes
Have a Parent Class's Method Access the Subclass's Constants