класс 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 запросах.
Этот список используется, в частности, для фильтрации обычных запросов, String идёт первым для быстрого обхода общего случая.
Если вы измените этот список, пожалуйста, обновите API
permitвыше.
Атрибуты
Публичные Классовые Методы
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 235
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 242
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 551 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 557 def []=(key, value) @parameters[key] = value end
Присваивает значение заданному key. Указанный ключ всё равно может быть отфильтрован при вызове permit.
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 136
Возвращает хеш, который может использоваться как JSON-представление параметров.
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 350 def converted_arrays @converted_arrays ||= Set.new end
Атрибут, отслеживающий преобразованные массивы (если есть), чтобы избежать двойного циклирования в распространённом случае с разрешением + массовой привязкой. Определён в методе, чтобы инициализировать его только при необходимости.
Проверка членства всё ещё проходит цикл, но будет быстрее, чем наш собственный цикл, преобразующий значения. Кроме того, мы не будем создавать новый объект массива при каждом запросе.
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 790
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 683 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 596 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 336
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 144
Возвращает true, если параметры не содержат пар ключ/значение.
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 626 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 635 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 574
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 152
Возвращает true, если заданный ключ присутствует в параметрах.
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 160
Возвращает true, если заданное значение присутствует для какого-либо ключа в параметрах.
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 168
Возвращает true, если заданный ключ присутствует в параметрах.
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 758
def inspect
"<#{self.class} #{@parameters} permitted: #{@permitted}>"
end # File actionpack/lib/action_controller/metal/strong_parameters.rb, line 176
Возвращает true, если заданный ключ присутствует в параметрах.
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 184
Возвращает новый массив ключей параметров.
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 721
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 729 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 528
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 376
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 360 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 702 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 707 def reject!(&block) @parameters.reject!(&block) self end
Удаляет элементы, для которых блок возвращает true, и возвращает self.
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 437
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 736
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 745
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 689 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 694 def select!(&block) @parameters.select!(&block) self end
Эквивалентно Hash#keep_if, но возвращает nil если изменений не было.
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 609 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 615 def slice!(*keys) @parameters.slice!(*keys) self end
Возвращает текущий ActionController::Parameters экземпляр, содержащий только указанные keys.
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 262
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 282 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 314 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 192
Возвращает содержимое параметров в виде строки.
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 329 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 662
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 674 def transform_keys!(&block) @parameters.transform_keys!(&block) self end
Выполняет преобразование ключей и возвращает изменённый ActionController::Parameters экземпляр.
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 645
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 654
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 200
Возвращает true, если заданное значение присутствует для какого-либо ключа в параметрах.
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 207 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 715 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 803
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 799 def permitted=(new_permitted) @permitted = new_permitted end
© 2004–2018 David Heinemeier Hansson
Licensed under the MIT License.