Class: ActionController::Parameters

Inherits:
Object
  • Object
show all
Includes:
ActiveSupport::DeepMergeable
Defined in:
lib/action_controller/metal/strong_parameters.rb

Overview

# Action Controller Parameters

Allows you to choose which attributes should be permitted for mass updating and thus prevent accidentally exposing that which shouldn’t be exposed. Provides two methods for this purpose: #require and #permit. The former is used to mark parameters as required. The latter is used to set the parameter as permitted and limit which attributes should be allowed for mass updating.

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">

It provides two options that controls the top-level behavior of new instances:

  • ‘permit_all_parameters` - If it’s ‘true`, all the parameters will be permitted by default. The default is `false`.

  • ‘action_on_unpermitted_parameters` - Controls behavior when parameters that are not explicitly permitted are found. The default value is `:log` in test and development environments, `false` otherwise. The values can be:

    • ‘false` to take no action.

    • ‘:log` to emit an `ActiveSupport::Notifications.instrument` event on the `unpermitted_parameters.action_controller` topic and log at the DEBUG level.

    • ‘:raise` to raise an ActionController::UnpermittedParameters exception.

Examples:

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

Please note that these options *are not thread-safe*. In a multi-threaded environment they should only be set once at boot-time and never mutated at runtime.

You can fetch values of ‘ActionController::Parameters` using either `:key` or `“key”`.

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

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(parameters = {}, logging_context = {}) ⇒ Parameters

Returns a new ‘ActionController::Parameters` instance. Also, sets the `permitted` attribute to the default value of `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">


288
289
290
291
292
293
294
295
296
297
298
# File 'lib/action_controller/metal/strong_parameters.rb', line 288

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

Class Method Details

.allow_deprecated_parameters_hash_equalityObject



253
254
255
256
257
258
# File 'lib/action_controller/metal/strong_parameters.rb', line 253

def allow_deprecated_parameters_hash_equality
  ActionController.deprecator.warn <<-WARNING.squish
    `Rails.application.config.action_controller.allow_deprecated_parameters_hash_equality` is
    deprecated and will be removed in Rails 8.0.
  WARNING
end

.allow_deprecated_parameters_hash_equality=(value) ⇒ Object



260
261
262
263
264
265
# File 'lib/action_controller/metal/strong_parameters.rb', line 260

def allow_deprecated_parameters_hash_equality=(value)
  ActionController.deprecator.warn <<-WARNING.squish
    `Rails.application.config.action_controller.allow_deprecated_parameters_hash_equality`
    is deprecated and will be removed in Rails 8.0.
  WARNING
end

.hook_into_yaml_loadingObject

:nodoc:



932
933
934
935
936
937
938
# File 'lib/action_controller/metal/strong_parameters.rb', line 932

def self.hook_into_yaml_loading # :nodoc:
  # Wire up YAML format compatibility with Rails 4.2 and Psych 2.0.8 and 2.0.9+.
  # Makes the YAML parser call `init_with` when it encounters the keys below
  # instead of trying its own parsing routines.
  YAML.load_tags["!ruby/hash-with-ivars:ActionController::Parameters"] = name
  YAML.load_tags["!ruby/hash:ActionController::Parameters"] = name
end

.nested_attribute?(key, value) ⇒ Boolean

:nodoc:

Returns:

  • (Boolean)


267
268
269
# File 'lib/action_controller/metal/strong_parameters.rb', line 267

def nested_attribute?(key, value) # :nodoc:
  /\A-?\d+\z/.match?(key) && (value.is_a?(Hash) || value.is_a?(Parameters))
end

Instance Method Details

#==(other) ⇒ Object

Returns true if another ‘Parameters` object contains the same content and permitted flag.



302
303
304
305
306
307
308
# File 'lib/action_controller/metal/strong_parameters.rb', line 302

def ==(other)
  if other.respond_to?(:permitted?)
    permitted? == other.permitted? && parameters == other.parameters
  else
    super
  end
end

#[](key) ⇒ Object

Returns a parameter for the given ‘key`. If not found, returns `nil`.

params = ActionController::Parameters.new(person: { name: "Francesco" })
params[:person] # => #<ActionController::Parameters {"name"=>"Francesco"} permitted: false>
params[:none]   # => nil


670
671
672
# File 'lib/action_controller/metal/strong_parameters.rb', line 670

def [](key)
  convert_hashes_to_parameters(key, @parameters[key])
end

#[]=(key, value) ⇒ Object

Assigns a value to a given ‘key`. The given key may still get filtered out when #permit is called.



676
677
678
# File 'lib/action_controller/metal/strong_parameters.rb', line 676

def []=(key, value)
  @parameters[key] = value
end

#compactObject

Returns a new ‘ActionController::Parameters` instance with `nil` values removed.



847
848
849
# File 'lib/action_controller/metal/strong_parameters.rb', line 847

def compact
  new_instance_with_inherited_permitted_status(@parameters.compact)
end

#compact!Object

Removes all ‘nil` values in place and returns `self`, or `nil` if no changes were made.



853
854
855
# File 'lib/action_controller/metal/strong_parameters.rb', line 853

def compact!
  self if @parameters.compact!
end

#compact_blankObject

Returns a new ‘ActionController::Parameters` instance without the blank values. Uses Object#blank? for determining if a value is blank.



859
860
861
# File 'lib/action_controller/metal/strong_parameters.rb', line 859

def compact_blank
  reject { |_k, v| v.blank? }
end

#compact_blank!Object

Removes all blank values in place and returns self. Uses Object#blank? for determining if a value is blank.



865
866
867
# File 'lib/action_controller/metal/strong_parameters.rb', line 865

def compact_blank!
  reject! { |_k, v| v.blank? }
end

#converted_arraysObject

Attribute that keeps track of converted arrays, if any, to avoid double looping in the common use case permit + mass-assignment. Defined in a method to instantiate it only if needed.

Testing membership still loops, but it’s going to be faster than our own loop that converts values. Also, we are not going to build a new array object per fetch.



436
437
438
# File 'lib/action_controller/metal/strong_parameters.rb', line 436

def converted_arrays
  @converted_arrays ||= Set.new
end

#deep_dupObject

Returns a duplicate ‘ActionController::Parameters` instance with the same permitted parameters.



965
966
967
968
969
# File 'lib/action_controller/metal/strong_parameters.rb', line 965

def deep_dup
  self.class.new(@parameters.deep_dup, @logging_context).tap do |duplicate|
    duplicate.permitted = @permitted
  end
end

#deep_merge?(other_hash) ⇒ Boolean

:nodoc:

Returns:

  • (Boolean)


900
901
902
# File 'lib/action_controller/metal/strong_parameters.rb', line 900

def deep_merge?(other_hash) # :nodoc:
  other_hash.is_a?(ActiveSupport::DeepMergeable)
end

#deep_transform_keys(&block) ⇒ Object

Returns a new ‘ActionController::Parameters` instance with the results of running `block` once for every key. This includes the keys from the root hash and from all nested hashes and arrays. The values are unchanged.



797
798
799
800
801
# File 'lib/action_controller/metal/strong_parameters.rb', line 797

def deep_transform_keys(&block)
  new_instance_with_inherited_permitted_status(
    _deep_transform_keys_in_object(@parameters, &block).to_unsafe_h
  )
end

#deep_transform_keys!(&block) ⇒ Object

Returns the same ‘ActionController::Parameters` instance with changed keys. This includes the keys from the root hash and from all nested hashes and arrays. The values are unchanged.



806
807
808
809
# File 'lib/action_controller/metal/strong_parameters.rb', line 806

def deep_transform_keys!(&block)
  @parameters = _deep_transform_keys_in_object(@parameters, &block).to_unsafe_h
  self
end

#delete(key, &block) ⇒ Object

Deletes a key-value pair from ‘Parameters` and returns the value. If `key` is not found, returns `nil` (or, with optional code block, yields `key` and returns the result). This method is similar to #extract!, which returns the corresponding `ActionController::Parameters` object.



815
816
817
# File 'lib/action_controller/metal/strong_parameters.rb', line 815

def delete(key, &block)
  convert_value_to_parameters(@parameters.delete(key, &block))
end

#dig(*keys) ⇒ Object

Extracts the nested parameter from the given ‘keys` by calling `dig` at each step. Returns `nil` if any intermediate step is `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


714
715
716
717
# File 'lib/action_controller/metal/strong_parameters.rb', line 714

def dig(*keys)
  convert_hashes_to_parameters(keys.first, @parameters[keys.first])
  @parameters.dig(*keys)
end

#each_pair(&block) ⇒ Object Also known as: each

Convert all hashes in values into parameters, then yield each pair in the same way as ‘Hash#each_pair`.



403
404
405
406
407
408
409
410
# File 'lib/action_controller/metal/strong_parameters.rb', line 403

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

#each_value(&block) ⇒ Object

Convert all hashes in values into parameters, then yield each value in the same way as ‘Hash#each_value`.



415
416
417
418
419
420
421
422
# File 'lib/action_controller/metal/strong_parameters.rb', line 415

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

#encode_with(coder) ⇒ Object

:nodoc:



959
960
961
# File 'lib/action_controller/metal/strong_parameters.rb', line 959

def encode_with(coder) # :nodoc:
  coder.map = { "parameters" => @parameters, "permitted" => @permitted }
end

#eql?(other) ⇒ Boolean

Returns:

  • (Boolean)


310
311
312
313
314
# File 'lib/action_controller/metal/strong_parameters.rb', line 310

def eql?(other)
  self.class == other.class &&
    permitted? == other.permitted? &&
    parameters.eql?(other.parameters)
end

#except(*keys) ⇒ Object Also known as: without

Returns a new ‘ActionController::Parameters` instance that filters out the given `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>


742
743
744
# File 'lib/action_controller/metal/strong_parameters.rb', line 742

def except(*keys)
  new_instance_with_inherited_permitted_status(@parameters.except(*keys))
end

#extract!(*keys) ⇒ Object

Removes and returns the key/value pairs matching the given keys.

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>


752
753
754
# File 'lib/action_controller/metal/strong_parameters.rb', line 752

def extract!(*keys)
  new_instance_with_inherited_permitted_status(@parameters.extract!(*keys))
end

#extract_value(key, delimiter: "_") ⇒ Object

Returns parameter value for the given ‘key` separated by `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

Note that if the given ‘key`’s value contains blank elements, then the returned array will include empty strings.

params = ActionController::Parameters.new(tags: "ruby,rails,,web")
params.extract_value(:tags, delimiter: ",") # => ["ruby", "rails", "", "web"]


983
984
985
# File 'lib/action_controller/metal/strong_parameters.rb', line 983

def extract_value(key, delimiter: "_")
  @parameters[key]&.split(delimiter, -1)
end

#fetch(key, *args) ⇒ Object

Returns a parameter for the given ‘key`. If the `key` can’t be found, there are several options: With no other arguments, it will raise an ActionController::ParameterMissing error; if a second argument is given, then that is returned (converted to an instance of ‘ActionController::Parameters` if possible); if a block is given, then that will be run and its result returned.

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"


693
694
695
696
697
698
699
700
701
702
703
# File 'lib/action_controller/metal/strong_parameters.rb', line 693

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

#has_value?(value) ⇒ Boolean Also known as: value?

Returns true if the given value is present for some key in the parameters.

Returns:

  • (Boolean)


870
871
872
# File 'lib/action_controller/metal/strong_parameters.rb', line 870

def has_value?(value)
  each_value.include?(convert_value_to_parameters(value))
end

#hashObject



316
317
318
# File 'lib/action_controller/metal/strong_parameters.rb', line 316

def hash
  [self.class, @parameters, @permitted].hash
end

#init_with(coder) ⇒ Object

:nodoc:



941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
# File 'lib/action_controller/metal/strong_parameters.rb', line 941

def init_with(coder) # :nodoc:
  case coder.tag
  when "!ruby/hash:ActionController::Parameters"
    # YAML 2.0.8's format where hash instance variables weren't stored.
    @parameters = coder.map.with_indifferent_access
    @permitted  = false
  when "!ruby/hash-with-ivars:ActionController::Parameters"
    # YAML 2.0.9's Hash subclass format where keys and values were stored under an
    # elements hash and `permitted` within an ivars hash.
    @parameters = coder.map["elements"].with_indifferent_access
    @permitted  = coder.map["ivars"][:@permitted]
  when "!ruby/object:ActionController::Parameters"
    # YAML's Object format. Only needed because of the format backwards
    # compatibility above, otherwise equivalent to YAML's initialization.
    @parameters, @permitted = coder.map["parameters"], coder.map["permitted"]
  end
end

#inspectObject



928
929
930
# File 'lib/action_controller/metal/strong_parameters.rb', line 928

def inspect
  "#<#{self.class} #{@parameters} permitted: #{@permitted}>"
end

#keysObject

:method: to_s

:call-seq:

to_s()

Returns the content of the parameters as a string.



237
238
# File 'lib/action_controller/metal/strong_parameters.rb', line 237

delegate :keys, :empty?, :exclude?, :include?,
:as_json, :to_s, :each_key, to: :@parameters

#merge(other_hash) ⇒ Object

Returns a new ‘ActionController::Parameters` instance with all keys from `other_hash` merged into current hash.



884
885
886
887
888
# File 'lib/action_controller/metal/strong_parameters.rb', line 884

def merge(other_hash)
  new_instance_with_inherited_permitted_status(
    @parameters.merge(other_hash.to_h)
  )
end

#merge!(other_hash, &block) ⇒ Object

:call-seq: merge!(other_hash)

Returns the current ‘ActionController::Parameters` instance with `other_hash` merged into current hash.



895
896
897
898
# File 'lib/action_controller/metal/strong_parameters.rb', line 895

def merge!(other_hash, &block)
  @parameters.merge!(other_hash.to_h, &block)
  self
end

#permit(*filters) ⇒ Object

Returns a new ‘ActionController::Parameters` instance that includes only the given `filters` and sets the `permitted` attribute for the object to `true`. This is useful for limiting which attributes should be allowed for mass updating.

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

Only permitted scalars pass the filter. For example, given

params.permit(:name)

‘:name` passes if it is a key of `params` whose associated value is of type `String`, `Symbol`, `NilClass`, `Numeric`, `TrueClass`, `FalseClass`, `Date`, `Time`, `DateTime`, `StringIO`, `IO`, ActionDispatch::Http::UploadedFile or `Rack::Test::UploadedFile`. Otherwise, the key `:name` is filtered out.

You may declare that the parameter should be an array of permitted scalars by mapping it to an empty array:

params = ActionController::Parameters.new(tags: ["rails", "parameters"])
params.permit(tags: [])

Sometimes it is not possible or convenient to declare the valid keys of a hash parameter or its internal structure. Just map to an empty hash:

params.permit(preferences: {})

Be careful because this opens the door to arbitrary input. In this case, ‘permit` ensures values in the returned structure are permitted scalars and filters out anything else.

You can also use ‘permit` on nested parameters, like:

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

Note that if you use ‘permit` in a key that points to a hash, it won’t allow all the hash. You also need to specify which attributes inside the hash should be permitted.

params = ActionController::Parameters.new({
  person: {
    contact: {
      email: "[email protected]",
      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"=>"[email protected]", "phone"=>"555-1234"} permitted: true>} permitted: true>

If your parameters specify multiple parameters indexed by a number, you can permit each set of parameters under the numeric key to be the same using the same syntax as permitting a single item.

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

If you want to specify what keys you want from each numeric key, you can instead specify each one individually

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


648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
# File 'lib/action_controller/metal/strong_parameters.rb', line 648

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

#permit!Object

Sets the ‘permitted` attribute to `true`. This can be used to pass mass assignment. Returns `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">


462
463
464
465
466
467
468
469
470
471
# File 'lib/action_controller/metal/strong_parameters.rb', line 462

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?Boolean

Returns ‘true` if the parameter is permitted, `false` otherwise.

params = ActionController::Parameters.new
params.permitted? # => false
params.permit!
params.permitted? # => true

Returns:

  • (Boolean)


446
447
448
# File 'lib/action_controller/metal/strong_parameters.rb', line 446

def permitted?
  @permitted
end

#reject(&block) ⇒ Object

Returns a new ‘ActionController::Parameters` instance with items that the block evaluates to true removed.



834
835
836
# File 'lib/action_controller/metal/strong_parameters.rb', line 834

def reject(&block)
  new_instance_with_inherited_permitted_status(@parameters.reject(&block))
end

#reject!(&block) ⇒ Object Also known as: delete_if

Removes items that the block evaluates to true and returns self.



839
840
841
842
# File 'lib/action_controller/metal/strong_parameters.rb', line 839

def reject!(&block)
  @parameters.reject!(&block)
  self
end

#require(key) ⇒ Object Also known as: required

This method accepts both a single key and an array of keys.

When passed a single key, if it exists and its associated value is either present or the singleton ‘false`, returns said value:

ActionController::Parameters.new(person: { name: "Francesco" }).require(:person)
# => #<ActionController::Parameters {"name"=>"Francesco"} permitted: false>

Otherwise raises 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

When given an array of keys, the method tries to require each one of them in order. If it succeeds, an array with the respective return values is returned:

params = ActionController::Parameters.new(user: { ... }, profile: { ... })
user_params, profile_params = params.require([:user, :profile])

Otherwise, the method re-raises the first exception found:

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

Technically this method can be used to fetch terminal values:

# CAREFUL
params = ActionController::Parameters.new(person: { name: "Finn" })
name = params.require(:person).require(:name) # CAREFUL

but take into account that at some point those ones have to be permitted:

def person_params
  params.require(:person).permit(:name).tap do |person_params|
    person_params.require(:name) # SAFER
  end
end

for example.



522
523
524
525
526
527
528
529
530
# File 'lib/action_controller/metal/strong_parameters.rb', line 522

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

#reverse_merge(other_hash) ⇒ Object Also known as: with_defaults

Returns a new ‘ActionController::Parameters` instance with all keys from current hash merged into `other_hash`.



906
907
908
909
910
# File 'lib/action_controller/metal/strong_parameters.rb', line 906

def reverse_merge(other_hash)
  new_instance_with_inherited_permitted_status(
    other_hash.to_h.merge(@parameters)
  )
end

#reverse_merge!(other_hash) ⇒ Object Also known as: with_defaults!

Returns the current ‘ActionController::Parameters` instance with current hash merged into `other_hash`.



915
916
917
918
# File 'lib/action_controller/metal/strong_parameters.rb', line 915

def reverse_merge!(other_hash)
  @parameters.merge!(other_hash.to_h) { |key, left, right| left }
  self
end

#select(&block) ⇒ Object

Returns a new ‘ActionController::Parameters` instance with only items that the block evaluates to true.



821
822
823
# File 'lib/action_controller/metal/strong_parameters.rb', line 821

def select(&block)
  new_instance_with_inherited_permitted_status(@parameters.select(&block))
end

#select!(&block) ⇒ Object Also known as: keep_if

Equivalent to Hash#keep_if, but returns ‘nil` if no changes were made.



826
827
828
829
# File 'lib/action_controller/metal/strong_parameters.rb', line 826

def select!(&block)
  @parameters.select!(&block)
  self
end

#slice(*keys) ⇒ Object

Returns a new ‘ActionController::Parameters` instance that includes only the given `keys`. If the given `keys` don’t exist, returns an empty hash.

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>


725
726
727
# File 'lib/action_controller/metal/strong_parameters.rb', line 725

def slice(*keys)
  new_instance_with_inherited_permitted_status(@parameters.slice(*keys))
end

#slice!(*keys) ⇒ Object

Returns the current ‘ActionController::Parameters` instance which contains only the given `keys`.



731
732
733
734
# File 'lib/action_controller/metal/strong_parameters.rb', line 731

def slice!(*keys)
  @parameters.slice!(*keys)
  self
end

#stringify_keysObject

This is required by ActiveModel attribute assignment, so that user can pass ‘Parameters` to a mass assignment methods in a model. It should not matter as we are using `HashWithIndifferentAccess` internally.



924
925
926
# File 'lib/action_controller/metal/strong_parameters.rb', line 924

def stringify_keys # :nodoc:
  dup
end

#to_h(&block) ⇒ Object

Returns a safe ActiveSupport::HashWithIndifferentAccess representation of the parameters with all unpermitted keys removed.

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"}


332
333
334
335
336
337
338
# File 'lib/action_controller/metal/strong_parameters.rb', line 332

def to_h(&block)
  if permitted?
    convert_parameters_to_hashes(@parameters, :to_h, &block)
  else
    raise UnfilteredParameters
  end
end

#to_hashObject

Returns a safe ‘Hash` representation of the parameters with all unpermitted keys removed.

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"}


352
353
354
# File 'lib/action_controller/metal/strong_parameters.rb', line 352

def to_hash
  to_h.to_hash
end

#to_query(*args) ⇒ Object Also known as: to_param

Returns a string representation of the receiver suitable for use as a URL query string:

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"

An optional namespace can be passed to enclose key names:

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"

The string pairs ‘“key=value”` that conform the query string are sorted lexicographically in ascending order.



382
383
384
# File 'lib/action_controller/metal/strong_parameters.rb', line 382

def to_query(*args)
  to_h.to_query(*args)
end

#to_unsafe_hObject Also known as: to_unsafe_hash

Returns an unsafe, unfiltered ActiveSupport::HashWithIndifferentAccess representation of the parameters.

params = ActionController::Parameters.new({
  name: "Senjougahara Hitagi",
  oddity: "Heavy stone crab"
})
params.to_unsafe_h
# => {"name"=>"Senjougahara Hitagi", "oddity" => "Heavy stone crab"}


396
397
398
# File 'lib/action_controller/metal/strong_parameters.rb', line 396

def to_unsafe_h
  convert_parameters_to_hashes(@parameters, :to_unsafe_h)
end

#transform_keys(&block) ⇒ Object

Returns a new ‘ActionController::Parameters` instance with the results of running `block` once for every key. The values are unchanged.



779
780
781
782
783
784
# File 'lib/action_controller/metal/strong_parameters.rb', line 779

def transform_keys(&block)
  return to_enum(:transform_keys) unless block_given?
  new_instance_with_inherited_permitted_status(
    @parameters.transform_keys(&block)
  )
end

#transform_keys!(&block) ⇒ Object

Performs keys transformation and returns the altered ‘ActionController::Parameters` instance.



788
789
790
791
792
# File 'lib/action_controller/metal/strong_parameters.rb', line 788

def transform_keys!(&block)
  return to_enum(:transform_keys!) unless block_given?
  @parameters.transform_keys!(&block)
  self
end

#transform_valuesObject

Returns a new ‘ActionController::Parameters` instance with the results of running `block` once for every value. The keys are unchanged.

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>


762
763
764
765
766
767
# File 'lib/action_controller/metal/strong_parameters.rb', line 762

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

#transform_values!Object

Performs values transformation and returns the altered ‘ActionController::Parameters` instance.



771
772
773
774
775
# File 'lib/action_controller/metal/strong_parameters.rb', line 771

def transform_values!
  return to_enum(:transform_values!) unless block_given?
  @parameters.transform_values! { |v| yield convert_value_to_parameters(v) }
  self
end

#valuesObject

Returns a new array of the values of the parameters.



425
426
427
# File 'lib/action_controller/metal/strong_parameters.rb', line 425

def values
  to_enum(:each_value).to_a
end

#values_at(*keys) ⇒ Object

Returns values that were assigned to the given ‘keys`. Note that all the `Hash` objects will be converted to `ActionController::Parameters`.



878
879
880
# File 'lib/action_controller/metal/strong_parameters.rb', line 878

def values_at(*keys)
  convert_value_to_parameters(@parameters.values_at(*keys))
end