Ruby on rails 在Rails中将所有控制器参数从camelCase转换为snake_case的最佳方法是什么?
正如您已经知道的,JSON命名约定提倡使用camelSpace,Rails提倡使用snake_case作为参数名 在rails控制器中,将所有请求的参数转换为snake_case的最佳方法是什么 由此:Ruby on rails 在Rails中将所有控制器参数从camelCase转换为snake_case的最佳方法是什么?,ruby-on-rails,json,Ruby On Rails,Json,正如您已经知道的,JSON命名约定提倡使用camelSpace,Rails提倡使用snake_case作为参数名 在rails控制器中,将所有请求的参数转换为snake_case的最佳方法是什么 由此: { ... "firstName": "John", "lastName": "Smith", "moreInfo": { "mealType": 2, "mealSize": 4, ... } } 为此: { ... "first_na
{
...
"firstName": "John",
"lastName": "Smith",
"moreInfo":
{
"mealType": 2,
"mealSize": 4,
...
}
}
为此:
{
...
"first_name": "John",
"last_name": "Smith",
"more_info":
{
"meal_type": 2,
"meal_size": 4,
...
}
}
谢谢您可以创建在任何控制器调用之前运行的筛选器,并对其应用以下说明:
# transform camel case string into snake case
snake_string = Proc.new {|s| s.gsub(/([a-z])([A-Z])/) {|t| "#{$1}_#{$2.downcase}"}}
# transform all hash keys into snake case
snake_hash = Proc.new do |hash|
hash.inject({}) do |memo, item|
key, value = item
key = case key
when String
snake_string.call(key)
when Symbol
snake_string.call(key.to_s).to_sym
else
key
end
memo[key] = value.instance_of?(Hash) ? snake_hash.call(value) : value
memo
end
end
params = snake_hash.call(params)
你必须考虑到上面的程序会在每个轨道上调用一个小的开销。p>
我不认为这是必要的,如果这只是为了适应一个惯例。tlewin的回答在Rails 3中对我不起作用。似乎params'=运算符使将来对它的操作无效。很奇怪。无论如何,以下操作对我来说是有效的,因为它只使用[]=和delete操作符:
before_filter :underscore_param_keys
def underscore_param_keys
snake_hash = ->(hash) {
# copying the hash for iteration so we are not altering and iterating over the same object
hash.to_a.each do |key, value|
hash.delete key
hash[key.to_s.underscore] = value
snake_hash.call(value) if value.is_a? Hash
value.each { |item| snake_hash.call(item) if item.is_a? Hash } if value.is_a? Array
end
}
snake_hash.call(params)
end
ActiveSupport已经提供了一个String#snakecase方法。您所要做的就是安装一个过滤器,通过params散列进行深度迭代,并用
key.snakecase
替换密钥
before_filter :deep_snake_case_params!
def deep_snake_case_params!(val = params)
case val
when Array
val.map {|v| deep_snake_case_params! v }
when Hash
val.keys.each do |k, v = val[k]|
val.delete k
val[k.snakecase] = deep_snake_case_params!(v)
end
val
else
val
end
end
我想使用Chris Healds版本,但因为我使用的是Rails 4,所以启用了强_参数,所以我不得不对其进行一些修改 这是我提出的版本:
before_filter :deep_underscore_params!
def deep_underscore_params!(val = request.parameters)
case val
when Array
val.map { |v| deep_underscore_params!(v) }
when Hash
val.keys.each do |k, v = val[k]|
val.delete k
val[k.underscore] = deep_underscore_params!(v)
end
params = val
else
val
end
end
结合Sebastian Hoitz的答案,我可以让它在rails 4.2上工作,强大的参数和使用标记方法包装的参数 我无法在过滤之前使用
,这可能是因为参数包装是在过滤之前完成的
在config/initializers/wrap_parameters.rb
中:
# Convert json parameters, sent from Javascript UI, from camelCase to snake_case.
# This bridges the gap between javascript and ruby naming conventions.
module ActionController
module ParamsNormalizer
extend ActiveSupport::Concern
def process_action(*args)
deep_underscore_params!(request.parameters)
super
end
private
def deep_underscore_params!(val)
case val
when Array
val.map {|v| deep_underscore_params! v }
when Hash
val.keys.each do |k, v = val[k]|
val.delete k
val[k.underscore] = deep_underscore_params!(v)
end
val
else
val
end
end
end
end
# Enable parameter wrapping for JSON. You can disable this by setting :format to an empty array.
ActiveSupport.on_load(:action_controller) do
wrap_parameters format: [:json] if respond_to?(:wrap_parameters)
# Include the above defined concern
include ::ActionController::ParamsNormalizer
end
完成以下步骤后,通过JSON请求提交的camelCase
param name将更改为snake\u case
before_filter :deep_snake_case_params!
def deep_snake_case_params!(val = params)
case val
when Array
val.map {|v| deep_snake_case_params! v }
when Hash
val.keys.each do |k, v = val[k]|
val.delete k
val[k.snakecase] = deep_snake_case_params!(v)
end
val
else
val
end
end
例如,名为passwordConfirmation
的JSON请求参数将作为params[:password\u confirmation]
在控制器中访问
在config/initializers/json\u param\u key\u transform.rb
中创建一个初始值设定项。此文件将仅更改JSON请求的参数解析行为(JSON请求必须具有请求头内容类型:application/JSON
)
找到您的Rails版本并选择下面相应的部分(在Gemfile.lock中找到您的Rails版本)
:
对于轨道5和6
对于Rails 5和6,要将camel-case参数键转换为snake-case,请将其放入初始值设定项:
#文件:config/initializers/json_param_key_transform.rb
#将JSON请求参数键从JSON转换为
#轨道常规蛇形外壳:
ActionDispatch::Request.parameter_解析器[:json]=lambda{| raw_post|
#修改自action\u dispatch/http/parameters.rb
data=ActiveSupport::JSON.decode(原始发布)
#将camelCase参数键转换为snake_case
if data.is_是?(数组)
data.map{| item | item.deep_transform_keys!(&:下划线)}
其他的
data.deep_transform_key!(&:下划线)
结束
#返回数据
data.is_a?(散列)?数据:{''u json':data}
}
对于Rails 4.2(可能还有更早的版本)
对于Rails 4.2(或者更早的版本),要将camel-case参数键转换为snake-case,请将其放入初始值设定项:
#文件:config/initializers/json_param_key_transform.rb
#将JSON请求参数键从JSON转换为
#轨道常规蛇形外壳:
Rails.application.config.middleware.swap(
::ActionDispatch::ParamsParser,::ActionDispatch::ParamsParser,
::Mime::JSON=>Proc.new{| raw_post|
#借用自action_dispatch/middleware/params_parser.rb,除了
#data.deep_transform_key!(&:下划线):
data=::ActiveSupport::JSON.decode(原始发布)
data={:_json=>data}除非data.is_a?(::Hash)
data=::ActionDispatch::Request::Utils.deep_munge(数据)
#将camelCase参数键转换为snake_大小写:
data.deep_transform_key!(&:下划线)
数据。与\u无关\u访问
}
)
所有Rails版本的最后一步
在rails控制台中重新启动rails服务器带有camelCase to snake_case的示例
2.3.1 :001 > params = ActionController::Parameters.new({"firstName"=>"john", "lastName"=>"doe", "email"=>"john@doe.com"})
=> <ActionController::Parameters {"firstName"=>"john", "lastName"=>"doe", "email"=>"john@doe.com"} permitted: false>
2.3.1 :002 > params.transform_keys(&:underscore)
=> <ActionController::Parameters {"first_name"=>"john", "last_name"=>"doe", "email"=>"john@doe.com"} permitted: false>
2.3.1:001>params=ActionController::Parameters.new({“firstName”=>“john”,“lastName”=>“doe”,“email”=>)john@doe.com"})
=>
更新:
如果您有嵌套属性和Rails 6,则可以执行以下操作:
ActionController::参数转换为哈希,然后进行深度转换:
params.permit!。to_h.deep_transform_keys{| key | key.to_s.underline}
params.permit!。to_h.deep_transform_values{| value | value.to_s.下划线}
请参阅:
Rails 5的解决方案
before_action :underscore_params!
def underscore_params!
underscore_hash = -> (hash) do
hash.transform_keys!(&:underscore)
hash.each do |key, value|
if value.is_a?(ActionController::Parameters)
underscore_hash.call(value)
elsif value.is_a?(Array)
value.each do |item|
next unless item.is_a?(ActionController::Parameters)
underscore_hash.call(item)
end
end
end
end
underscore_hash.call(params)
end
我们正在将Rails API JSON密钥从snake_案例转换为camelCase。我们必须以增量方式进行转换,即一些API使用snake_案例,而其他API使用camelCase
我们的解决办法是
- 创建方法
ActionController::Parameters\deep\u snakize
- 创建方法
ApplicationController\snakize\u参数
- 仅为使用camelCase键处理传入请求的控制器操作设置
before_action:snakize_params
您可以尝试一个完全工作的Rails应用程序示例
# File: config/initializers/params_snakeizer.rb
# Transform JSON request param keys from JSON-conventional camelCase to
# Rails-conventional snake_case
module ActionController
# Modified from action_controller/metal/strong_parameters.rb
class Parameters
def deep_snakeize!
@parameters.deep_transform_keys!(&:underscore)
self
end
end
end
# File: app/controllers/application_controller.rb
class ApplicationController < ActionController::API
protected
# Snakeize JSON API request params
def snakeize_params
params.deep_snakeize!
end
end
class UsersController < ApplicationController
before_action :snakeize_params, only: [:create]
# POST /users
def create
@user = User.new(user_params)
if @user.save
render :show, status: :created, location: @user
else
render json: @user.errors, status: :unprocessable_entity
end
end
end
#文件:config/initializers/params_snakeizer.rb
#将JSON请求参数键从JSON转换为
#铁轨普通蛇壳
模块动作控制器
#修改自action_controller/metal/strong_parameters.rb
类参数
def deep_snakeze!
@parameters.deep\u transform\u键!(&:下划线)
自己
结束
结束
结束
#文件:app/controllers/application_controller.rb
类ApplicationControllerclass ApplicationController < ActionController::API
include ControllerHelper
before_action :deep_underscore_params!
def deep_underscore_params!(app_params = params)
app_params.transform_keys!(&:underscore)
app_params.each do |key, value|
deep_underscore_params!(value) if value.instance_of?(ActionController::Parameters)
end
app_params.reject! { |k, v| v.blank? }
end
end
# 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] = (
# Compose the original parser with a transformation
ActionDispatch::Request.parameter_parsers[:json] >>
# Transform camelCase param keys to snake_case
->(data) {
data.deep_transform_keys(&:underscore)
}
)
module UnderscoreizeParams
extend ActiveSupport::Concern
def process_action(*args)
request.parameters.deep_transform_keys!(&:underscore)
super
end
end
class V3::BaseController
include UnderscoreizeParams
end