Skip to content

Commit

Permalink
Merge pull request rails#6 from rails/nested-params
Browse files Browse the repository at this point in the history
Nested params in `permit`
  • Loading branch information
dhh committed Mar 22, 2012
2 parents b1fe35a + 12ebf52 commit e2bb863
Show file tree
Hide file tree
Showing 2 changed files with 114 additions and 2 deletions.
36 changes: 34 additions & 2 deletions lib/action_controller/parameters.rb
Expand Up @@ -30,8 +30,32 @@ def required(key)
self[key].presence || raise(ActionController::ParameterMissing.new(key))
end

def permit(*keys)
slice(*keys).permit!
def permit(*filters)
params = self.class.new

filters.each do |filter|
case filter
when Symbol then
params[filter] = self[filter]
when Hash then
self.slice(*filter.keys).each do |key, value|
return unless value

key = key.to_sym

params[key] = each_element(value) do |value|
# filters are a Hash, so we expect value to be a Hash too
next if filter.is_a?(Hash) && !value.is_a?(Hash)

value = self.class.new(value) if !value.respond_to?(:permit)

value.permit(*Array.wrap(filter[key]))
end
end
end
end

params.permit!
end

def [](key)
Expand Down Expand Up @@ -59,6 +83,14 @@ def convert_hashes_to_parameters(key, value)
self[key] = self.class.new(value)
end
end

def each_element(object)
if object.is_a?(Array)
object.map { |el| yield el }.compact
else
yield object
end
end
end

module StrongParameters
Expand Down
80 changes: 80 additions & 0 deletions test/nested_parameters_test.rb
@@ -0,0 +1,80 @@
require 'test_helper'
require 'action_controller/parameters'

class NestedParametersTest < ActiveSupport::TestCase
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"
}],
details: {
pages: 200,
genre: "Tragedy"
}
},
magazine: "Mjallo!"
})

permitted = params.permit book: [ :title, { authors: [ :name ] }, { details: :pages } ]

assert 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_nil permitted[:book][:details][:genre]
assert_nil permitted[:book][:authors][1][:born]
assert_nil permitted[:magazine]
end

test "nested arrays with strings" do
params = ActionController::Parameters.new({
book: {
genres: ["Tragedy"]
}
})

permitted = params.permit book: :genres
assert_equal ["Tragedy"], permitted[:book][:genres]
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
end

0 comments on commit e2bb863

Please sign in to comment.