1
0
Fork 0
mirror of https://github.com/rails/rails.git synced 2022-11-09 12:12:34 -05:00
rails--rails/actionpack/test/controller/parameters/nested_parameters_permit_test.rb

280 lines
9.7 KiB
Ruby
Raw Normal View History

# frozen_string_literal: true
require "abstract_unit"
require "action_controller/metal/strong_parameters"
class NestedParametersPermitTest < ActiveSupport::TestCase
def assert_filtered_out(params, key)
assert_not params.has_key?(key), "key #{key.inspect} has not been filtered out"
end
test "permitted nested parameters" do
params = ActionController::Parameters.new(
book: {
title: "Romeo and Juliet",
authors: [{
name: "William Shakespeare",
born: "1564-04-26"
}, {
name: "Christopher Marlowe"
}, {
2013-01-22 07:40:33 -05:00
name: %w(malicious injected names)
}],
details: {
pages: 200,
genre: "Tragedy"
},
id: {
isbn: "x"
}
},
magazine: "Mjallo!")
permitted = params.permit book: [ :title, { authors: [ :name ] }, { details: :pages }, :id ]
assert_predicate permitted, :permitted?
assert_equal "Romeo and Juliet", permitted[:book][:title]
assert_equal "William Shakespeare", permitted[:book][:authors][0][:name]
assert_equal "Christopher Marlowe", permitted[:book][:authors][1][:name]
assert_equal 200, permitted[:book][:details][:pages]
assert_filtered_out permitted, :magazine
assert_filtered_out permitted[:book], :id
assert_filtered_out permitted[:book][:details], :genre
assert_filtered_out permitted[:book][:authors][0], :born
assert_filtered_out permitted[:book][:authors][2], :name
end
test "permitted nested parameters with a string or a symbol as a key" do
params = ActionController::Parameters.new(
book: {
"authors" => [
{ name: "William Shakespeare", born: "1564-04-26" },
{ name: "Christopher Marlowe" }
]
})
permitted = params.permit book: [ { "authors" => [ :name ] } ]
assert_equal "William Shakespeare", permitted[:book]["authors"][0][:name]
assert_equal "William Shakespeare", permitted[:book][:authors][0][:name]
assert_equal "Christopher Marlowe", permitted[:book]["authors"][1][:name]
assert_equal "Christopher Marlowe", permitted[:book][:authors][1][:name]
permitted = params.permit book: [ { authors: [ :name ] } ]
assert_equal "William Shakespeare", permitted[:book]["authors"][0][:name]
assert_equal "William Shakespeare", permitted[:book][:authors][0][:name]
assert_equal "Christopher Marlowe", permitted[:book]["authors"][1][:name]
assert_equal "Christopher Marlowe", permitted[:book][:authors][1][:name]
end
test "nested arrays with strings" do
params = ActionController::Parameters.new(
book: {
2013-01-22 07:40:33 -05:00
genres: ["Tragedy"]
})
permitted = params.permit book: { genres: [] }
assert_equal ["Tragedy"], permitted[:book][:genres]
end
test "permit may specify symbols or strings" do
params = ActionController::Parameters.new(
book: {
2013-01-22 07:40:33 -05:00
title: "Romeo and Juliet",
author: "William Shakespeare"
},
magazine: "Shakespeare Today")
permitted = params.permit({ book: ["title", :author] }, "magazine")
assert_equal "Romeo and Juliet", permitted[:book][:title]
assert_equal "William Shakespeare", permitted[:book][:author]
assert_equal "Shakespeare Today", permitted[:magazine]
end
test "nested array with strings that should be hashes" do
params = ActionController::Parameters.new(
book: {
genres: ["Tragedy"]
})
permitted = params.permit book: { genres: :type }
assert_empty permitted[:book][:genres]
end
test "nested array with strings that should be hashes and additional values" do
params = ActionController::Parameters.new(
book: {
title: "Romeo and Juliet",
genres: ["Tragedy"]
})
permitted = params.permit book: [ :title, { genres: :type } ]
assert_equal "Romeo and Juliet", permitted[:book][:title]
assert_empty permitted[:book][:genres]
end
test "nested string that should be a hash" do
params = ActionController::Parameters.new(
book: {
genre: "Tragedy"
})
permitted = params.permit book: { genre: :type }
assert_nil permitted[:book][:genre]
end
test "nested params with numeric keys" do
params = ActionController::Parameters.new(
book: {
2013-01-22 07:40:33 -05:00
authors_attributes: {
2016-08-06 13:35:13 -04:00
'0': { name: "William Shakespeare", age_of_death: "52" },
'1': { name: "Unattributed Assistant" },
'2': { name: %w(injected names) }
}
})
2013-01-22 07:40:33 -05:00
permitted = params.permit book: { authors_attributes: [ :name ] }
assert_not_nil permitted[:book][:authors_attributes]["0"]
assert_not_nil permitted[:book][:authors_attributes]["1"]
assert_empty permitted[:book][:authors_attributes]["2"]
assert_equal "William Shakespeare", permitted[:book][:authors_attributes]["0"][:name]
assert_equal "Unattributed Assistant", permitted[:book][:authors_attributes]["1"][:name]
assert_equal(
2017-01-17 22:10:14 -05:00
{ "book" => { "authors_attributes" => { "0" => { "name" => "William Shakespeare" }, "1" => { "name" => "Unattributed Assistant" }, "2" => {} } } },
permitted.to_h
)
assert_filtered_out permitted[:book][:authors_attributes]["0"], :age_of_death
end
test "nested params with non_numeric keys" do
params = ActionController::Parameters.new(
book: {
authors_attributes: {
'0': { name: "William Shakespeare", age_of_death: "52" },
'1': { name: "Unattributed Assistant" },
'2': "Not a hash",
'new_record': { name: "Some name" }
}
})
permitted = params.permit book: { authors_attributes: [ :name ] }
assert_not_nil permitted[:book][:authors_attributes]["0"]
assert_not_nil permitted[:book][:authors_attributes]["1"]
assert_nil permitted[:book][:authors_attributes]["2"]
assert_nil permitted[:book][:authors_attributes]["new_record"]
assert_equal "William Shakespeare", permitted[:book][:authors_attributes]["0"][:name]
assert_equal "Unattributed Assistant", permitted[:book][:authors_attributes]["1"][:name]
assert_equal(
{ "book" => { "authors_attributes" => { "0" => { "name" => "William Shakespeare" }, "1" => { "name" => "Unattributed Assistant" } } } },
permitted.to_h
)
end
test "nested params with negative numeric keys" do
params = ActionController::Parameters.new(
book: {
2013-01-22 07:40:33 -05:00
authors_attributes: {
2016-08-06 13:35:13 -04:00
'-1': { name: "William Shakespeare", age_of_death: "52" },
'-2': { name: "Unattributed Assistant" }
}
})
2013-01-22 07:40:33 -05:00
permitted = params.permit book: { authors_attributes: [:name] }
assert_not_nil permitted[:book][:authors_attributes]["-1"]
assert_not_nil permitted[:book][:authors_attributes]["-2"]
assert_equal "William Shakespeare", permitted[:book][:authors_attributes]["-1"][:name]
assert_equal "Unattributed Assistant", permitted[:book][:authors_attributes]["-2"][:name]
assert_filtered_out permitted[:book][:authors_attributes]["-1"], :age_of_death
end
Allow permitting numeric params When specifying numeric parameters, strong params lets you permit them all using the same permitted params for each. For example params like, ```ruby book: { authors_attributes: { '0': { name: "William Shakespeare", age_of_death: "52" }, '1': { name: "Unattributed Assistant" }, '2': "Not a hash", 'new_record': { name: "Some name" } } } ``` can be permitted with, ``` permit book: { authors_attributes: [ :name ] } ``` This returns the name keys for each of the numeric keyed params that have a name field, ```ruby { "book" => { "authors_attributes" => { "0" => { "name" => "William Shakespeare" }, "1" => { "name" => "Unattributed Assistant" } } } } ``` This is exactly what you want most of the time. Rarely you might need to specify different keys for particular numeric attributes. This allows another strong params syntax for those cases where you can specify the keys allowed for each individual numerically keys attributes hash. After this change using the same params above, you can permit the name and age for only the `0` key and only the name for the `1` key, ```ruby permit book: { authors_attributes: { '1': [ :name ], '0': [ :name, :age_of_death ] } } ``` This returns exactly the parameters that you specify, ```ruby { "book" => { "authors_attributes" => { "0" => { "name" => "William Shakespeare", "age_of_death" => "52" }, "1" => { "name" => "Unattributed Assistant" } } } } ``` Sidenote: this allows `permit` to do the equivalent to ```ruby params.require(:book).permit(authors_attributes: { '1': [:name]}) ``` without raising when `book: ... ` is not present. The simpler syntax should be preferred, but in cases where you need more control, this is a nice option to have.
2021-06-15 17:08:16 -04:00
test "nested params with numeric keys addressing individual numeric keys" do
params = ActionController::Parameters.new(
book: {
authors_attributes: {
'0': { name: "William Shakespeare", age_of_death: "52" },
'1': { name: "Unattributed Assistant" },
'2': { name: %w(injected names) }
}
})
permitted = params.permit book: { authors_attributes: { '1': [ :name ], '0': [ :name, :age_of_death ] } }
assert_equal(
{ "book" => { "authors_attributes" => { "0" => { "name" => "William Shakespeare", "age_of_death" => "52" }, "1" => { "name" => "Unattributed Assistant" } } } },
permitted.to_h
)
end
test "nested params with numeric keys addressing individual numeric keys using require first" do
params = ActionController::Parameters.new(
book: {
authors_attributes: {
'0': { name: "William Shakespeare", age_of_death: "52" },
'1': { name: "Unattributed Assistant" },
'2': { name: %w(injected names) }
}
})
permitted = params.require(:book).permit(authors_attributes: { '1': [:name] })
assert_equal(
{ "authors_attributes" => { "1" => { "name" => "Unattributed Assistant" } } },
permitted.to_h
)
end
test "nested params with numeric keys addressing individual numeric keys to arrays" do
params = ActionController::Parameters.new(
book: {
authors_attributes: {
'0': ["draft 1", "draft 2", "draft 3"],
'1': ["final draft"],
'2': { name: %w(injected names) }
}
})
permitted = params.permit book: { authors_attributes: { '2': [ :name ], '0': [] } }
assert_equal(
{ "book" => { "authors_attributes" => { "2" => {}, "0" => ["draft 1", "draft 2", "draft 3"] } } },
permitted.to_h
)
end
test "nested params with numeric keys addressing individual numeric keys to more nested params" do
params = ActionController::Parameters.new(
book: {
authors_attributes: {
'0': ["draft 1", "draft 2", "draft 3"],
'1': ["final draft"],
'2': { name: { "projects" => [ "hamlet", "Othello" ] } }
}
})
permitted = params.permit book: { authors_attributes: { '2': { name: { projects: [] } }, '0': [] } }
assert_equal(
{ "book" => { "authors_attributes" => { "2" => { "name" => { "projects" => ["hamlet", "Othello"] } }, "0" => ["draft 1", "draft 2", "draft 3"] } } },
permitted.to_h
)
end
test "nested number as key" do
params = ActionController::Parameters.new(
product: {
properties: {
"0" => "prop0",
"1" => "prop1"
}
})
2016-08-06 13:35:13 -04:00
params = params.require(:product).permit(properties: ["0"])
assert_not_nil params[:properties]["0"]
assert_nil params[:properties]["1"]
assert_equal "prop0", params[:properties]["0"]
end
end