5
1

More than 5 years have passed since last update.

Rails4でfilter_parametersのネスト

Posted at
Rails.application.config.filter_parameters += [:name]

としてしまうと正規表現が使われているので、nameという文字が入っているパラメータはすべてマスクされてしまいます。

特定の親のパラメータを持っているもののみマスクしたいとき、ありますよね?

残念ならが、Rails4ではサポートされておらず、Rails5からサポートされています。

Rails4のコードとRails5のコードを見くれべて見ます。

差分のコミットは下記の2つ
https://github.com/rails/rails/commit/33b93174f0db9783b3c6c906666923103569c6a3
https://github.com/rails/rails/commit/5bb1d4d288d019e276335465d0389fd2f5246bfd

CompiledFilterクラスの中身が少し書き換わっただけです。

ということで、Rails5のコードを下記のようにほぼコピーしてinitializersとかに書けば、

Rails.application.config.filter_parameters += ['user.name']

のように親のパラメータを指定できるようになります。

唯一の変更点は定数FILTEREDActionDispatch::Http::ParameterFilter::FILTEREDに書き換えています。

class ActionDispatch::Http::ParameterFilter::CompiledFilter
  def self.compile(filters)
    return lambda { |params| params.dup } if filters.empty?

    strings, regexps, blocks = [], [], []

    filters.each do |item|
      case item
      when Proc
        blocks << item
      when Regexp
        regexps << item
      else
        strings << Regexp.escape(item.to_s)
      end
    end

    deep_regexps, regexps = regexps.partition { |r| r.to_s.include?("\\.".freeze) }
    deep_strings, strings = strings.partition { |s| s.include?("\\.".freeze) }

    regexps << Regexp.new(strings.join('|'.freeze), true) unless strings.empty?
    deep_regexps << Regexp.new(deep_strings.join('|'.freeze), true) unless deep_strings.empty?

    new regexps, deep_regexps, blocks
   end

   attr_reader :regexps, :deep_regexps, :blocks

   def initialize(regexps, deep_regexps, blocks)
     @regexps = regexps
     @deep_regexps = deep_regexps.any? ? deep_regexps : nil
     @blocks  = blocks
   end

   def call(original_params, parents = [])
     filtered_params = {}

     original_params.each do |key, value|
       parents.push(key) if deep_regexps
       if regexps.any? { |r| key =~ r }
         value = ActionDispatch::Http::ParameterFilter::FILTERED
       elsif deep_regexps && (joined = parents.join('.')) && deep_regexps.any? { |r| joined =~ r }
         value = ActionDispatch::Http::ParameterFilter::FILTERED
       elsif value.is_a?(Hash)
         value = call(value, parents)
       elsif value.is_a?(Array)
         value = value.map { |v| v.is_a?(Hash) ? call(v, parents) : v }
       elsif blocks.any?
         key = key.dup if key.duplicable?
         value = value.dup if value.duplicable?
         blocks.each { |b| b.call(key, value) }
        end
        parents.pop if deep_regexps

        filtered_params[key] = value
      end

      filtered_params
    end
  end
end
5
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
1