diff --git a/README.rdoc b/README.rdoc index 8c719bf..a046c36 100644 --- a/README.rdoc +++ b/README.rdoc @@ -35,6 +35,10 @@ You can also use permit on nested parameters, like: Thanks to Nick Kallen for the permit idea! +You can also easily permit similarly named parameters using regular expressions: + + params.permit(/^company_\d$/ => [:name, :location, /^quarter_\d_profit$/]) + == Todos * Automatically permit parameters coming from a signed form [Yehuda] diff --git a/lib/action_controller/parameters.rb b/lib/action_controller/parameters.rb index daaf901..fd5664c 100644 --- a/lib/action_controller/parameters.rb +++ b/lib/action_controller/parameters.rb @@ -39,19 +39,25 @@ def permit(*filters) case filter when Symbol then params[filter] = self[filter] if has_key?(filter) + when Regexp then + self.each do |key, value| + params[key] = self[key] if key =~ filter + end when Hash then - self.slice(*filter.keys).each do |key, value| + expanded_filter = expand_regexp_filters(filter) + + self.slice(*expanded_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) + next if expanded_filter.is_a?(Hash) && !value.is_a?(Hash) value = self.class.new(value) if !value.respond_to?(:permit) - value.permit(*Array.wrap(filter[key])) + value.permit(*Array.wrap(expanded_filter[key])) end end end @@ -97,6 +103,18 @@ def each_element(object) yield object end end + + def expand_regexp_filters(filter) + expanded_filter = filter.select{|k,v| !k.is_a?(Regexp) } + filter.each do |filter_key, filter_value| + if filter_key.is_a?(Regexp) + self.select {|k,v| k =~ filter_key }.each do |k, v| + expanded_filter[k] = filter_value + end + end + end + self.class.new(expanded_filter) + end end module StrongParameters diff --git a/test/regexp_parameters_test.rb b/test/regexp_parameters_test.rb new file mode 100644 index 0000000..b342d0d --- /dev/null +++ b/test/regexp_parameters_test.rb @@ -0,0 +1,36 @@ +require 'test_helper' +require 'action_controller/parameters' + +class RegexpParametersTest < ActiveSupport::TestCase + test "permitted parameters defined by regexp" do + params = ActionController::Parameters.new({ + :object_1 => { + :safe_param_1 => 'value', + :safe_param_2 => 'value', + :malicious => 'haxored!' + }, + :object_2 => { + :safe_param_1 => 'value', + :safe_param_2 => 'value', + :malicious => 'haxored!' + }, + :bad_object => { + :param => 'value' + } + }) + + expected = ActionController::Parameters.new({ + :object_1 => { + :safe_param_1 => 'value', + :safe_param_2 => 'value' + }, + :object_2 => { + :safe_param_1 => 'value', + :safe_param_2 => 'value' + } + }) + + permitted = params.permit(/^object_\d$/ => [/^safe_param_\d$/]) + assert_equal expected, permitted + end +end