Preserve is a Rails plugin which stores selected parameters in the session to make them available in subsequent requests.
Installation
Add the following line to your application's Gemfile:
gem 'preserve'
Install the gem with Bundler:
$ bundle install
Or do it manually by running:
$ gem install preserve
Usage
For the sole purpose of this example, let's assume we have a Rails application with a controller showing all parameters sent in a request.
class ParametersController < ApplicationController
def index
render json: parameters
end
private
def parameters
params.except(:controller, :action)
end
end
Routes are declared as following:
Rails.application.routes.draw do
resources :parameters, only: :index
end
Let's start the application and test its behavior using cURL.
The whole concept is based on the session, so in order for this to work the cookie engine must be enabled (hence the -c
and -b
options).
In the first request, the status
parameter is set to active
.
$ curl -c cookies http://localhost:3000/parameters?status=active
{"status":"active"}
As expected, the application returns the parameter and its value.
The next request is sent without any parameters.
$ curl -b cookies http://localhost:3000/parameters
{}
Obviously, the status
parameter is no longer available.
Now, let's call the preserve
macro inside the ParametersController
class with the parameter name as an argument.
class ParametersController < ApplicationController
preserve :status
# ...
end
Sending the same two requests again yields a different result.
$ curl -c cookies http://localhost:3000/parameters?status=active
{"status":"active"}
$ curl -b cookies http://localhost:3000/parameters
{"status":"active"}
This time, the status
parameter is still available when the second request is made, even though it wasn't sent particularly in that request.
Multiple arguments
If more than one parameter needs to be preserved within the same controller, its name can be passed as a succeeding argument to the preserve
method.
preserve :page, :per_page
Action restrictions
Limiting functionality provided by the gem to a certain set of controller actions can be achieved by applying the only
(or except
) option.
For example:
preserve :status, only: :index
The behavior is exactly the same as with an Action Controller filter.
Application-wide parameters
Parameters used across the whole application can be persisted by adding the preserve
macro to the ApplicationController
.
class ApplicationController < ActionController::Base
preserve :locale
end
In more complex scenarios, controller inheritance can be utilized to further adjust the scope.
Nested parameters
Storing a value of a nested parameter requires calling the preserve
macro with an array of consecutive keys leading to that parameter in the parameters hash (similar to the Hash#dig
method).
For example, in case of the JSON payload below:
{
"sort": {
"column": "name",
"direction": "desc"
}
}
The column
parameter can be persisted with the following line:
preserve [:sort, :column]
Default parameter value
There might be a situation where neither the parameters hash nor the session contains a parameter value.
To provide a fallback value for such a scenario, you can use the default
option.
For instance:
preserve :status, default: 'active'
Note that default values are not stored in the session, but assigned on every request instead.
Blank parameter values
Normally, when a parameter value is an empty string it is overwritten by a value stored in the session.
To change this behavior, you can use the allow_blank
option.
preserve :status, allow_blank: true
As a result, the parameter value would be restored from the session only when the parameter was not sent in a request.