Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Merge pull request #117 from d-Pixie/master

Allow multiple keys in call to require
  • Loading branch information...
commit 59f3365d9cf427fbc814dd830b5d8890ed874a5c 2 parents c789f57 + 7758a34
@dhh dhh authored
View
10 README.md
@@ -70,6 +70,16 @@ This declaration whitelists the `name`, `emails` and `friends` attributes. It is
Thanks to Nick Kallen for the permit idea!
+## Requiring multiple values
+
+In some cases you might want to require several parameters to be present before proceeding, such as for an API where the params might be a flat hash. You can use `require` to do this:
+
+``` ruby
+params.require(:username, :password).permit(:version)
+```
+
+When used with multiple inputs `require` raises a `ActionController::MissingParameter` error with *all* the missing attributes specified in the message. If no values are missing the params hash is returned unmodified.
+
## Handling of Unpermitted Keys
By default parameter keys that are not explicitly permitted will be logged in the development and test environment. In other environments these parameters will simply be filtered out and ignored.
View
29 lib/action_controller/parameters.rb
@@ -22,7 +22,7 @@ class UnpermittedParameters < IndexError
def initialize(params)
@params = params
- super("found unpermitted parameters: #{params.join(", ")}")
+ super("found unpermitted parameter(s): #{params.join(", ")}")
end
end
@@ -51,8 +51,12 @@ def permit!
self
end
- def require(key)
- self[key].presence || raise(ActionController::ParameterMissing.new(key))
+ def require(*keys)
+ if keys.many?
+ require_multiple(keys)
+ else
+ require_single(keys)
+ end
end
alias :required :require
@@ -98,6 +102,20 @@ def dup
end
protected
+ def require_single(keys)
+ key = keys.first
+ self[key].presence || raise(ActionController::ParameterMissing.new(key))
+ end
+
+ def require_multiple(keys)
+ missing_keys = keys.select do |key|
+ self[key].blank?
+ end
+
+ raise(ActionController::ParameterMissing.new(missing_keys.join(', '))) if missing_keys.compact.any?
+ self
+ end
+
def convert_value(value)
if value.class == Hash
self.class.new_from_hash_copying_default(value)
@@ -109,7 +127,6 @@ def convert_value(value)
end
private
-
def convert_hashes_to_parameters(key, value)
if value.is_a?(Parameters) || !value.is_a?(Hash)
value
@@ -217,7 +234,7 @@ def unpermitted_parameters!(params)
unpermitted_keys = unpermitted_keys(params)
if unpermitted_keys.any?
- case self.class.action_on_unpermitted_parameters
+ case self.class.action_on_unpermitted_parameters
when :log
name = "unpermitted_parameters.action_controller"
ActiveSupport::Notifications.instrument(name, :keys => unpermitted_keys)
@@ -237,7 +254,7 @@ module StrongParameters
included do
rescue_from(ActionController::ParameterMissing) do |parameter_missing_exception|
- render :text => "Required parameter missing: #{parameter_missing_exception.param}", :status => :bad_request
+ render :text => "Required parameter(s) missing: #{parameter_missing_exception.param}", :status => :bad_request
end
end
View
2  test/action_controller_required_params_test.rb
@@ -25,6 +25,6 @@ class ActionControllerRequiredParamsTest < ActionController::TestCase
test "missing parameters will be mentioned in the return" do
post :create, { :magazine => { :name => "Mjallo!" } }
- assert_equal "Required parameter missing: book", response.body
+ assert_match "book", response.body
end
end
View
4 test/log_on_unpermitted_params_test.rb
@@ -16,7 +16,7 @@ def teardown
:fishing => "Turnips"
})
- assert_logged("Unpermitted parameters: fishing") do
+ assert_logged("Unpermitted parameter(s): fishing") do
params.permit(:book => [:pages])
end
end
@@ -26,7 +26,7 @@ def teardown
:book => { :pages => 65, :title => "Green Cats and where to find then." }
})
- assert_logged("Unpermitted parameters: title") do
+ assert_logged("Unpermitted parameter(s): title") do
params.permit(:book => [:pages])
end
end
View
25 test/parameters_require_test.rb
@@ -7,4 +7,29 @@ class ParametersRequireTest < ActiveSupport::TestCase
ActionController::Parameters.new(:person => {}).require(:person)
end
end
+
+ test "permit multiple required parameters" do
+ params = ActionController::Parameters.new(:username => 'user', :password => '<3<3<3<3')
+ assert_nothing_raised(ActionController::ParameterMissing) do
+ params.require(:username, :password)
+ end
+
+ assert params.has_key?(:username)
+ assert params.has_key?(:password)
+ end
+
+ test "multiple required parameters must be present not merely not nil" do
+ params = ActionController::Parameters.new(:username => '', :password => nil)
+ assert_raises(ActionController::ParameterMissing) do
+ params.require(:username, :password)
+ end
+ end
+
+ test "all parameters are returned after required with multiple parameters" do
+ params = ActionController::Parameters.new(:username => 'user', :password => '<3<3<3<3', :version => 1)
+
+ params.require(:username, :password)
+
+ assert params.has_key?(:version)
+ end
end
Please sign in to comment.
Something went wrong with that request. Please try again.