mirror of https://github.com/rails/rails
Merge pull request #45369 from seanpdoyle/action-controller-parameters-deep-merge
Support `ActionController::Parameters#deep_merge`
This commit is contained in:
commit
99cf11cca4
|
@ -1,3 +1,8 @@
|
||||||
|
* Add support for `#deep_merge` and `#deep_merge!` to
|
||||||
|
`ActionController::Parameters`.
|
||||||
|
|
||||||
|
*Sean Doyle*
|
||||||
|
|
||||||
## Rails 7.1.0.beta1 (September 13, 2023) ##
|
## Rails 7.1.0.beta1 (September 13, 2023) ##
|
||||||
|
|
||||||
* `AbstractController::Translation.raise_on_missing_translations` removed
|
* `AbstractController::Translation.raise_on_missing_translations` removed
|
||||||
|
|
|
@ -4,6 +4,7 @@ require "active_support/core_ext/hash/indifferent_access"
|
||||||
require "active_support/core_ext/array/wrap"
|
require "active_support/core_ext/array/wrap"
|
||||||
require "active_support/core_ext/string/filters"
|
require "active_support/core_ext/string/filters"
|
||||||
require "active_support/core_ext/object/to_query"
|
require "active_support/core_ext/object/to_query"
|
||||||
|
require "active_support/deep_mergeable"
|
||||||
require "action_dispatch/http/upload"
|
require "action_dispatch/http/upload"
|
||||||
require "rack/test"
|
require "rack/test"
|
||||||
require "stringio"
|
require "stringio"
|
||||||
|
@ -137,6 +138,8 @@ module ActionController
|
||||||
# params[:key] # => "value"
|
# params[:key] # => "value"
|
||||||
# params["key"] # => "value"
|
# params["key"] # => "value"
|
||||||
class Parameters
|
class Parameters
|
||||||
|
include ActiveSupport::DeepMergeable
|
||||||
|
|
||||||
cattr_accessor :permit_all_parameters, instance_accessor: false, default: false
|
cattr_accessor :permit_all_parameters, instance_accessor: false, default: false
|
||||||
|
|
||||||
cattr_accessor :action_on_unpermitted_parameters, instance_accessor: false
|
cattr_accessor :action_on_unpermitted_parameters, instance_accessor: false
|
||||||
|
@ -853,13 +856,41 @@ module ActionController
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
##
|
||||||
|
# :call-seq: merge!(other_hash)
|
||||||
|
#
|
||||||
# Returns the current +ActionController::Parameters+ instance with
|
# Returns the current +ActionController::Parameters+ instance with
|
||||||
# +other_hash+ merged into current hash.
|
# +other_hash+ merged into current hash.
|
||||||
def merge!(other_hash)
|
def merge!(other_hash, &block)
|
||||||
@parameters.merge!(other_hash.to_h)
|
@parameters.merge!(other_hash.to_h, &block)
|
||||||
self
|
self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
##
|
||||||
|
# :method: deep_merge
|
||||||
|
# :call-seq: deep_merge(other_hash, &block)
|
||||||
|
#
|
||||||
|
# Returns a new +ActionController::Parameters+ instance with +self+ and +other_hash+ merged recursively.
|
||||||
|
#
|
||||||
|
# Like with +Hash#merge+ in the standard library, a block can be provided
|
||||||
|
# to merge values.
|
||||||
|
#
|
||||||
|
#--
|
||||||
|
# Implemented by ActiveSupport::DeepMergeable#deep_merge.
|
||||||
|
|
||||||
|
##
|
||||||
|
# :method: deep_merge!
|
||||||
|
# :call-seq: deep_merge!(other_hash, &block)
|
||||||
|
#
|
||||||
|
# Same as +#deep_merge+, but modifies +self+.
|
||||||
|
#
|
||||||
|
#--
|
||||||
|
# Implemented by ActiveSupport::DeepMergeable#deep_merge!.
|
||||||
|
|
||||||
|
def deep_merge?(other_hash) # :nodoc
|
||||||
|
other_hash.is_a?(ActiveSupport::DeepMergeable)
|
||||||
|
end
|
||||||
|
|
||||||
# Returns a new +ActionController::Parameters+ instance with all keys
|
# Returns a new +ActionController::Parameters+ instance with all keys
|
||||||
# from current hash merged into +other_hash+.
|
# from current hash merged into +other_hash+.
|
||||||
def reverse_merge(other_hash)
|
def reverse_merge(other_hash)
|
||||||
|
|
|
@ -319,6 +319,62 @@ class ParametersPermitTest < ActiveSupport::TestCase
|
||||||
assert_equal "32", @params[:person][:age]
|
assert_equal "32", @params[:person][:age]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
test "not permitted is sticky beyond deep merges" do
|
||||||
|
assert_not_predicate @params.deep_merge(a: "b"), :permitted?
|
||||||
|
end
|
||||||
|
|
||||||
|
test "permitted is sticky beyond deep merges" do
|
||||||
|
@params.permit!
|
||||||
|
assert_predicate @params.deep_merge(a: "b"), :permitted?
|
||||||
|
end
|
||||||
|
|
||||||
|
test "not permitted is sticky beyond deep_merge!" do
|
||||||
|
assert_not_predicate @params.deep_merge!(a: "b"), :permitted?
|
||||||
|
end
|
||||||
|
|
||||||
|
test "permitted is sticky beyond deep_merge!" do
|
||||||
|
@params.permit!
|
||||||
|
assert_predicate @params.deep_merge!(a: "b"), :permitted?
|
||||||
|
end
|
||||||
|
|
||||||
|
test "deep_merge with other Hash" do
|
||||||
|
first, last = @params.dig(:person, :name).values_at(:first, :last)
|
||||||
|
merged_params = @params.deep_merge(person: { name: { last: "A." } })
|
||||||
|
|
||||||
|
assert_equal first, merged_params.dig(:person, :name, :first)
|
||||||
|
assert_not_equal last, merged_params.dig(:person, :name, :last)
|
||||||
|
assert_equal "A.", merged_params.dig(:person, :name, :last)
|
||||||
|
end
|
||||||
|
|
||||||
|
test "deep_merge! with other Hash" do
|
||||||
|
first, last = @params.dig(:person, :name).values_at(:first, :last)
|
||||||
|
@params.deep_merge!(person: { name: { last: "A." } })
|
||||||
|
|
||||||
|
assert_equal first, @params.dig(:person, :name, :first)
|
||||||
|
assert_not_equal last, @params.dig(:person, :name, :last)
|
||||||
|
assert_equal "A.", @params.dig(:person, :name, :last)
|
||||||
|
end
|
||||||
|
|
||||||
|
test "deep_merge with other Parameters" do
|
||||||
|
first, last = @params.dig(:person, :name).values_at(:first, :last)
|
||||||
|
other_params = ActionController::Parameters.new(person: { name: { last: "A." } }).permit!
|
||||||
|
merged_params = @params.deep_merge(other_params)
|
||||||
|
|
||||||
|
assert_equal first, merged_params.dig(:person, :name, :first)
|
||||||
|
assert_not_equal last, merged_params.dig(:person, :name, :last)
|
||||||
|
assert_equal "A.", merged_params.dig(:person, :name, :last)
|
||||||
|
end
|
||||||
|
|
||||||
|
test "deep_merge! with other Parameters" do
|
||||||
|
first, last = @params.dig(:person, :name).values_at(:first, :last)
|
||||||
|
other_params = ActionController::Parameters.new(person: { name: { last: "A." } }).permit!
|
||||||
|
@params.deep_merge!(other_params)
|
||||||
|
|
||||||
|
assert_equal first, @params.dig(:person, :name, :first)
|
||||||
|
assert_not_equal last, @params.dig(:person, :name, :last)
|
||||||
|
assert_equal "A.", @params.dig(:person, :name, :last)
|
||||||
|
end
|
||||||
|
|
||||||
test "#reverse_merge with parameters" do
|
test "#reverse_merge with parameters" do
|
||||||
default_params = ActionController::Parameters.new(id: "1234", person: {}).permit!
|
default_params = ActionController::Parameters.new(id: "1234", person: {}).permit!
|
||||||
merged_params = @params.reverse_merge(default_params)
|
merged_params = @params.reverse_merge(default_params)
|
||||||
|
|
Loading…
Reference in New Issue