Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the best way to convert all controller params from camelCase to snake_case in Rails?

As you already know, JSON naming convention advocates the use of camelCase and the Rails advocates the use of snake_case for parameter names.

What is the best way to convert all request's params to snake_case in a rails controller?

From this:

{   ...   "firstName": "John",   "lastName": "Smith",   "moreInfo":   {     "mealType": 2,     "mealSize": 4,     ...   } } 

to this:

{   ...   "first_name": "John",   "last_name": "Smith",   "more_info":   {     "meal_type": 2,     "meal_size": 4,     ...   } } 
like image 698
a.s.t.r.o Avatar asked Jun 21 '13 16:06

a.s.t.r.o


People also ask

Is Ruby camel case or snake case?

General Ruby conventionsClass names are CamelCase . Methods and variables are snake_case .

What is params in Rails controller?

Specifically, params refers to the parameters being passed to the controller via a GET or POST request. In a GET request, params get passed to the controller from the URL in the user's browser.


2 Answers

When you’ve completed the steps below, camelCase param names submitted via JSON requests will be changed to snake_case.

For example, a JSON request param named passwordConfirmation would be accessed in a controller as params[:password_confirmation]

Create an initializer at config/initializers/json_param_key_transform.rb. This file is going to change the parameter parsing behaviour for JSON requests only (JSON requests must have the request header Content-Type: application/json).

Find your Rails version and choose the appropriate section below (find your Rails version in Gemfile.lock):

For Rails 5 and 6

For Rails 5 and 6, to convert camel-case param keys to snake-case, put this in the initializer:

# File: config/initializers/json_param_key_transform.rb # Transform JSON request param keys from JSON-conventional camelCase to # Rails-conventional snake_case: ActionDispatch::Request.parameter_parsers[:json] = lambda { |raw_post|   # Modified from action_dispatch/http/parameters.rb   data = ActiveSupport::JSON.decode(raw_post)    # Transform camelCase param keys to snake_case   if data.is_a?(Array)     data.map { |item| item.deep_transform_keys!(&:underscore) }   else     data.deep_transform_keys!(&:underscore)   end    # Return data   data.is_a?(Hash) ? data : { '_json': data } } 

For Rails 4.2 (and maybe earlier versions)

For Rails 4.2 (and maybe earlier versions), to convert camel-case param keys to snake-case, put this in the initializer:

# File: config/initializers/json_param_key_transform.rb # Transform JSON request param keys from JSON-conventional camelCase to # Rails-conventional snake_case: Rails.application.config.middleware.swap(   ::ActionDispatch::ParamsParser, ::ActionDispatch::ParamsParser,   ::Mime::JSON => Proc.new { |raw_post|      # Borrowed from action_dispatch/middleware/params_parser.rb except for     # data.deep_transform_keys!(&:underscore) :     data = ::ActiveSupport::JSON.decode(raw_post)     data = {:_json => data} unless data.is_a?(::Hash)     data = ::ActionDispatch::Request::Utils.deep_munge(data)          # Transform camelCase param keys to snake_case:     data.deep_transform_keys!(&:underscore)      data.with_indifferent_access   } ) 

Final step for all Rails versions

Restart rails server.

like image 163
Eliot Sykes Avatar answered Sep 23 '22 19:09

Eliot Sykes


Example with camelCase to snake_case in rails console

2.3.1 :001 > params = ActionController::Parameters.new({"firstName"=>"john", "lastName"=>"doe", "email"=>"[email protected]"}) => <ActionController::Parameters {"firstName"=>"john", "lastName"=>"doe", "email"=>"[email protected]"} permitted: false>  2.3.1 :002 > params.transform_keys(&:underscore) => <ActionController::Parameters {"first_name"=>"john", "last_name"=>"doe", "email"=>"[email protected]"} permitted: false> 

source:

http://api.rubyonrails.org/classes/ActionController/Parameters.html#method-i-transform_keys http://apidock.com/rails/String/underscore

UPDATE:

If you have nested attributes and Rails 6 you can do:

ActionController::Parameters convert to hash and then do deep transform:

params.permit!.to_h.deep_transform_keys { |key| key.to_s.underscore } params.permit!.to_h.deep_transform_values { |value| value.to_s.underscore }

Please see:

http://apidock.com/rails/v6.0.0/Hash/deep_transform_values http://apidock.com/rails/v6.0.0/Hash/deep_transform_keys

like image 43
Hubert Olender Avatar answered Sep 20 '22 19:09

Hubert Olender