Simple params renaming for Rails applications.
Add this line to your application's Gemfile:
gem 'rename_params'
And then execute:
$ bundle
Or install it yourself as:
$ gem install rename_params
Specify the input params that you would like to rename in your controller:
class UsersController < ApplicationController
# This will rename "username" to "login" in the params
rename :username, to: :login, only: :index
def index
@users = User.where(query_params)
end
private
def query_params
params.permit(:login, :age)
end
end
This means that for a request like the following:
GET /users?username=aperson&age=28
The params
method will now have a key called login
instead of username
within the context of the index
action:
> puts params
{ login: 'aperson', age: '28' }
If you need to rename a parameter which is nested into a certain key, you can use the
namespace
option. Just specify the nesting using an array format.
class UsersController < ApplicationController
# Renames params[:user][:username] to params[:user][:login]
rename :username, to: :login, namespace: :user, only: :create
def create
@user = User.new(user_params)
respond_to do |format|
format.html { redirect_to(@user, notice: 'User was successfully created.') }
end
end
private
def user_params
params.require(:user).permit(:login)
end
end
If the parameter you need to change is nested under more than one namespace, you can use the array syntax like this:
class UsersController < ApplicationController
# Renames params[:session][:credentials][:username] to params[:session][:credentials][:login]
rename :username, to: :login, namespace: [:session, :credentials]
end
There are cases where just renaming the parameter key won't be enough and you will want to also
transform the values that were sent. The convert
option will give you some more flexibility as to
what to do with those values.
If the request will only take a finite number of values you can use an Enum converter to define the conversion rules. This will be just a mapper in the form of a hash.
class TicketsController < ApplicationController
# Converts params[:status] value from "open"/"in_progress"/"closed" to 0/1/2
rename :status, to: :status, convert: { open: 0, in_progress: 1, closed: 2 }
end
The example above will convert the status
parameter from open
/in_progress
/closed
to 0
/1
/2
:
# If params came with { status: 'in_progress' }, then after the transformation:
> puts params
{ status: 1 }
You can also use a Proc
or a private method to convert the value to whatever makes sense by executing ruby code.
class UsersController < ApplicationController
# Converts params[:age] value into year_of_birth
rename :age, to: :year_of_birth, convert: -> (value) { Date.today.year - value }
end
Assuming Time.current
is in 2016, this will result in the following conversion:
# If params came with { age: 28 }, then after the transformation:
> puts params
{ year_of_birth: 1988 }
If you want to use private method instead of a proc, you can just declare it like this:
class UsersController < ApplicationController
rename :age, to: :year_of_birth, convert: :to_year
private
def to_year(value)
Date.today.year - value
end
end
If you need to rename more than one parameter, just specify as many rename
declarations
as you need. Normally you will want to put the rename
declarations at the top of the file, before
any before_action
in your controller.
class UsersController < ApplicationController
rename :username, to: :login, namespace: :user, only: :create
rename :age, to: :year_of_birth, convert: -> (value) { Date.today.year - value }, only: :index
end
You can think of the transformations as if they were ran in sequence in the same order they were defined. So keep this in mind if one transformation depends on a previous one.
There will be some cases where you will need to move a param from one namespace to another. For those
cases, you can use the move
macro.
class UsersController < ApplicationController
# Moves params[:username] to params[:user][:username]
move :username, to: [:user], only: :create
def create
#...
end
end
In this case, the params were sent like this:
> puts params
{ username: 'aperson' }
And they were transformed to:
> puts params
{
user: {
username: 'aperson'
}
}
You can specify deeper nesting using the array notation. Example:
class UsersController < ApplicationController
# Moves params[:street] to params[:contact][:address][:street]
move :street, to: [:contact, :address]
end
This will be renamed to:
> puts params
{
contact: {
address: {
street: '123 St.'
}
}
}
The move
option also accepts a namespace
just like rename
. If you want to move something that is not at the root
level, you can always specify the path to it using a namespace.
Let's say you have a UsersController
class UsersController < ApplicationController
# Moves params[:user][:address][:street] to params[:user][:street]
move :street, namespace: [:user, :address], to: :user
end
This will be renamed from this:
> puts params
{
user: {
address: {
street: '123 St.'
}
}
}
To this:
> puts params
{
user: {
street: '123 St.'
}
}
If you need to move a param to the root level, you can do that by using the :root
keyword:
class UsersController < ApplicationController
# Moves params[:user][:login] to params[:login]
move :login, namespace: :user, to: :root
end
Doing a request like the following:
GET `/users?user[login]=aperson`
Will rename the params to:
> puts params
{ login: 'aperson' }
If you want to rename something and move it to a different namespace, you can do that by either first calling rename
and then move
in the line below, or you can use the move_to
option within the same rename
clause.
class UsersController < ApplicationController
# Renames params[:username] to params[:user][:login]
rename :username, to: :login, move_to: :user, only: :create
def create
#...
end
end
In this case, the params were sent like
> puts params
{ username: 'aperson' }
But they were transformed to:
> puts params
{
user: {
login: 'aperson'
}
}
This is the same than doing:
class UsersController < ApplicationController
# Renames params[:username] to params[:user][:login]
rename :username, to: :login, only: :create
move :login, to: :user, only: :create
def create
#...
end
end
- Fork it ( https://github.com/cedarcode/rename_params/ )
- Create your feature branch (
git checkout -b my-new-feature
) - Commit your changes (
git commit -am 'Add some feature'
) - Push to the branch (
git push origin my-new-feature
) - Create a new Pull Request
See the Running Tests guide for details on how to run the test suite.
This project is licensed under the MIT License - see the LICENSE file for details