Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/json/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/xcode/7.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ruby on rails 在Rails中将所有控制器参数从camelCase转换为snake_case的最佳方法是什么?_Ruby On Rails_Json - Fatal编程技术网

Ruby on rails 在Rails中将所有控制器参数从camelCase转换为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

正如您已经知道的,JSON命名约定提倡使用camelSpace,Rails提倡使用snake_case作为参数名

在rails控制器中,将所有请求的参数转换为snake_case的最佳方法是什么

由此:

{
  ...
  "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