класс 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 234
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 241
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 545 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 551 def []=(key, value) @parameters[key] = value end
Присваивает значение заданному key. Заданный ключ может быть отфильтрован, когда вызывается permit.
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 135
Возвращает хэш, который может использоваться в качестве JSON-представления параметров.
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 344 def converted_arrays @converted_arrays ||= Set.new end
Атрибут, который отслеживает преобразованные массивы (если таковые имеются) для избежания двойного циклирования в общем случае с разрешением + массовым назначением. Определен в методе для инициализации только при необходимости.
Тестирование членства по-прежнему циклируется, но это будет быстрее, чем наш собственный цикл, который преобразует значения. Кроме того, мы не будем создавать новый объект массива при каждом извлечении.
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 781
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 676 def delete(key, &block) convert_value_to_parameters(@parameters.delete(key, &block)) end
Удаляет и возвращает пару ключ-значение из Parameters, ключ которой равен ключу. Если ключ не найден, возвращает значение по умолчанию. Если предоставлен необязательный блок кода и ключ не найден, передаёт ключ и возвращает результат блока.
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 588 def dig(*keys) convert_value_to_parameters(@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 330
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 143
Возвращает true, если параметры не содержат пар ключ/значение.
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 617 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 626 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 566
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; если предоставлены дополнительные аргументы, то они возвращаются; если задан блок, то он выполняется и возвращается его результат.
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, "Francesco") # => "Francesco"
params.fetch(:none) { "Francesco" } # => "Francesco"
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 151
Возвращает true, если заданный ключ присутствует в параметрах.
# 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 749
def inspect
"<#{self.class} #{@parameters} permitted: #{@permitted}>"
end # File actionpack/lib/action_controller/metal/strong_parameters.rb, line 175
Возвращает true, если заданный ключ присутствует в параметрах.
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 183
Возвращает новый массив ключей параметров.
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 714
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 722 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 522
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 или 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
Обратите внимание, что если вы используете 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 370
def permit!
each_pair do |key, value|
Array.wrap(value).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 354 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 695 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 700 def reject!(&block) @parameters.reject!(&block) self end
Удаляет элементы, для которых блок возвращает true, и возвращает self.
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 431
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 729
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 737
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 682 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 687 def select!(&block) @parameters.select!(&block) self end
Эквивалент Hash#keep_if, но возвращает nil , если изменений не было.
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 600 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 606 def slice!(*keys) @parameters.slice!(*keys) self end
Возвращает текущий ActionController::Parameters экземпляр, который содержит только указанные keys.
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 261
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 unfiltered 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 281 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 unfiltered 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 308 def to_query(*args) to_h.to_query(*args) end
Возвращает строковое представление получателя, подходящее для использования в строке запроса URL:
params = ActionController::Parameters.new({
name: "David",
nationality: "Danish"
})
params.to_query
# => "name=David&nationality=Danish"
Можно передать необязательное имя пространства, чтобы заключить имена ключей:
params = ActionController::Parameters.new({
name: "David",
nationality: "Danish"
})
params.to_query("user")
# => "user%5Bname%5D=David&user%5Bnationality%5D=Danish"
Строки пар «ключ=значение», образующие строку запроса, отсортированы в лексикографическом порядке по возрастанию.
Этот метод также имеет алиас to_param.
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 190
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 323 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 655
def transform_keys(&block)
if block
new_instance_with_inherited_permitted_status(
@parameters.transform_keys(&block)
)
else
@parameters.transform_keys
end
end Возвращает новый ActionController::Parameters экземпляр с результатами выполнения block один раз для каждого ключа. Значения не изменяются.
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 667 def transform_keys!(&block) @parameters.transform_keys!(&block) self end
Выполняет преобразование ключей и возвращает измененный ActionController::Parameters экземпляр.
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 636
def transform_values(&block)
if block
new_instance_with_inherited_permitted_status(
@parameters.transform_values(&block)
)
else
@parameters.transform_values
end
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 648 def transform_values!(&block) @parameters.transform_values!(&block) self end
Выполняет преобразование значений и возвращает измененный ActionController::Parameters экземпляр.
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 198
Возвращает true, если заданное значение присутствует для какого-либо ключа в параметрах.
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 205 delegate :keys, :key?, :has_key?, :values, :has_value?, :value?, :empty?, :include?, :as_json, :to_s, to: :@parameters
Возвращает новый массив значений параметров.
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 708 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 794
def fields_for_style?
@parameters.all? { |k, v| k =~ /\A-?\d+\z/ && (v.is_a?(Hash) || v.is_a?(Parameters)) }
end # File actionpack/lib/action_controller/metal/strong_parameters.rb, line 790 def permitted=(new_permitted) @permitted = new_permitted end
© 2004–2018 David Heinemeier Hansson
Licensed under the MIT License.