跳至内容 跳至搜索

Action Controller Parameters

允许您选择哪些属性应该被允许进行批量更新,从而防止意外暴露不应该暴露的内容。

提供用于过滤和要求参数的方法

  • expect 以安全的方式允许和要求参数,一步到位。

  • permit 过滤用于批量赋值的参数。

  • require 要求一个参数或抛出一个错误。

示例

params = ActionController::Parameters.new({
  person: {
    name: "Francesco",
    age:  22,
    role: "admin"
  }
})

permitted = params.expect(person: [:name, :age])
permitted # => #<ActionController::Parameters {"name"=>"Francesco", "age"=>22} permitted: true>

Person.first.update!(permitted)
# => #<Person id: 1, name: "Francesco", age: 22, role: "user">

Parameters 提供了两个选项来控制新实例的顶级行为

  • permit_all_parameters - 如果它为 true,默认情况下所有参数都将被允许。默认值为 false

  • action_on_unpermitted_parameters - 控制在找到未明确允许的参数时的行为。默认值为测试和开发环境中的 :log,其他环境中的 false。这些值可以是

    • false 不采取任何行动。

    • :logunpermitted_parameters.action_controller 主题上发出 ActiveSupport::Notifications.instrument 事件,并在 DEBUG 级别记录。

    • :raise 抛出 ActionController::UnpermittedParameters 异常。

示例

params = ActionController::Parameters.new
params.permitted? # => false

ActionController::Parameters.permit_all_parameters = true

params = ActionController::Parameters.new
params.permitted? # => true

params = ActionController::Parameters.new(a: "123", b: "456")
params.permit(:c)
# => #<ActionController::Parameters {} permitted: true>

ActionController::Parameters.action_on_unpermitted_parameters = :raise

params = ActionController::Parameters.new(a: "123", b: "456")
params.permit(:c)
# => ActionController::UnpermittedParameters: found unpermitted keys: a, b

请注意,这些选项不是线程安全的。在多线程环境中,它们应该只在启动时设置一次,并且永远不要在运行时修改。

您可以使用 :key"key" 获取 ActionController::Parameters 的值。

params = ActionController::Parameters.new(key: "value")
params[:key]  # => "value"
params["key"] # => "value"
方法
#
A
C
D
E
F
H
I
K
M
N
P
R
S
T
V
W

常量

PERMITTED_SCALAR_TYPES = [ String, Symbol, NilClass, Numeric, TrueClass, FalseClass, Date, Time, # DateTimes are Dates, we document the type but avoid the redundant check. StringIO, IO, ActionDispatch::Http::UploadedFile, Rack::Test::UploadedFile, ]
 

— 过滤 ———————————————————-

这是一个允许的标量类型列表,其中包括 XML 和 JSON 请求中支持的类型。

此列表特别用于过滤普通请求,String 作为第一个元素,以便快速地进行短路处理常见情况。

如果您修改了此集合,请更新 permit 文档中的集合。

属性

[R] parameters
[W] permitted

类公有方法

new(parameters = {}, logging_context = {})

返回一个新的 ActionController::Parameters 实例。此外,将 permitted 属性设置为 ActionController::Parameters.permit_all_parameters 的默认值。

class Person < ActiveRecord::Base
end

params = ActionController::Parameters.new(name: "Francesco")
params.permitted?  # => false
Person.new(params) # => ActiveModel::ForbiddenAttributesError

ActionController::Parameters.permit_all_parameters = true

params = ActionController::Parameters.new(name: "Francesco")
params.permitted?  # => true
Person.new(params) # => #<Person id: nil, name: "Francesco">
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 287
def initialize(parameters = {}, logging_context = {})
  parameters.each_key do |key|
    unless key.is_a?(String) || key.is_a?(Symbol)
      raise InvalidParameterKey, "all keys must be Strings or Symbols, got: #{key.class}"
    end
  end

  @parameters = parameters.with_indifferent_access
  @logging_context = logging_context
  @permitted = self.class.permit_all_parameters
end

实例公有方法

==(other)

如果另一个 Parameters 对象包含相同的内容和允许标志,则返回 true。

# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 301
def ==(other)
  if other.respond_to?(:permitted?)
    permitted? == other.permitted? && parameters == other.parameters
  else
    super
  end
end

[](key)

返回给定 key 的参数。如果未找到,则返回 nil

params = ActionController::Parameters.new(person: { name: "Francesco" })
params[:person] # => #<ActionController::Parameters {"name"=>"Francesco"} permitted: false>
params[:none]   # => nil
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 797
def [](key)
  convert_hashes_to_parameters(key, @parameters[key])
end

[]=(key, value)

为给定的 key 分配一个值。当调用 permit 时,给定的键可能仍然被过滤掉。

# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 803
def []=(key, value)
  @parameters[key] = value
end

as_json(options=nil)

返回一个哈希,可以用作参数的 JSON 表示。

# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 194
    

compact()

返回一个新的 ActionController::Parameters 实例,其中去除了 nil 值。

# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 974
def compact
  new_instance_with_inherited_permitted_status(@parameters.compact)
end

compact!()

就地移除所有 nil 值,并返回 self,如果未进行任何更改,则返回 nil

# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 980
def compact!
  self if @parameters.compact!
end

compact_blank()

返回一个新的 ActionController::Parameters 实例,其中去除了空白值。使用 Object#blank? 来确定一个值是否为空。

# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 986
def compact_blank
  reject { |_k, v| v.blank? }
end

compact_blank!()

就地移除所有空白值,并返回 self。使用 Object#blank? 来确定一个值是否为空。

# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 992
def compact_blank!
  reject! { |_k, v| v.blank? }
end

converted_arrays()

属性,跟踪已转换的数组(如果有),以避免在常见的 permit + 批量赋值用例中进行双重循环。在方法中定义,以便仅在需要时实例化它。

Testing 成员资格仍然会循环,但它比我们自己的转换值的循环更快。此外,我们不会为每个获取构建一个新的数组对象。

# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 435
def converted_arrays
  @converted_arrays ||= Set.new
end

deep_dup()

返回一个具有相同允许参数的 ActionController::Parameters 实例的副本。

# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 1092
def deep_dup
  self.class.new(@parameters.deep_dup, @logging_context).tap do |duplicate|
    duplicate.permitted = @permitted
  end
end

deep_merge(other_hash, &block)

返回一个新的 ActionController::Parameters 实例,其中递归地合并了 selfother_hash

与标准库中的 Hash#merge 一样,可以提供一个块来合并值。

# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 168
    

deep_merge!(other_hash, &block)

#deep_merge 相同,但会修改 self

# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 183
    

deep_transform_keys(&block)

返回一个新的 ActionController::Parameters 实例,其中包含对每个键运行 block 的结果。这包括来自根哈希和来自所有嵌套哈希和数组的键。值保持不变。

# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 924
def deep_transform_keys(&block)
  new_instance_with_inherited_permitted_status(
    _deep_transform_keys_in_object(@parameters, &block).to_unsafe_h
  )
end

deep_transform_keys!(&block)

返回具有更改键的相同 ActionController::Parameters 实例。这包括来自根哈希和来自所有嵌套哈希和数组的键。值保持不变。

# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 933
def deep_transform_keys!(&block)
  @parameters = _deep_transform_keys_in_object(@parameters, &block).to_unsafe_h
  self
end

delete(key, &block)

Parameters 中删除一个键值对并返回其值。如果找不到 key,则返回 nil(或者,使用可选的代码块,则会生成 key 并返回结果)。此方法类似于 extract!,它返回相应的 ActionController::Parameters 对象。

# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 942
def delete(key, &block)
  convert_value_to_parameters(@parameters.delete(key, &block))
end

delete_if(&block)

别名:reject!

dig(*keys)

通过在每个步骤调用 dig 从给定的 keys 中提取嵌套参数。如果任何中间步骤为 nil,则返回 nil

params = ActionController::Parameters.new(foo: { bar: { baz: 1 } })
params.dig(:foo, :bar, :baz) # => 1
params.dig(:foo, :zot, :xyz) # => nil

params2 = ActionController::Parameters.new(foo: [10, 11, 12])
params2.dig(:foo, 1) # => 11
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 841
def dig(*keys)
  convert_hashes_to_parameters(keys.first, @parameters[keys.first])
  @parameters.dig(*keys)
end

each(&block)

别名:each_pair

each_key(&block)

为参数中的每个键调用块一次,传递键。如果没有给出块,则返回枚举器。

# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 202
    

each_pair(&block)

将值中的所有哈希转换为参数,然后以与 Hash#each_pair 相同的方式生成每个对。

也称为:each
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 402
def each_pair(&block)
  return to_enum(__callee__) unless block_given?
  @parameters.each_pair do |key, value|
    yield [key, convert_hashes_to_parameters(key, value)]
  end

  self
end

each_value(&block)

将值中的所有哈希转换为参数,然后以与 Hash#each_value 相同的方式生成每个值。

# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 414
def each_value(&block)
  return to_enum(:each_value) unless block_given?
  @parameters.each_pair do |key, value|
    yield convert_hashes_to_parameters(key, value)
  end

  self
end

empty?()

如果参数没有键值对,则返回 true。

# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 211
    

eql?(other)

# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 309
def eql?(other)
  self.class == other.class &&
    permitted? == other.permitted? &&
    parameters.eql?(other.parameters)
end

except(*keys)

返回一个新的 ActionController::Parameters 实例,该实例过滤掉给定的 keys

params = ActionController::Parameters.new(a: 1, b: 2, c: 3)
params.except(:a, :b) # => #<ActionController::Parameters {"c"=>3} permitted: false>
params.except(:d)     # => #<ActionController::Parameters {"a"=>1, "b"=>2, "c"=>3} permitted: false>
也称为:without
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 869
def except(*keys)
  new_instance_with_inherited_permitted_status(@parameters.except(*keys))
end

exclude?(key)

如果给定的键不存在于参数中,则返回 true。

# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 219
    

expect(*filters)

expect 是要求和允许参数的首选方法。它比以前建议的按顺序调用 permitrequire 更安全,这可能会导致用户触发的 500 错误。

expect 对类型更加严格,以避免使用 .require.permit 模式可能遇到的许多潜在陷阱。

例如

params = ActionController::Parameters.new(comment: { text: "hello" })
params.expect(comment: [:text])
# => #<ActionController::Parameters { text: "hello" } permitted: true>

params = ActionController::Parameters.new(comment: [{ text: "hello" }, { text: "world" }])
params.expect(comment: [:text])
# => ActionController::ParameterMissing: param is missing or the value is empty or invalid: comment

为了允许参数数组,必须显式定义数组。使用双方括号,即数组内嵌数组,来声明期望参数数组。

params = ActionController::Parameters.new(comments: [{ text: "hello" }, { text: "world" }])
params.expect(comments: [[:text]])
# => [#<ActionController::Parameters { "text" => "hello" } permitted: true>,
#     #<ActionController::Parameters { "text" => "world" } permitted: true>]

params = ActionController::Parameters.new(comments: { text: "hello" })
params.expect(comments: [[:text]])
# => ActionController::ParameterMissing: param is missing or the value is empty or invalid: comments

expect 用于防止数组篡改。

params = ActionController::Parameters.new(user: "hack")
# The previous way of requiring and permitting parameters will error
params.require(:user).permit(:name, pets: [:name]) # wrong
# => NoMethodError: undefined method `permit' for an instance of String

# similarly with nested parameters
params = ActionController::Parameters.new(user: { name: "Martin", pets: { name: "hack" } })
user_params = params.require(:user).permit(:name, pets: [:name]) # wrong
# user_params[:pets] is expected to be an array but is a hash

expect 通过对类型更加严格来解决此问题。

params = ActionController::Parameters.new(user: "hack")
params.expect(user: [ :name, pets: [[:name]] ])
# => ActionController::ParameterMissing: param is missing or the value is empty or invalid: user

# with nested parameters
params = ActionController::Parameters.new(user: { name: "Martin", pets: { name: "hack" } })
user_params = params.expect(user: [:name, pets: [[:name]] ])
user_params[:pets] # => nil

如示例所示,expect 需要 :user 键,以及类似于 .require.permit 模式的任何根键。如果期望多个根键,则它们都将被要求。

params = ActionController::Parameters.new(name: “Martin”, pies: [{ type: “dessert”, flavor: “pumpkin”}]) name, pies = params.expect(:name, pies: [[:type, :flavor]]) name # => “Martin” pies # => [#<ActionController::Parameters {“type”=>“dessert”, “flavor”=>“pumpkin”} permitted: true>]

当使用具有多个键的哈希调用时,expect 将允许参数并按在哈希中给出的顺序要求键,返回允许参数的数组。

params = ActionController::Parameters.new(subject: { name: “Martin” }, object: { pie: “pumpkin” }) subject, object = params.expect(subject: [:name], object: [:pie]) subject # =>

除了对数组与哈希参数更加严格之外,expect 在内部使用 permit,因此它的行为将类似。

params = ActionController::Parameters.new({
  person: {
    name: "Francesco",
    age:  22,
    pets: [{
      name: "Purplish",
      category: "dogs"
    }]
  }
})

permitted = params.expect(person: [ :name, { pets: [[:name]] } ])
permitted.permitted?           # => true
permitted[:name]               # => "Francesco"
permitted[:age]                # => nil
permitted[:pets][0][:name]     # => "Purplish"
permitted[:pets][0][:category] # => nil

可以使用以下方法期望允许标量数组

params = ActionController::Parameters.new(tags: ["rails", "parameters"])
permitted = params.expect(tags: [])
permitted.permitted?      # => true
permitted.is_a?(Array)    # => true
permitted.size            # => 2
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 772
def expect(*filters)
  params = permit_filters(filters)
  keys = filters.flatten.flat_map { |f| f.is_a?(Hash) ? f.keys : f }
  values = params.require(keys)
  values.size == 1 ? values.first : values
end

expect!(*filters)

expect 相同,但会引发 ActionController::ExpectedParameterMissing 而不是 ActionController::ParameterMissing。与会渲染 400 响应的 expect 不同,expect! 会引发未处理的异常。这旨在用于调试内部 API 的无效参数,其中格式不正确的参数将表明客户端库中的错误,该错误应予以修复。

# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 786
def expect!(*filters)
  expect(*filters)
rescue ParameterMissing => e
  raise ExpectedParameterMissing.new(e.param, e.keys)
end

extract!(*keys)

删除并返回与给定键匹配的键值对。

params = ActionController::Parameters.new(a: 1, b: 2, c: 3)
params.extract!(:a, :b) # => #<ActionController::Parameters {"a"=>1, "b"=>2} permitted: false>
params                  # => #<ActionController::Parameters {"c"=>3} permitted: false>
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 879
def extract!(*keys)
  new_instance_with_inherited_permitted_status(@parameters.extract!(*keys))
end

extract_value(key, delimiter: "_")

返回由 delimiter 分隔的给定 key 的参数值。

params = ActionController::Parameters.new(id: "1_123", tags: "ruby,rails")
params.extract_value(:id) # => ["1", "123"]
params.extract_value(:tags, delimiter: ",") # => ["ruby", "rails"]
params.extract_value(:non_existent_key) # => nil

请注意,如果给定的 key 的值包含空白元素,则返回的数组将包含空字符串。

params = ActionController::Parameters.new(tags: "ruby,rails,,web")
params.extract_value(:tags, delimiter: ",") # => ["ruby", "rails", "", "web"]
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 1110
def extract_value(key, delimiter: "_")
  @parameters[key]&.split(delimiter, -1)
end

fetch(key, *args)

返回给定 key 的参数。如果找不到 key,则有几种选择:如果没有其他参数,它将引发 ActionController::ParameterMissing 错误;如果给出第二个参数,则返回该参数(如果可能,则转换为 ActionController::Parameters 的实例);如果给出块,则将运行该块并返回其结果。

params = ActionController::Parameters.new(person: { name: "Francesco" })
params.fetch(:person)               # => #<ActionController::Parameters {"name"=>"Francesco"} permitted: false>
params.fetch(:none)                 # => ActionController::ParameterMissing: param is missing or the value is empty or invalid: none
params.fetch(:none, {})             # => #<ActionController::Parameters {} permitted: false>
params.fetch(:none, "Francesco")    # => "Francesco"
params.fetch(:none) { "Francesco" } # => "Francesco"
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 820
def fetch(key, *args)
  convert_value_to_parameters(
    @parameters.fetch(key) {
      if block_given?
        yield
      else
        args.fetch(0) { raise ActionController::ParameterMissing.new(key, @parameters.keys) }
      end
    }
  )
end

has_key?

别名:include?

has_value?(value)

如果给定的值在参数中的某些键存在,则返回 true。

也称为:value?
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 997
def has_value?(value)
  each_value.include?(convert_value_to_parameters(value))
end

hash()

# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 315
def hash
  [self.class, @parameters, @permitted].hash
end

include?(key)

如果给定的键存在于参数中,则返回 true。

也称为:has_key?, key?, member?
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 227
    

inspect()

# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 1055
def inspect
  "#<#{self.class} #{@parameters} permitted: #{@permitted}>"
end

keep_if(&block)

别名:select!

key?

别名:include?

keys()

返回参数键的新数组。

# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 235
    

member?

别名:include?

merge(other_hash)

返回一个新的 ActionController::Parameters 实例,其中包含从 other_hash 合并到当前哈希中的所有键。

# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 1011
def merge(other_hash)
  new_instance_with_inherited_permitted_status(
    @parameters.merge(other_hash.to_h)
  )
end

merge!(other_hash)

返回当前的 ActionController::Parameters 实例,并将 other_hash 合并到当前的哈希中。

# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 1022
def merge!(other_hash, &block)
  @parameters.merge!(other_hash.to_h, &block)
  self
end

permit(*filters)

返回一个新的 ActionController::Parameters 实例,该实例仅包含给定的 filters,并将对象的 permitted 属性设置为 true。这对于限制哪些属性允许进行批量更新很有用。

params = ActionController::Parameters.new(name: "Francesco", age: 22, role: "admin")
permitted = params.permit(:name, :age)
permitted.permitted?      # => true
permitted.has_key?(:name) # => true
permitted.has_key?(:age)  # => true
permitted.has_key?(:role) # => false

只有允许的标量才能通过过滤器。例如,给定

params.permit(:name)

:name 如果它是 params 的一个键,其关联的值类型为 StringSymbolNilClassNumericTrueClassFalseClassDateTimeDateTimeStringIOIOActionDispatch::Http::UploadedFileRack::Test::UploadedFile,则可以通过过滤器。否则,键 :name 将被过滤掉。

您可以通过将其映射到空数组来声明该参数应该是允许标量的数组。

params = ActionController::Parameters.new(tags: ["rails", "parameters"])
params.permit(tags: [])

有时无法或不方便声明哈希参数的有效键或其内部结构。只需映射到空哈希即可。

params.permit(preferences: {})

请小心,因为这会打开任意输入的大门。在这种情况下,permit 确保返回结构中的值是允许的标量,并过滤掉其他任何内容。

您也可以对嵌套参数使用 permit

params = ActionController::Parameters.new({
  person: {
    name: "Francesco",
    age:  22,
    pets: [{
      name: "Purplish",
      category: "dogs"
    }]
  }
})

permitted = params.permit(person: [ :name, { pets: :name } ])
permitted.permitted?                    # => true
permitted[:person][:name]               # => "Francesco"
permitted[:person][:age]                # => nil
permitted[:person][:pets][0][:name]     # => "Purplish"
permitted[:person][:pets][0][:category] # => nil

这还有助于拒绝发送字符串而不是哈希的用户的修改输入。

require 之后,您可以同时过滤和要求参数,遵循 Rails 表单的典型模式。expect 方法专门为这种情况而设计,是要求和允许参数的推荐方法。

 permitted = params.expect(person: [:name, :age])

在分别使用 permitrequire 时,请注意方法调用的顺序。

 params = ActionController::Parameters.new(person: { name: "Martin", age: 40, role: "admin" })
 permitted = params.permit(person: [:name, :age]).require(:person) # correct

当首先使用 require 时,应用程序的用户可能会在用户(例如)为 :person 发送字符串时触发 NoMethodError。

 params = ActionController::Parameters.new(person: "tampered")
 permitted = params.require(:person).permit(:name, :age) # not recommended
 # => NoMethodError: undefined method `permit' for an instance of String

请注意,如果您在指向哈希的键中使用 permit,它将不会允许所有哈希。您还需要指定哈希中哪些属性应该被允许。

params = ActionController::Parameters.new({
  person: {
    contact: {
      email: "[email protected]",
      phone: "555-1234"
    }
  }
})

params.permit(person: :contact).require(:person)
# => #<ActionController::Parameters {} permitted: true>

params.permit(person: { contact: :phone }).require(:person)
# => #<ActionController::Parameters {"contact"=>#<ActionController::Parameters {"phone"=>"555-1234"} permitted: true>} permitted: true>

params.permit(person: { contact: [ :email, :phone ] }).require(:person)
# => #<ActionController::Parameters {"contact"=>#<ActionController::Parameters {"email"=>"[email protected]", "phone"=>"555-1234"} permitted: true>} permitted: true>

如果您的参数指定了多个由数字索引的参数,您可以使用与允许单个项目相同的语法来允许每个数字键下的参数集相同。

params = ActionController::Parameters.new({
  person: {
    '0': {
      email: "[email protected]",
      phone: "555-1234"
    },
    '1': {
      email: "[email protected]",
      phone: "555-6789"
    },
  }
})
params.permit(person: [:email]).to_h
# => {"person"=>{"0"=>{"email"=>"[email protected]"}, "1"=>{"email"=>"[email protected]"}}}

如果您想指定每个数字键想要哪些键,您可以改为分别指定每个键。

params = ActionController::Parameters.new({
  person: {
    '0': {
      email: "[email protected]",
      phone: "555-1234"
    },
    '1': {
      email: "[email protected]",
      phone: "555-6789"
    },
  }
})
params.permit(person: { '0': [:email], '1': [:phone]}).to_h
# => {"person"=>{"0"=>{"email"=>"[email protected]"}, "1"=>{"phone"=>"555-6789"}}}
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 668
def permit(*filters)
  permit_filters(filters, on_unpermitted: self.class.action_on_unpermitted_parameters, explicit_arrays: false)
end

permit!()

permitted 属性设置为 true。这可用于传递批量赋值。返回 self

class Person < ActiveRecord::Base
end

params = ActionController::Parameters.new(name: "Francesco")
params.permitted?  # => false
Person.new(params) # => ActiveModel::ForbiddenAttributesError
params.permit!
params.permitted?  # => true
Person.new(params) # => #<Person id: nil, name: "Francesco">
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 461
def permit!
  each_pair do |key, value|
    Array.wrap(value).flatten.each do |v|
      v.permit! if v.respond_to? :permit!
    end
  end

  @permitted = true
  self
end

permitted?()

如果参数被允许,则返回 true,否则返回 false

params = ActionController::Parameters.new
params.permitted? # => false
params.permit!
params.permitted? # => true
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 445
def permitted?
  @permitted
end

reject(&block)

返回一个新的 ActionController::Parameters 实例,其中块评估为 true 的项已删除。

# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 961
def reject(&block)
  new_instance_with_inherited_permitted_status(@parameters.reject(&block))
end

reject!(&block)

删除块评估为 true 的项,并返回 self。

也作为别名:delete_if
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 966
def reject!(&block)
  @parameters.reject!(&block)
  self
end

require(key)

此方法接受单个键和键数组。

当传递单个键时,如果它存在并且其关联的值存在或为单例 false,则返回该值。

ActionController::Parameters.new(person: { name: "Francesco" }).require(:person)
# => #<ActionController::Parameters {"name"=>"Francesco"} permitted: false>

否则,引发 ActionController::ParameterMissing

ActionController::Parameters.new.require(:person)
# ActionController::ParameterMissing: param is missing or the value is empty or invalid: person

ActionController::Parameters.new(person: nil).require(:person)
# ActionController::ParameterMissing: param is missing or the value is empty or invalid: person

ActionController::Parameters.new(person: "\t").require(:person)
# ActionController::ParameterMissing: param is missing or the value is empty or invalid: person

ActionController::Parameters.new(person: {}).require(:person)
# ActionController::ParameterMissing: param is missing or the value is empty or invalid: person

当给定一个键数组时,该方法尝试按顺序要求其中的每一个键。如果成功,则返回包含相应返回值的数组。

params = ActionController::Parameters.new(user: { ... }, profile: { ... })
user_params, profile_params = params.require([:user, :profile])

否则,该方法重新引发第一个找到的异常。

params = ActionController::Parameters.new(user: {}, profile: {})
user_params, profile_params = params.require([:user, :profile])
# ActionController::ParameterMissing: param is missing or the value is empty or invalid: user

此方法不推荐用于获取终端值,因为它不允许值。例如,这会导致问题。

# CAREFUL
params = ActionController::Parameters.new(person: { name: "Finn" })
name = params.require(:person).require(:name) # CAREFUL

建议使用 expect 代替。

def person_params
  # params.expect(person: :name).require(:name)
end
也作为别名:required
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 519
def require(key)
  return key.map { |k| require(k) } if key.is_a?(Array)
  value = self[key]
  if value.present? || value == false
    value
  else
    raise ParameterMissing.new(key, @parameters.keys)
  end
end

required(key)

别名:require

reverse_merge(other_hash)

返回一个新的 ActionController::Parameters 实例,其中当前哈希中的所有键都合并到 other_hash 中。

也作为别名:with_defaults
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 1033
def reverse_merge(other_hash)
  new_instance_with_inherited_permitted_status(
    other_hash.to_h.merge(@parameters)
  )
end

reverse_merge!(other_hash)

返回当前的 ActionController::Parameters 实例,其中当前哈希合并到 other_hash 中。

也作为别名:with_defaults!
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 1042
def reverse_merge!(other_hash)
  @parameters.merge!(other_hash.to_h) { |key, left, right| left }
  self
end

select(&block)

返回一个新的 ActionController::Parameters 实例,其中仅包含块评估为 true 的项。

# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 948
def select(&block)
  new_instance_with_inherited_permitted_status(@parameters.select(&block))
end

select!(&block)

等效于 Hash#keep_if,但如果未进行任何更改,则返回 nil

也作为别名:keep_if
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 953
def select!(&block)
  @parameters.select!(&block)
  self
end

slice(*keys)

返回一个新的 ActionController::Parameters 实例,该实例仅包含给定的 keys。如果给定的 keys 不存在,则返回一个空哈希。

params = ActionController::Parameters.new(a: 1, b: 2, c: 3)
params.slice(:a, :b) # => #<ActionController::Parameters {"a"=>1, "b"=>2} permitted: false>
params.slice(:d)     # => #<ActionController::Parameters {} permitted: false>
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 852
def slice(*keys)
  new_instance_with_inherited_permitted_status(@parameters.slice(*keys))
end

slice!(*keys)

返回当前的 ActionController::Parameters 实例,该实例仅包含给定的 keys

# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 858
def slice!(*keys)
  @parameters.slice!(*keys)
  self
end

to_h(&block)

返回参数的安全 ActiveSupport::HashWithIndifferentAccess 表示形式,其中已删除所有未经允许的键。

params = ActionController::Parameters.new({
  name: "Senjougahara Hitagi",
  oddity: "Heavy stone crab"
})
params.to_h
# => ActionController::UnfilteredParameters: unable to convert unpermitted parameters to hash

safe_params = params.permit(:name)
safe_params.to_h # => {"name"=>"Senjougahara Hitagi"}
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 331
def to_h(&block)
  if permitted?
    convert_parameters_to_hashes(@parameters, :to_h, &block)
  else
    raise UnfilteredParameters
  end
end

to_hash()

返回参数的安全 Hash 表示形式,其中已删除所有未经允许的键。

params = ActionController::Parameters.new({
  name: "Senjougahara Hitagi",
  oddity: "Heavy stone crab"
})
params.to_hash
# => ActionController::UnfilteredParameters: unable to convert unpermitted parameters to hash

safe_params = params.permit(:name)
safe_params.to_hash # => {"name"=>"Senjougahara Hitagi"}
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 351
def to_hash
  to_h.to_hash
end

to_param(*args)

别名:to_query

to_query(*args)

返回接收者的字符串表示形式,适合用作 URL 查询字符串。

params = ActionController::Parameters.new({
  name: "David",
  nationality: "Danish"
})
params.to_query
# => ActionController::UnfilteredParameters: unable to convert unpermitted parameters to hash

safe_params = params.permit(:name, :nationality)
safe_params.to_query
# => "name=David&nationality=Danish"

可以传递一个可选的命名空间来包含键名。

params = ActionController::Parameters.new({
  name: "David",
  nationality: "Danish"
})
safe_params = params.permit(:name, :nationality)
safe_params.to_query("user")
# => "user%5Bname%5D=David&user%5Bnationality%5D=Danish"

构成查询字符串的字符串对 "key=value" 按字母顺序排序。

也作为别名:to_param
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 381
def to_query(*args)
  to_h.to_query(*args)
end

to_s()

以字符串形式返回参数的内容。

# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 250
delegate :keys, :empty?, :exclude?, :include?,
  :as_json, :to_s, :each_key, to: :@parameters

to_unsafe_h()

返回参数的不安全、未过滤的 ActiveSupport::HashWithIndifferentAccess 表示形式。

params = ActionController::Parameters.new({
  name: "Senjougahara Hitagi",
  oddity: "Heavy stone crab"
})
params.to_unsafe_h
# => {"name"=>"Senjougahara Hitagi", "oddity" => "Heavy stone crab"}
也作为别名:to_unsafe_hash
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 395
def to_unsafe_h
  convert_parameters_to_hashes(@parameters, :to_unsafe_h)
end

to_unsafe_hash()

别名:to_unsafe_h

transform_keys(&block)

返回一个新的 ActionController::Parameters 实例,其中包含对每个键运行 block 的结果。值保持不变。

# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 906
def transform_keys(&block)
  return to_enum(:transform_keys) unless block_given?
  new_instance_with_inherited_permitted_status(
    @parameters.transform_keys(&block)
  )
end

transform_keys!(&block)

执行键转换并返回已更改的 ActionController::Parameters 实例。

# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 915
def transform_keys!(&block)
  return to_enum(:transform_keys!) unless block_given?
  @parameters.transform_keys!(&block)
  self
end

transform_values()

返回一个新的 ActionController::Parameters 实例,其中包含对每个值运行 block 的结果。键保持不变。

params = ActionController::Parameters.new(a: 1, b: 2, c: 3)
params.transform_values { |x| x * 2 }
# => #<ActionController::Parameters {"a"=>2, "b"=>4, "c"=>6} permitted: false>
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 889
def transform_values
  return to_enum(:transform_values) unless block_given?
  new_instance_with_inherited_permitted_status(
    @parameters.transform_values { |v| yield convert_value_to_parameters(v) }
  )
end

transform_values!()

执行值转换并返回已更改的 ActionController::Parameters 实例。

# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 898
def transform_values!
  return to_enum(:transform_values!) unless block_given?
  @parameters.transform_values! { |v| yield convert_value_to_parameters(v) }
  self
end

value?(value)

别名:has_value?

values()

返回一个包含参数值的新的数组。

# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 424
def values
  to_enum(:each_value).to_a
end

values_at(*keys)

返回分配给给定 keys 的值。请注意,所有 Hash 对象都将转换为 ActionController::Parameters

# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 1005
def values_at(*keys)
  convert_value_to_parameters(@parameters.values_at(*keys))
end

with_defaults(other_hash)

别名:reverse_merge

with_defaults!(other_hash)

without(*keys)

别名:except

实例保护方法

each_nested_attribute()

# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 1123
def each_nested_attribute
  hash = self.class.new
  self.each { |k, v| hash[k] = yield v if Parameters.nested_attribute?(k, v) }
  hash
end

nested_attributes?()

# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 1119
def nested_attributes?
  @parameters.any? { |k, v| Parameters.nested_attribute?(k, v) }
end

permit_filters(filters, on_unpermitted: nil, explicit_arrays: true)

过滤自身,并可选地检查未经许可的键

# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 1130
def permit_filters(filters, on_unpermitted: nil, explicit_arrays: true)
  params = self.class.new

  filters.flatten.each do |filter|
    case filter
    when Symbol, String
      # Declaration [:name, "age"]
      permitted_scalar_filter(params, filter)
    when Hash
      # Declaration [{ person: ... }]
      hash_filter(params, filter, on_unpermitted:, explicit_arrays:)
    end
  end

  unpermitted_parameters!(params, on_unpermitted:)

  params.permit!
end