class ActionController::Parameters
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.
Атрибуты
Публичные методы класса
# 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">
Открытые методы экземпляра
# 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 содержит те же данные и флаг разрешения.
# 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
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 803 def []=(key, value) @parameters[key] = value end
Присваивает значение указанному key. Указанный ключ всё ещё может быть отфильтрован при вызове permit.
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 194
Возвращает хеш, который можно использовать в качестве JSON-представления параметров.
# 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.
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 980 def compact! self if @parameters.compact! end
Удаляет все значения nil на месте и возвращает self либо nil, если изменений не было.
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 986
def compact_blank
reject { |_k, v| v.blank? }
end Возвращает новый экземпляр ActionController::Parameters без пустых значений. Для определения того, является ли значение пустым, используется Object#blank?.
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 992
def compact_blank!
reject! { |_k, v| v.blank? }
end Удаляет все пустые значения на месте и возвращает self. Для определения того, является ли значение пустым, используется Object#blank?.
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 435 def converted_arrays @converted_arrays ||= Set.new end
Атрибут, отслеживающий преобразованные массивы, если таковые имеются, чтобы избежать повторного перебора в распространённом сценарии использования permit и массового присваивания. Определён в методе, чтобы создавать его только при необходимости.
Testing по-прежнему выполняет перебор при проверке вхождения, но это быстрее, чем собственный цикл преобразования значений. Кроме того, для каждого извлечения не будет создаваться новый объект массива.
# 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 с теми же разрешёнными параметрами.
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 168
Возвращает новый экземпляр ActionController::Parameters с рекурсивно объединёнными self и other_hash.
Как и для Hash#merge в стандартной библиотеке, для объединения значений можно передать блок.
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 183
То же, что и deep_merge, но изменяет self.
# 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 для каждого ключа. Сюда входят ключи корневого хеша, а также всех вложенных хешей и массивов. Значения остаются неизменными.
# 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 с изменёнными ключами. Сюда входят ключи корневого хеша, а также всех вложенных хешей и массивов. Значения остаются неизменными.
# 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.
# 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
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 202
Вызывает блок один раз для каждого ключа параметров, передавая ему ключ. Если блок не указан, вместо него возвращается перечислитель.
# 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.
# 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.
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 211
Возвращает true, если параметры не содержат пар ключ-значение.
# 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 # 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>
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 219
Возвращает true, если указанный ключ отсутствует в параметрах.
# 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
# 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, где неверный формат параметров указывает на ошибку в клиентской библиотеке, которую следует исправить.
# 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>
# 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"]
# 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"
# 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, если указанное значение присутствует в параметрах хотя бы для одного ключа.
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 315 def hash [self.class, @parameters, @permitted].hash end
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 227
Возвращает true, если указанный ключ присутствует в параметрах.
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 1055
def inspect
"#<#{self.class} #{@parameters} permitted: #{@permitted}>"
end # File actionpack/lib/action_controller/metal/strong_parameters.rb, line 235
Возвращает новый массив ключей параметров.
# 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, объединёнными с текущим хешем.
# 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, объединённым с текущим хешем.
# 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"}}}
# 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">
# 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
# 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.
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 966 def reject!(&block) @parameters.reject!(&block) self end
Удаляет элементы, для которых блок возвращает true, и возвращает self.
# 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
# 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.
# 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.
# 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.
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 953 def select!(&block) @parameters.select!(&block) self end
Эквивалентен Hash#keep_if, но возвращает nil, если изменений не было.
# 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>
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 858 def slice!(*keys) @parameters.slice!(*keys) self end
Возвращает текущий экземпляр ActionController::Parameters, содержащий только указанные keys.
# 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"}
# 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"}
# 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", составляющие строку запроса, сортируются лексикографически по возрастанию.
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 250 delegate :keys, :empty?, :exclude?, :include?, :as_json, :to_s, :each_key, to: :@parameters
Возвращает содержимое параметров в виде строки.
# 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"}
# 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 для каждого ключа. Значения не изменяются.
# 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.
# 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>
# 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.
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 424 def values to_enum(:each_value).to_a end
Возвращает новый массив значений параметров.
# 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.
Защищённые методы экземпляра
# 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 # File actionpack/lib/action_controller/metal/strong_parameters.rb, line 1119
def nested_attributes?
@parameters.any? { |k, v| Parameters.nested_attribute?(k, v) }
end # 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.