module InputSanitizer
  class RestrictedHash < Hash
    def initialize(allowed_keys)
      @allowed_keys = allowed_keys
      super() { |hash, key| default_for_key(key) }
    end

    def key_allowed?(key)
      @allowed_keys.include?(key)
    end

    private
    def default_for_key(key)
      key_allowed?(key) ? nil : raise_not_allowed(key)
    end

    def raise_not_allowed(key)
      msg = "Key not allowed: #{key}"
      raise KeyNotAllowedError.new(msg)
    end
  end
end

module InputSanitizer
  class RestrictedHash < Hash
    def initialize(allowed_keys)
      @allowed_keys = allowed_keys
      super() { |hash, key| default_for_key(key) }
    end

    def key_allowed?(key)
      @allowed_keys.include?(key)
    end

    def transform_keys
      return enum_for(:transform_keys) unless block_given?
      new_allowed_keys = @allowed_keys.map { |key| yield(key) }
      result = self.class.new(new_allowed_keys)
      each_key do |key|
        result[yield(key)] = self[key]
      end
      result
    end

    def transform_keys!
      return enum_for(:transform_keys!) unless block_given?
      @allowed_keys.map! { |key| yield(key) }
      keys.each do |key|
        self[yield(key)] = delete(key)
      end
      self
    end

    private
    def default_for_key(key)
      key_allowed?(key) ? nil : raise_not_allowed(key)
    end

    def raise_not_allowed(key)
      msg = "Key not allowed: #{key}"
      raise KeyNotAllowedError.new(msg)
    end
  end
end

Fix RestrictedHash for Rails 4.2
Fix RestrictedHash for Rails 4.2

In 4.2 the implementation of transform_keys (that is used by
stringify_keys for example) in ActiveSupport's hash
extension changed: rails/rails@f1bad130.
Now it tries to create a new instance of the
class of the object the stringify_keys is called on and not just
creating new class. This means that in case of RestrictedHash it tries
to call RestrictedHash#new with no attributes.

Since ActiveRecord does stringify when you do Model.create(hash)
it basically makes input_sanitizer unusable with Rails 4.2.

This commit overrides the rails extension hash methods transform_keys
and transform_keys! so that it behaves correctly.

Test case: https://gist.github.com/piotrj/25106a05881ba44d38b2
