класс ActionController::Parameters
Параметры Action Controller
Позволяет выбрать, какие атрибуты должны быть разрешены для массового обновления, тем самым предотвращая случайное раскрытие конфиденциальных данных. Предоставляет два метода для этой цели: require и permit. Первый используется для маркировки параметров как обязательных. Второй используется для обозначения параметра как разрешенного и ограничения атрибутов, разрешенных для массового обновления.
params = ActionController::Parameters.new({
person: {
name: "Francesco",
age: 22,
role: "admin"
}
})
permitted = params.require(:person).permit(:name, :age)
permitted # => <ActionController::Parameters {"name"=>"Francesco", "age"=>22} permitted: true>
permitted.permitted? # => true
Person.first.update!(permitted)
# => #<Person id: 1, name: "Francesco", age: 22, role: "user">
Он предоставляет два варианта, которые управляют поведением новых экземпляров:
-
permit_all_parameters- Если этоtrue, все параметры по умолчанию будут разрешены. По умолчаниюfalse. -
action_on_unpermitted_parameters- Позволяет контролировать поведение при обнаружении параметров, которые не были явно разрешены. Значения могут бытьfalseдля простого отбрасывания таких параметров,:logдля добавления сообщения в логгер или:raiseдля повышения исключения ActionController::UnpermittedParameters. Значение по умолчанию -:logв тестовых и разработочных средах,falseв остальных.
Примеры:
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"
Константы
- EMPTY_ARRAY
- EMPTY_HASH
- PERMITTED_SCALAR_TYPES
-
Это белый список разрешенных скалярных типов, включающих типы, поддерживаемые в запросах XML и JSON.
Этот список используется для фильтрации обычных запросов, Строка указана в качестве первого элемента для быстрого исключения общего случая.
Если вы изменяете этот список, обновите API
permitвыше.
Атрибуты
Публичные методы класса
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 242
def initialize(parameters = {})
@parameters = parameters.with_indifferent_access
@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 249
def ==(other)
if other.respond_to?(:permitted?)
permitted? == other.permitted? && parameters == other.parameters
else
@parameters == other
end
end Возвращает true, если другой объект Parameters содержит то же содержимое и флаг разрешения.
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 566 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 572 def []=(key, value) @parameters[key] = value end
Присваивает значение заданному key. Заданный ключ все еще может быть отфильтрован при вызове permit.
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 134
Возвращает хеш, который можно использовать в качестве JSON-представления параметров.
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 365 def converted_arrays @converted_arrays ||= Set.new end
Атрибут, который отслеживает преобразованные массивы (если таковые имеются), чтобы избежать двойного циклирования в общем случае разрешения + массового назначения. Определен в методе для инициализации только при необходимости.
Тестирование членства все еще циклирует, но это будет быстрее, чем наш собственный цикл, преобразующий значения. Кроме того, мы не будем создавать новый объект массива при каждом извлечении.
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 801
def deep_dup
self.class.new(@parameters.deep_dup).tap do |duplicate|
duplicate.permitted = @permitted
end
end Возвращает дубликат объекта, включая все параметры.
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 694 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 610 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 143
Вызывает блок один раз для каждого ключа в параметрах, передавая ключ. Если блок не задан, вместо этого возвращается перечислитель.
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 343
def each_pair(&block)
@parameters.each_pair do |key, value|
yield [key, convert_hashes_to_parameters(key, value)]
end
end Преобразует все хеши в значения в параметры, затем передает каждую пару таким же образом, как Hash#each_pair.
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 352
def each_value(&block)
@parameters.each_pair do |key, value|
yield convert_hashes_to_parameters(key, value)
end
end Преобразует все хеши в значения в параметры, затем передает каждое значение таким же образом, как Hash#each_value.
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 151
Возвращает true, если параметры не содержат пар ключ/значение.
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 639 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 648 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 589
def fetch(key, *args)
convert_value_to_parameters(
@parameters.fetch(key) {
if block_given?
yield
else
args.fetch(0) { raise ActionController::ParameterMissing.new(key) }
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: 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 159
Возвращает true, если заданный ключ присутствует в параметрах.
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 167
Возвращает true, если заданное значение присутствует для какого-либо ключа в параметрах.
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 175
Возвращает true, если заданный ключ присутствует в параметрах.
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 769
def inspect
"<#{self.class} #{@parameters} permitted: #{@permitted}>"
end # File actionpack/lib/action_controller/metal/strong_parameters.rb, line 183
Возвращает true, если заданный ключ присутствует в параметрах.
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 191
Возвращает новый массив ключей параметров.
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 732
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 740 def merge!(other_hash) @parameters.merge!(other_hash.to_h) self end
Возвращает текущий ActionController::Parameters экземпляр с объединённым в текущий хэш other_hash.
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 543
def permit(*filters)
params = self.class.new
filters.flatten.each do |filter|
case filter
when Symbol, String
permitted_scalar_filter(params, filter)
when Hash
hash_filter(params, filter)
end
end
unpermitted_parameters!(params) if self.class.action_on_unpermitted_parameters
params.permit!
end Возвращает новый ActionController::Parameters экземпляр, содержащий только указанные filters, и устанавливает атрибут permitted объекта в значение true. Это полезно для ограничения атрибутов, которые должны быть разрешены при массовом обновлении.
params = ActionController::Parameters.new(user: { name: "Francesco", age: 22, role: "admin" })
permitted = params.require(:user).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. В противном случае ключ :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
Обратите внимание, что если вы используете permit в ключе, который указывает на хэш, он не позволит использовать весь хэш. Вам также нужно указать, какие атрибуты внутри хэша должны быть разрешены.
params = ActionController::Parameters.new({
person: {
contact: {
email: "none@test.com",
phone: "555-1234"
}
}
})
params.require(:person).permit(:contact)
# => <ActionController::Parameters {} permitted: true>
params.require(:person).permit(contact: :phone)
# => <ActionController::Parameters {"contact"=><ActionController::Parameters {"phone"=>"555-1234"} permitted: true>} permitted: true>
params.require(:person).permit(contact: [ :email, :phone ])
# => <ActionController::Parameters {"contact"=><ActionController::Parameters {"email"=>"none@test.com", "phone"=>"555-1234"} permitted: true>} permitted: true>
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 391
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 375 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 713 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 718 def reject!(&block) @parameters.reject!(&block) self end
Удаляет элементы, для которых блок возвращает true, и возвращает self.
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 452
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)
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: person
ActionController::Parameters.new(person: nil).require(:person)
# ActionController::ParameterMissing: param is missing or the value is empty: person
ActionController::Parameters.new(person: "\t").require(:person)
# ActionController::ParameterMissing: param is missing or the value is empty: person
ActionController::Parameters.new(person: {}).require(:person)
# ActionController::ParameterMissing: param is missing or the value is empty: 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: user
Технически этот метод можно использовать для получения конечных значений:
# CAREFUL
params = ActionController::Parameters.new(person: { name: "Finn" })
name = params.require(:person).require(:name) # CAREFUL
но имейте в виду, что в какой-то момент эти значения должны быть разрешены:
def person_params
params.require(:person).permit(:name).tap do |person_params|
person_params.require(:name) # SAFER
end
end
например.
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 747
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 756
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 700 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 705 def select!(&block) @parameters.select!(&block) self end
Эквивалентно Hash#keep_if, но возвращает nil если изменений не было.
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 622 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 628 def slice!(*keys) @parameters.slice!(*keys) self end
Возвращает текущий ActionController::Parameters экземпляр, содержащий только указанные keys.
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 269
def to_h
if permitted?
convert_parameters_to_hashes(@parameters, :to_h)
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 289 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 321 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"
Строки пар «ключ=значение», образующие строку запроса, сортируются лексикографически в порядке возрастания.
Этот метод также алиасирован как to_param.
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 199
Возвращает содержимое параметров в виде строки.
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 336 def to_unsafe_h convert_parameters_to_hashes(@parameters, :to_unsafe_h) end
Возвращает небезопасное, неотфильтрованное представление параметров.
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 675
def transform_keys(&block)
return to_enum(:transform_keys) unless block_given?
new_instance_with_inherited_permitted_status(
@parameters.transform_keys(&block)
)
end Возвращает новый экземпляр с результатами выполнения блока для каждого ключа. Значения остаются неизменными.
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 684 def transform_keys!(&block) return to_enum(:transform_keys!) unless block_given? @parameters.transform_keys!(&block) self end
Выполняет преобразование ключей и возвращает измененный экземпляр.
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 658
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 Возвращает новый экземпляр с результатами выполнения блока для каждого значения. Ключи остаются неизменными.
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 667
def transform_values!
return to_enum(:transform_values!) unless block_given?
@parameters.transform_values! { |v| yield convert_value_to_parameters(v) }
self
end Выполняет преобразование значений и возвращает измененный экземпляр.
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 207
Возвращает true, если заданное значение присутствует для какого-либо ключа в параметрах.
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 214 delegate :keys, :key?, :has_key?, :values, :has_value?, :value?, :empty?, :include?, :as_json, :to_s, :each_key, to: :@parameters
Возвращает новый массив значений параметров.
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 726 def values_at(*keys) convert_value_to_parameters(@parameters.values_at(*keys)) end
Возвращает значения, назначенные заданным ключам. Обратите внимание, что все объекты будут преобразованы в соответствующий тип.
Защищенные методы экземпляра
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 812
def fields_for_style?
@parameters.all? { |k, v| k =~ /\A-?\d+\z/ && (v.is_a?(Hash) || v.is_a?(Parameters)) }
end
© 2004–2019 David Heinemeier Hansson
Licensed under the MIT License.