This repository has been archived by the owner. It is now read-only.

Allow multiple keys in call to require #117

Merged
merged 1 commit into from Apr 17, 2013
Jump to file or symbol
Failed to load files and symbols.
+61 −9
Split
View
@@ -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.
@@ -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)
@dhh

dhh Mar 27, 2013

Owner

Nix blank line.

+ 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
@@ -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
@@ -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
@@ -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