1
0
Fork 0
mirror of https://github.com/rails/rails.git synced 2022-11-09 12:12:34 -05:00

Changes to a dupped ActionController::Parameters mutate the original

When `ActionController::Parameters` is duplicated with `#dup`, it doesn't create a duplicate of the instance variables (e.g. `@parameters`) but rather maintains the reference (see <http://ruby-doc.org/core-2.3.1/Object.html>). Given that the parameters object is often manipulated as if it were a hash (e.g. with `#delete` and similar methods), this leads to unexpected behaviour, like the following:

```
params = ActionController::Parameters.new(foo: "bar")
duplicated_params = params.dup
duplicated_params.delete(:foo)

params == duplicated_params
```

This fixes the bug by defining a private `#initialize_copy` method, used internally by `#dup`, which makes a copy of `@parameters`.
This commit is contained in:
Tim Rogers 2016-07-07 10:48:13 +01:00
parent 6038a548fd
commit ba3dd5ca04
2 changed files with 30 additions and 0 deletions

View file

@ -783,6 +783,11 @@ module ActionController
end
end
end
def initialize_copy(source)
super
@parameters = source.instance_variable_get(:@parameters).dup
end
end
# == Strong \Parameters

View file

@ -0,0 +1,25 @@
require 'abstract_unit'
require 'action_controller/metal/strong_parameters'
class ParametersDupTest < ActiveSupport::TestCase
setup do
ActionController::Parameters.permit_all_parameters = false
@params = ActionController::Parameters.new(
person: {
age: '32',
name: {
first: 'David',
last: 'Heinemeier Hansson'
},
addresses: [{city: 'Chicago', state: 'Illinois'}]
}
)
end
test "changes on a duplicate do not affect the original" do
dupped_params = @params.dup
dupped_params.delete(:person)
assert_not_equal @params, dupped_params
end
end