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, ... } }
General Ruby conventionsClass names are CamelCase . Methods and variables are snake_case .
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.
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, 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), 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 } )
Restart rails server
.
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With