From 32876476a714581377f7605539c9718883ce9907 Mon Sep 17 00:00:00 2001 From: David Heinemeier Hansson Date: Thu, 3 Jan 2008 15:49:59 +0000 Subject: [PATCH] Refactored ActionController::Verification and improved docs (closes #10681) [jamesh] git-svn-id: http://svn-commit.rubyonrails.org/rails/trunk@8543 5ecf4fe2-1ee6-0310-87b1-e25e094e27de --- .../lib/action_controller/verification.rb | 132 ++++++++++-------- 1 file changed, 74 insertions(+), 58 deletions(-) diff --git a/actionpack/lib/action_controller/verification.rb b/actionpack/lib/action_controller/verification.rb index e5045fba7c..9f606e7b7c 100644 --- a/actionpack/lib/action_controller/verification.rb +++ b/actionpack/lib/action_controller/verification.rb @@ -43,72 +43,88 @@ module ActionController #:nodoc: # the user is redirected to a different action. The +options+ parameter # is a hash consisting of the following key/value pairs: # - # * :params - a single key or an array of keys that must - # be in the params hash in order for the action(s) to be safely - # called. - # * :session - a single key or an array of keys that must - # be in the session in order for the action(s) to be safely called. - # * :flash - a single key or an array of keys that must - # be in the flash in order for the action(s) to be safely called. - # * :method - a single key or an array of keys--any one of which - # must match the current request method in order for the action(s) to - # be safely called. (The key should be a symbol: :get or - # :post, for example.) - # * :xhr - true/false option to ensure that the request is coming - # from an Ajax call or not. - # * :add_flash - a hash of name/value pairs that should be merged - # into the session's flash if the prerequisites cannot be satisfied. - # * :add_headers - a hash of name/value pairs that should be - # merged into the response's headers hash if the prerequisites cannot - # be satisfied. - # * :redirect_to - the redirection parameters to be used when - # redirecting if the prerequisites cannot be satisfied. You can - # redirect either to named route or to the action in some controller. - # * :render - the render parameters to be used when - # the prerequisites cannot be satisfied. - # * :only - only apply this verification to the actions specified - # in the associated array (may also be a single value). - # * :except - do not apply this verification to the actions - # specified in the associated array (may also be a single value). + # :params:: + # a single key or an array of keys that must be in the params + # hash in order for the action(s) to be safely called. + # :session:: + # a single key or an array of keys that must be in the session + # in order for the action(s) to be safely called. + # :flash:: + # a single key or an array of keys that must be in the flash in order + # for the action(s) to be safely called. + # :method:: + # a single key or an array of keys--any one of which must match the + # current request method in order for the action(s) to be safely called. + # (The key should be a symbol: :get or :post, for + # example.) + # :xhr:: + # true/false option to ensure that the request is coming from an Ajax + # call or not. + # :add_flash:: + # a hash of name/value pairs that should be merged into the session's + # flash if the prerequisites cannot be satisfied. + # :add_headers:: + # a hash of name/value pairs that should be merged into the response's + # headers hash if the prerequisites cannot be satisfied. + # :redirect_to:: + # the redirection parameters to be used when redirecting if the + # prerequisites cannot be satisfied. You can redirect either to named + # route or to the action in some controller. + # :render:: + # the render parameters to be used when the prerequisites cannot be satisfied. + # :only:: + # only apply this verification to the actions specified in the associated + # array (may also be a single value). + # :except:: + # do not apply this verification to the actions specified in the associated + # array (may also be a single value). def verify(options={}) - filter_opts = { :only => options[:only], :except => options[:except] } - before_filter(filter_opts) do |c| + before_filter :only => options[:only], :except => options[:except] do |c| c.send! :verify_action, options end end end - def verify_action(options) #:nodoc: - prereqs_invalid = - [*options[:params] ].find { |v| params[v].nil? } || - [*options[:session]].find { |v| session[v].nil? } || - [*options[:flash] ].find { |v| flash[v].nil? } - - if !prereqs_invalid && options[:method] - prereqs_invalid ||= - [*options[:method]].all? { |v| request.method != v.to_sym } - end - - prereqs_invalid ||= (request.xhr? != options[:xhr]) unless options[:xhr].nil? - - if prereqs_invalid - flash.update(options[:add_flash]) if options[:add_flash] - response.headers.update(options[:add_headers]) if options[:add_headers] + private - unless performed? - case - when options[:render] - render(options[:render]) - when options[:redirect_to] - options[:redirect_to] = self.send!(options[:redirect_to]) if options[:redirect_to].is_a?(Symbol) - redirect_to(options[:redirect_to]) - else - head(:bad_request) - end - end + def verify_action(options) #:nodoc: + if prereqs_invalid?(options) + flash.update(options[:add_flash]) if options[:add_flash] + response.headers.update(options[:add_headers]) if options[:add_headers] + apply_remaining_actions(options) unless performed? + end + end + + def prereqs_invalid?(options) # :nodoc: + verify_presence_of_keys_in_hash_flash_or_params(options) || + verify_method(options) || + verify_request_xhr_status(options) + end + + def verify_presence_of_keys_in_hash_flash_or_params(options) # :nodoc: + [*options[:params] ].find { |v| params[v].nil? } || + [*options[:session]].find { |v| session[v].nil? } || + [*options[:flash] ].find { |v| flash[v].nil? } + end + + def verify_method(options) # :nodoc: + [*options[:method]].all? { |v| request.method != v.to_sym } if options[:method] + end + + def verify_request_xhr_status(options) # :nodoc: + request.xhr? != options[:xhr] unless options[:xhr].nil? + end + + def apply_redirect_to(redirect_to_option) # :nodoc: + redirect_to_option.is_a?(Symbol) ? self.send!(redirect_to_option) : redirect_to_option + end + + def apply_remaining_actions(options) # :nodoc: + case + when options[:render] ; render(options[:render]) + when options[:redirect_to] ; redirect_to(apply_redirect_to(options[:redirect_to])) + else head(:bad_request) end end - - private :verify_action end end \ No newline at end of file