首页 > 解决方案 > 将字符串数组转换为 StrongParameters 白名单

问题描述

我有一串像这样的字段名称"name,address.postal_code",它充当哈希的白名单,如下所示:

{
  name: "Test",
  email: "test@test.com",
  address:  {
    postal_code: "12345",
    street: "Teststreet"
  }
}

所以现在我想要将白名单字符串转换为以下格式可以接受的格式ActionController::Parameters.permit[:name, address: [:postal_code]]

最好的方法是什么?我已经尝试过group_by和其他一些事情,但结果总是比我认为需要的复杂得多。

标签: ruby-on-railsruby

解决方案


这并不理想,但它应该可以工作:

def to_strong_parameters_compatible(fields)
  fields # fields="name,address.postal_code,address.street"
    .split(',') # ["name", "address.postal_code", "address.street"]
    .group_by { |val| val.split('.').first } # { "name" => ["name"], "address" => ["address.postal_code", "address.street"]}
    .inject([]) do |params, hash|
      k = hash.first
      v = hash.last
      puts "k: #{k}"
      puts "v: #{v}"
      # 1st: k="name", v=["name"]
      # 2nd: k="address", v=["address.postal_code", "address.street"]

      if v.length == 1
        params << k
        # 1st: params=["name"]
      else
        params << { k => v.map { |chain| chain.split('.').last } }
        # 2nd: params=["name", { "address" => ["postal_code", "street"]}]
      end

      params
    end
end

fields = "name,address.postal_code,address.street"

# How you should use it:
params.permit(*to_strong_parameters_compatible(fields))

注意:它不适用于a.b.c......这样的领域你必须使这个算法递归(它应该不难)

编辑:这是递归版本

def to_strong_parameters_compatible(fields)
  fields
    .split(',')
    .group_by { |val| val.split('.').first }
    .inject([]) do |params, hash|
      k = hash.first
      v = hash.last

      if v.length == 1
        params << k
      else
        params << {
          k => to_strong_parameters_compatible(
            v
              .map { |chain| chain.split('.').drop(1).join('.') }
              .join(',')
          )
        }
      end

      params
    end
end
fields = "name,address.postal_code,address.street,address.country.code,address.country.name"
to_strong_parameters_compatible(fields)
# ["name", {"address"=>["postal_code", "street", {"country"=>["code", "name"]}]}]

# How you should use it:
params.permit(*to_strong_parameters_compatible(fields))

推荐阅读