Spec-Zone.ru › Ruby on Rails 8.1

class ActionController::Parameters

Родительский класс:
Object

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 — не предпринимать никаких действий.

    • :log — отправить событие ActiveSupport::Notifications.instrument в теме unpermitted_parameters.action_controller и записать сообщение с уровнем 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

Обратите внимание, что эти параметры не являются потокобезопасными. В многопоточной среде их следует задавать только один раз при запуске и никогда не изменять во время выполнения.

Получить значения ActionController::Parameters можно с помощью :key или "key".

params = ActionController::Parameters.new(key: "value")
params[:key]  # => "value"
params["key"] # => "value"

Константы

PERMITTED_SCALAR_TYPES

Это список разрешённых скалярных типов, включая типы, поддерживаемые в запросах XML и JSON.

Этот список используется, в частности, для фильтрации обычных запросов. String стоит первым элементом, чтобы быстро завершить проверку в наиболее распространённом случае.

Если вы измените эту коллекцию, обновите также соответствующий список в документации permit.

Атрибуты

parameters [R]
permitted [W]

Публичные методы класса

new (parameters = {}, logging_context = {}) Показать исходный код
# 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

Возвращает новый экземпляр 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">

Открытые методы экземпляра

== (other) Показать исходный код
# 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

Возвращает true, если другой объект Parameters содержит те же данные и флаг разрешения.

Вызывает метод суперкласса
[] (key) Показать исходный код
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 797
def [](key)
  convert_hashes_to_parameters(key, @parameters[key])
end

Возвращает параметр для указанного key. Если он не найден, возвращает nil.

params = ActionController::Parameters.new(person: { name: "Francesco" })
params[:person] # => #<ActionController::Parameters {"name"=>"Francesco"} permitted: false>
params[:none]   # => nil
[]= (key, value) Показать исходный код
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 803
def []=(key, value)
  @parameters[key] = value
end

Присваивает значение указанному key. Указанный ключ всё ещё может быть отфильтрован при вызове permit.

as_json(options=nil) Показать исходный код
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 194
    

Возвращает хеш, который можно использовать в качестве JSON-представления параметров.

compact () Показать исходный код
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 974
def compact
  new_instance_with_inherited_permitted_status(@parameters.compact)
end

Возвращает новый экземпляр ActionController::Parameters без значений nil.

compact! () Показать исходный код
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 980
def compact!
  self if @parameters.compact!
end

Удаляет все значения nil на месте и возвращает self либо nil, если изменений не было.

compact_blank () Показать исходный код
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 986
def compact_blank
  reject { |_k, v| v.blank? }
end

Возвращает новый экземпляр ActionController::Parameters без пустых значений. Для определения того, является ли значение пустым, используется Object#blank?.

compact_blank! () Показать исходный код
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 992
def compact_blank!
  reject! { |_k, v| v.blank? }
end

Удаляет все пустые значения на месте и возвращает self. Для определения того, является ли значение пустым, используется Object#blank?.

converted_arrays () Показать исходный код
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 435
def converted_arrays
  @converted_arrays ||= Set.new
end

Атрибут, отслеживающий преобразованные массивы, если таковые имеются, чтобы избежать повторного перебора в распространённом сценарии использования permit и массового присваивания. Определён в методе, чтобы создавать его только при необходимости.

Testing по-прежнему выполняет перебор при проверке вхождения, но это быстрее, чем собственный цикл преобразования значений. Кроме того, для каждого извлечения не будет создаваться новый объект массива.

deep_dup () Показать исходный код
# 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

Возвращает дублированный экземпляр ActionController::Parameters с теми же разрешёнными параметрами.

deep_merge(other_hash, &block) Показать исходный код
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 168
    

Возвращает новый экземпляр ActionController::Parameters с рекурсивно объединёнными self и other_hash.

Как и для Hash#merge в стандартной библиотеке, для объединения значений можно передать блок.

deep_merge!(other_hash, &block) Показать исходный код
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 183
    

То же, что и deep_merge, но изменяет self.

deep_transform_keys (&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

Возвращает новый экземпляр ActionController::Parameters с результатами однократного выполнения block для каждого ключа. Сюда входят ключи корневого хеша, а также всех вложенных хешей и массивов. Значения остаются неизменными.

deep_transform_keys! (&block) Показать исходный код
# 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

Возвращает тот же экземпляр ActionController::Parameters с изменёнными ключами. Сюда входят ключи корневого хеша, а также всех вложенных хешей и массивов. Значения остаются неизменными.

delete (key, &block) Показать исходный код
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 942
def delete(key, &block)
  convert_value_to_parameters(@parameters.delete(key, &block))
end

Удаляет пару ключ-значение из Parameters и возвращает значение. Если key не найден, возвращает nil (или, если передан необязательный блок кода, передаёт ему key и возвращает результат). Этот метод похож на extract!, который возвращает соответствующий объект ActionController::Parameters.

delete_if (&block)
Псевдоним для: reject!
dig (*keys) Показать исходный код
# 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

Извлекает вложенный параметр из указанного keys, вызывая dig на каждом шаге. Возвращает 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
each (&block)
Псевдоним для: each_pair
each_key(&block) Показать исходный код
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 202
    

Вызывает блок один раз для каждого ключа параметров, передавая ему ключ. Если блок не указан, вместо него возвращается перечислитель.

each_pair () { |key, convert_hashes_to_parameters(key, value)| ... } Показать исходный код
# 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

Преобразует все хеши в значениях в параметры, а затем передаёт каждую пару так же, как Hash#each_pair.

Также имеет псевдоним: each
each_value () { |convert_hashes_to_parameters(key, 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

Преобразует все хеши в значениях в параметры, а затем передаёт каждое значение так же, как Hash#each_value.

empty?() Показать исходный код
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 211
    

Возвращает true, если параметры не содержат пар ключ-значение.

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) Показать исходный код
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 869
def except(*keys)
  new_instance_with_inherited_permitted_status(@parameters.except(*keys))
end

Возвращает новый экземпляр 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
exclude?(key) Показать исходный код
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 219
    

Возвращает true, если указанный ключ отсутствует в параметрах.

expect (*filters) Показать исходный код
# 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 — рекомендуемый способ требовать и разрешать параметры. Он безопаснее, чем прежняя рекомендация последовательно вызывать permit и require, что могло приводить к ошибкам 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 # => #<ActionController::Parameters {"name"=>"Martin"} permitted: true>
object  # => #<ActionController::Parameters {"pie"=>"pumpkin"} permitted: true>

Помимо более строгой проверки того, являются ли параметры массивом или хешем, 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                 # => ["rails", "parameters"]
permitted.is_a?(Array)    # => true
permitted.size            # => 2
expect! (*filters) Показать исходный код
# 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

То же, что и expect, но вместо ActionController::ParameterMissing вызывает исключение ActionController::ExpectedParameterMissing. В отличие от expect, который возвращает ответ 400, expect! вызывает необработанное исключение. Это предназначено для отладки некорректных параметров внутреннего API, где неверный формат параметров указывает на ошибку в клиентской библиотеке, которую следует исправить.

extract! (*keys) Показать исходный код
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 879
def extract!(*keys)
  new_instance_with_inherited_permitted_status(@parameters.extract!(*keys))
end

Удаляет и возвращает пары ключ-значение, соответствующие указанным ключам.

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>
extract_value (key, delimiter: "_") Показать исходный код
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 1110
def extract_value(key, delimiter: "_")
  @parameters[key]&.split(delimiter, -1)
end

Возвращает значение параметра для указанного key, разделённого с помощью delimiter.

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"]
fetch (key, *args) { || ... } Показать исходный код
# 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

Возвращает параметр для указанного 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"
has_key?
Псевдоним для: include?
has_value? (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

Возвращает true, если указанное значение присутствует в параметрах хотя бы для одного ключа.

Также имеет псевдоним: value?
hash () Показать исходный код
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 315
def hash
  [self.class, @parameters, @permitted].hash
end
include?(key) Показать исходный код
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 227
    

Возвращает true, если указанный ключ присутствует в параметрах.

Также имеет псевдонимы: has_key?, key?, member?
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) Показать исходный код
# 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

Возвращает новый экземпляр ActionController::Parameters со всеми ключами из other_hash, объединёнными с текущим хешем.

merge!(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

Возвращает текущий экземпляр ActionController::Parameters с other_hash, объединённым с текущим хешем.

permit (*filters) Показать исходный код
# 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

Возвращает новый экземпляр 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, значение которого имеет тип String, Symbol, NilClass, Numeric, TrueClass, FalseClass, Date, Time, DateTime, StringIO, IO, ActionDispatch::Http::UploadedFile или Rack::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])

При раздельном использовании permit и require внимательно следите за порядком вызова методов.

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

Если сначала использовать require, пользователи приложения могут вызвать NoMethodError, например передав строку вместо :person.

 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: "none@test.com",
      phone: "555-1234"
    }
  }
})

params.permit(person: :contact).require(:person)
# => ActionController::ParameterMissing: param is missing or the value is empty or invalid: person

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"=>"none@test.com", "phone"=>"555-1234"} permitted: true>} permitted: true>

Если параметры содержат несколько параметров, индексированных числом, можно разрешить одинаковый набор параметров для каждого числового ключа, используя тот же синтаксис, что и для разрешения одного элемента.

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

Если нужно указать, какие ключи следует извлечь для каждого числового ключа, можно вместо этого перечислить их по отдельности

params = ActionController::Parameters.new({
  person: {
    '0': {
      email: "none@test.com",
      phone: "555-1234"
    },
    '1': {
      email: "nothing@test.com",
      phone: "555-6789"
    },
  }
})
params.permit(person: { '0': [:email], '1': [:phone]}).to_h
# => {"person"=>{"0"=>{"email"=>"none@test.com"}, "1"=>{"phone"=>"555-6789"}}}
permit! () Показать исходный код
# 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. Это можно использовать для массового присваивания. Возвращает 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">
permitted? () Показать исходный код
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 445
def permitted?
  @permitted
end

Возвращает true, если параметр разрешён, и false в противном случае.

params = ActionController::Parameters.new
params.permitted? # => false
params.permit!
params.permitted? # => true
reject (&block) Показать исходный код
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 961
def reject(&block)
  new_instance_with_inherited_permitted_status(@parameters.reject(&block))
end

Возвращает новый экземпляр ActionController::Parameters без элементов, для которых блок возвращает true.

reject! (&block) Показать исходный код
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 966
def reject!(&block)
  @parameters.reject!(&block)
  self
end

Удаляет элементы, для которых блок возвращает true, и возвращает self.

Также имеет псевдоним: delete_if
require (key) Показать исходный код
# 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

Этот метод принимает как один ключ, так и массив ключей.

Если передан один ключ и он существует, а связанное с ним значение задано или является синглтоном 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
required (key)
Псевдоним для: require
reverse_merge (other_hash) Показать исходный код
# 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

Возвращает новый экземпляр ActionController::Parameters, в который объединены все ключи текущего хеша и other_hash.

Также имеет псевдоним: with_defaults
reverse_merge! (other_hash) Показать исходный код
# 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

Возвращает текущий экземпляр ActionController::Parameters, в который объединены текущий хеш и other_hash.

Также имеет псевдоним: with_defaults!
select (&block) Показать исходный код
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 948
def select(&block)
  new_instance_with_inherited_permitted_status(@parameters.select(&block))
end

Возвращает новый экземпляр ActionController::Parameters, содержащий только элементы, для которых блок возвращает true.

select! (&block) Показать исходный код
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 953
def select!(&block)
  @parameters.select!(&block)
  self
end

Эквивалентен Hash#keep_if, но возвращает nil, если изменений не было.

Также имеет псевдоним: keep_if
slice (*keys) Показать исходный код
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 852
def slice(*keys)
  new_instance_with_inherited_permitted_status(@parameters.slice(*keys))
end

Возвращает новый экземпляр 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>
slice! (*keys) Показать исходный код
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 858
def slice!(*keys)
  @parameters.slice!(*keys)
  self
end

Возвращает текущий экземпляр ActionController::Parameters, содержащий только указанные keys.

to_h (&block) Показать исходный код
# 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

Возвращает безопасное представление параметров в виде 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"}
to_hash () Показать исходный код
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 351
def to_hash
  to_h.to_hash
end

Возвращает безопасное представление параметров в виде 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"}
to_param (*args)
Псевдоним для: to_query
to_query (*args) Показать исходный код
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 381
def to_query(*args)
  to_h.to_query(*args)
end

Возвращает строковое представление объекта, пригодное для использования в качестве строки запроса 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
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 () Показать исходный код
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 395
def to_unsafe_h
  convert_parameters_to_hashes(@parameters, :to_unsafe_h)
end

Возвращает небезопасное, нефильтрованное представление параметров в виде 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
to_unsafe_hash ()
Псевдоним для: to_unsafe_h
transform_keys (&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

Возвращает новый экземпляр ActionController::Parameters с результатами однократного выполнения block для каждого ключа. Значения не изменяются.

transform_keys! (&block) Показать исходный код
# 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

Преобразует ключи и возвращает изменённый экземпляр ActionController::Parameters.

transform_values () { |convert_value_to_parameters(v)| ... } Показать исходный код
# 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

Возвращает новый экземпляр 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>
transform_values! () { |convert_value_to_parameters(v)| ... } Показать исходный код
# 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

Преобразует значения и возвращает изменённый экземпляр ActionController::Parameters.

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) Показать исходный код
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 1005
def values_at(*keys)
  convert_value_to_parameters(@parameters.values_at(*keys))
end

Возвращает значения, присвоенные указанным keys. Обратите внимание, что все объекты Hash будут преобразованы в ActionController::Parameters.

with_defaults (other_hash)
Псевдоним для: reverse_merge
with_defaults! (other_hash)
Псевдоним для: reverse_merge!
without (*keys)
Псевдоним для: except

Защищённые методы экземпляра

each_nested_attribute () { |v| ... } Показать исходный код
# 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

Фильтрует self и при необходимости проверяет наличие неразрешённых ключей

© 2004–2021 David Heinemeier Hansson
Licensed under the MIT License.

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API