aboutsummaryrefslogtreecommitdiffstats
path: root/actionpack/lib
diff options
context:
space:
mode:
Diffstat (limited to 'actionpack/lib')
-rw-r--r--actionpack/lib/abstract_controller/base.rb35
-rw-r--r--actionpack/lib/abstract_controller/callbacks.rb2
-rw-r--r--actionpack/lib/action_controller/metal/http_authentication.rb28
-rw-r--r--actionpack/lib/action_controller/metal/implicit_render.rb24
-rw-r--r--actionpack/lib/action_controller/metal/mime_responds.rb4
-rw-r--r--actionpack/lib/action_controller/metal/responder.rb45
-rw-r--r--actionpack/lib/action_dispatch/routing/mapper.rb8
-rw-r--r--actionpack/lib/action_dispatch/testing/assertions/routing.rb6
8 files changed, 100 insertions, 52 deletions
diff --git a/actionpack/lib/abstract_controller/base.rb b/actionpack/lib/abstract_controller/base.rb
index c384fd0978..0951267fea 100644
--- a/actionpack/lib/abstract_controller/base.rb
+++ b/actionpack/lib/abstract_controller/base.rb
@@ -1,3 +1,4 @@
+require 'erubis'
require 'active_support/configurable'
require 'active_support/descendants_tracker'
require 'active_support/core_ext/module/anonymous'
@@ -18,6 +19,7 @@ module AbstractController
include ActiveSupport::Configurable
extend ActiveSupport::DescendantsTracker
+ undef_method :not_implemented
class << self
attr_reader :abstract
alias_method :abstract?, :abstract
@@ -128,20 +130,23 @@ module AbstractController
self.class.action_methods
end
- private
+ # Returns true if the name can be considered an action. This can
+ # be overridden in subclasses to modify the semantics of what
+ # can be considered an action.
+ #
+ # For instance, this is overriden by ActionController to add
+ # the implicit rendering feature.
+ #
+ # ==== Parameters
+ # * <tt>name</tt> - The name of an action to be tested
+ #
+ # ==== Returns
+ # * <tt>TrueClass</tt>, <tt>FalseClass</tt>
+ def action_method?(name)
+ self.class.action_methods.include?(name)
+ end
- # Returns true if the name can be considered an action. This can
- # be overridden in subclasses to modify the semantics of what
- # can be considered an action.
- #
- # ==== Parameters
- # * <tt>name</tt> - The name of an action to be tested
- #
- # ==== Returns
- # * <tt>TrueClass</tt>, <tt>FalseClass</tt>
- def action_method?(name)
- self.class.action_methods.include?(name)
- end
+ private
# Call the action. Override this in a subclass to modify the
# behavior around processing an action. This, and not #process,
@@ -160,8 +165,8 @@ module AbstractController
# If the action name was not found, but a method called "action_missing"
# was found, #method_for_action will return "_handle_action_missing".
# This method calls #action_missing with the current action name.
- def _handle_action_missing
- action_missing(@_action_name)
+ def _handle_action_missing(*args)
+ action_missing(@_action_name, *args)
end
# Takes an action name and returns the name of the method that will
diff --git a/actionpack/lib/abstract_controller/callbacks.rb b/actionpack/lib/abstract_controller/callbacks.rb
index 1943ca4436..95992c2698 100644
--- a/actionpack/lib/abstract_controller/callbacks.rb
+++ b/actionpack/lib/abstract_controller/callbacks.rb
@@ -14,7 +14,7 @@ module AbstractController
# Override AbstractController::Base's process_action to run the
# process_action callbacks around the normal behavior.
def process_action(method_name, *args)
- run_callbacks(:process_action, action_name) do
+ run_callbacks(:process_action, method_name) do
super
end
end
diff --git a/actionpack/lib/action_controller/metal/http_authentication.rb b/actionpack/lib/action_controller/metal/http_authentication.rb
index c305abf5eb..1d6df89007 100644
--- a/actionpack/lib/action_controller/metal/http_authentication.rb
+++ b/actionpack/lib/action_controller/metal/http_authentication.rb
@@ -8,9 +8,7 @@ module ActionController
# === Simple \Basic example
#
# class PostsController < ApplicationController
- # USER_NAME, PASSWORD = "dhh", "secret"
- #
- # before_filter :authenticate, :except => [ :index ]
+ # http_basic_authenticate_with :name => "dhh", :password => "secret", :except => :index
#
# def index
# render :text => "Everyone can see me!"
@@ -19,15 +17,7 @@ module ActionController
# def edit
# render :text => "I'm only accessible if you know the password"
# end
- #
- # private
- # def authenticate
- # authenticate_or_request_with_http_basic do |user_name, password|
- # user_name == USER_NAME && password == PASSWORD
- # end
- # end
- # end
- #
+ # end
#
# === Advanced \Basic example
#
@@ -115,6 +105,18 @@ module ActionController
extend self
module ControllerMethods
+ extend ActiveSupport::Concern
+
+ module ClassMethods
+ def http_basic_authenticate_with(options = {})
+ before_filter(options.except(:name, :password, :realm)) do
+ authenticate_or_request_with_http_basic(options[:realm] || "Application") do |name, password|
+ name == options[:name] && password == options[:password]
+ end
+ end
+ end
+ end
+
def authenticate_or_request_with_http_basic(realm = "Application", &login_procedure)
authenticate_with_http_basic(&login_procedure) || request_http_basic_authentication(realm)
end
@@ -378,7 +380,6 @@ module ActionController
#
# RewriteRule ^(.*)$ dispatch.fcgi [E=X-HTTP_AUTHORIZATION:%{HTTP:Authorization},QSA,L]
module Token
-
extend self
module ControllerMethods
@@ -458,6 +459,5 @@ module ActionController
controller.__send__ :render, :text => "HTTP Token: Access denied.\n", :status => :unauthorized
end
end
-
end
end
diff --git a/actionpack/lib/action_controller/metal/implicit_render.rb b/actionpack/lib/action_controller/metal/implicit_render.rb
index cfa7004048..3ec0c4c6a4 100644
--- a/actionpack/lib/action_controller/metal/implicit_render.rb
+++ b/actionpack/lib/action_controller/metal/implicit_render.rb
@@ -1,21 +1,21 @@
module ActionController
module ImplicitRender
- def send_action(*)
- ret = super
- default_render unless response_body
- ret
+ def send_action(method, *args)
+ if respond_to?(method, true)
+ ret = super
+ default_render unless response_body
+ ret
+ else
+ default_render
+ end
end
- def default_render
- render
+ def default_render(*args)
+ render(*args)
end
- def method_for_action(action_name)
- super || begin
- if template_exists?(action_name.to_s, _prefixes)
- "default_render"
- end
- end
+ def action_method?(action_name)
+ super || template_exists?(action_name.to_s, _prefixes)
end
end
end
diff --git a/actionpack/lib/action_controller/metal/mime_responds.rb b/actionpack/lib/action_controller/metal/mime_responds.rb
index 998bef6556..6469e24d36 100644
--- a/actionpack/lib/action_controller/metal/mime_responds.rb
+++ b/actionpack/lib/action_controller/metal/mime_responds.rb
@@ -189,7 +189,7 @@ module ActionController #:nodoc:
raise ArgumentError, "respond_to takes either types or a block, never both" if mimes.any? && block_given?
if response = retrieve_response_from_mimes(mimes, &block)
- response.call
+ response.call(nil)
end
end
@@ -262,7 +262,7 @@ module ActionController #:nodoc:
#
def retrieve_response_from_mimes(mimes=nil, &block)
mimes ||= collect_mimes_from_class_level
- collector = Collector.new(mimes) { default_render }
+ collector = Collector.new(mimes) { |options| default_render(options || {}) }
block.call(collector) if block_given?
if format = request.negotiate_mime(collector.order)
diff --git a/actionpack/lib/action_controller/metal/responder.rb b/actionpack/lib/action_controller/metal/responder.rb
index 4b45413cf8..59a3621f72 100644
--- a/actionpack/lib/action_controller/metal/responder.rb
+++ b/actionpack/lib/action_controller/metal/responder.rb
@@ -77,6 +77,37 @@ module ActionController #:nodoc:
#
# respond_with(@project, :manager, @task)
#
+ # === Custom options
+ #
+ # <code>respond_with</code> also allow you to pass options that are forwarded
+ # to the underlying render call. Those options are only applied success
+ # scenarios. For instance, you can do the following in the create method above:
+ #
+ # def create
+ # @project = Project.find(params[:project_id])
+ # @task = @project.comments.build(params[:task])
+ # flash[:notice] = 'Task was successfully created.' if @task.save
+ # respond_with(@project, @task, :status => 201)
+ # end
+ #
+ # This will return status 201 if the task was saved with success. If not,
+ # it will simply ignore the given options and return status 422 and the
+ # resource errors. To customize the failure scenario, you can pass a
+ # a block to <code>respond_with</code>:
+ #
+ # def create
+ # @project = Project.find(params[:project_id])
+ # @task = @project.comments.build(params[:task])
+ # respond_with(@project, @task, :status => 201) do |format|
+ # if @task.save
+ # flash[:notice] = 'Task was successfully created.'
+ # else
+ # format.html { render "some_special_template" }
+ # end
+ # end
+ # end
+ #
+ # Using <code>respond_with</code> with a block follows the same syntax as <code>respond_to</code>.
class Responder
attr_reader :controller, :request, :format, :resource, :resources, :options
@@ -131,7 +162,11 @@ module ActionController #:nodoc:
# responds to :to_format and display it.
#
def to_format
- default_render
+ if get? || !has_errors?
+ default_render
+ else
+ display_errors
+ end
rescue ActionView::MissingTemplate => e
api_behavior(e)
end
@@ -155,8 +190,6 @@ module ActionController #:nodoc:
if get?
display resource
- elsif has_errors?
- display resource.errors, :status => :unprocessable_entity
elsif post?
display resource, :status => :created, :location => api_location
elsif has_empty_resource_definition?
@@ -185,7 +218,7 @@ module ActionController #:nodoc:
# controller.
#
def default_render
- @default_response.call
+ @default_response.call(options)
end
# Display is just a shortcut to render a resource with the current format.
@@ -209,6 +242,10 @@ module ActionController #:nodoc:
controller.render given_options.merge!(options).merge!(format => resource)
end
+ def display_errors
+ controller.render format => resource.errors, :status => :unprocessable_entity
+ end
+
# Check whether the resource has errors.
#
def has_errors?
diff --git a/actionpack/lib/action_dispatch/routing/mapper.rb b/actionpack/lib/action_dispatch/routing/mapper.rb
index 14c424f24b..35be0b3a27 100644
--- a/actionpack/lib/action_dispatch/routing/mapper.rb
+++ b/actionpack/lib/action_dispatch/routing/mapper.rb
@@ -104,10 +104,16 @@ module ActionDispatch
@options.reverse_merge!(:controller => /.+?/)
end
+ # Add a constraint for wildcard route to make it non-greedy and match the
+ # optional format part of the route by default
+ if path.match(/\*([^\/]+)$/) && @options[:format] != false
+ @options.reverse_merge!(:"#{$1}" => /.+?/)
+ end
+
if @options[:format] == false
@options.delete(:format)
path
- elsif path.include?(":format") || path.end_with?('/') || path.match(/^\/?\*/)
+ elsif path.include?(":format") || path.end_with?('/')
path
else
"#{path}(.:format)"
diff --git a/actionpack/lib/action_dispatch/testing/assertions/routing.rb b/actionpack/lib/action_dispatch/testing/assertions/routing.rb
index 11e8c63fa0..b760db42e2 100644
--- a/actionpack/lib/action_dispatch/testing/assertions/routing.rb
+++ b/actionpack/lib/action_dispatch/testing/assertions/routing.rb
@@ -46,7 +46,7 @@ module ActionDispatch
expected_options.stringify_keys!
msg = build_message(message, "The recognized options <?> did not match <?>, difference: <?>",
request.path_parameters, expected_options, expected_options.diff(request.path_parameters))
- assert_block(msg) { request.path_parameters == expected_options }
+ assert_equal(expected_options, request.path_parameters, msg)
end
# Asserts that the provided options can be used to generate the provided path. This is the inverse of +assert_recognizes+.
@@ -84,11 +84,11 @@ module ActionDispatch
found_extras = options.reject {|k, v| ! extra_keys.include? k}
msg = build_message(message, "found extras <?>, not <?>", found_extras, extras)
- assert_block(msg) { found_extras == extras }
+ assert_equal(extras, found_extras, msg)
msg = build_message(message, "The generated path <?> did not match <?>", generated_path,
expected_path)
- assert_block(msg) { expected_path == generated_path }
+ assert_equal(expected_path, generated_path, msg)
end
# Asserts that path and options match both ways; in other words, it verifies that <tt>path</tt> generates