aboutsummaryrefslogtreecommitdiffstats
path: root/actionpack/lib/action_controller/abstract
diff options
context:
space:
mode:
Diffstat (limited to 'actionpack/lib/action_controller/abstract')
-rw-r--r--actionpack/lib/action_controller/abstract/base.rb6
-rw-r--r--actionpack/lib/action_controller/abstract/benchmarker.rb28
-rw-r--r--actionpack/lib/action_controller/abstract/callbacks.rb11
-rw-r--r--actionpack/lib/action_controller/abstract/helpers.rb27
-rw-r--r--actionpack/lib/action_controller/abstract/layouts.rb52
-rw-r--r--actionpack/lib/action_controller/abstract/logger.rb1
-rw-r--r--actionpack/lib/action_controller/abstract/renderer.rb24
7 files changed, 117 insertions, 32 deletions
diff --git a/actionpack/lib/action_controller/abstract/base.rb b/actionpack/lib/action_controller/abstract/base.rb
index 1f2f096dae..0e4803388a 100644
--- a/actionpack/lib/action_controller/abstract/base.rb
+++ b/actionpack/lib/action_controller/abstract/base.rb
@@ -68,11 +68,11 @@ module AbstractController
self.response_obj = {}
end
- def process(action_name)
- @_action_name = action_name = action_name.to_s
+ def process(action)
+ @_action_name = action_name = action.to_s
unless action_name = method_for_action(action_name)
- raise ActionNotFound, "The action '#{action_name}' could not be found"
+ raise ActionNotFound, "The action '#{action}' could not be found"
end
process_action(action_name)
diff --git a/actionpack/lib/action_controller/abstract/benchmarker.rb b/actionpack/lib/action_controller/abstract/benchmarker.rb
new file mode 100644
index 0000000000..9f5889c704
--- /dev/null
+++ b/actionpack/lib/action_controller/abstract/benchmarker.rb
@@ -0,0 +1,28 @@
+module AbstractController
+ module Benchmarker
+ extend ActiveSupport::DependencyModule
+
+ depends_on Logger
+
+ module ClassMethods
+ def benchmark(title, log_level = ::Logger::DEBUG, use_silence = true)
+ if logger && logger.level >= log_level
+ result = nil
+ ms = Benchmark.ms { result = use_silence ? silence { yield } : yield }
+ logger.add(log_level, "#{title} (#{('%.1f' % ms)}ms)")
+ result
+ else
+ yield
+ end
+ end
+
+ # Silences the logger for the duration of the block.
+ def silence
+ old_logger_level, logger.level = logger.level, ::Logger::ERROR if logger
+ yield
+ ensure
+ logger.level = old_logger_level if logger
+ end
+ end
+ end
+end \ No newline at end of file
diff --git a/actionpack/lib/action_controller/abstract/callbacks.rb b/actionpack/lib/action_controller/abstract/callbacks.rb
index 51b968c694..e4f9dd3112 100644
--- a/actionpack/lib/action_controller/abstract/callbacks.rb
+++ b/actionpack/lib/action_controller/abstract/callbacks.rb
@@ -36,6 +36,17 @@ module AbstractController
process_action_callback(:#{filter}, name, options)
end
end
+
+ def skip_#{filter}_filter(*names, &blk)
+ options = names.last.is_a?(Hash) ? names.pop : {}
+ _normalize_callback_options(options)
+ names.push(blk) if block_given?
+ names.each do |name|
+ skip_process_action_callback(:#{filter}, name, options)
+ end
+ end
+
+ alias_method :append_#{filter}_filter, :#{filter}_filter
RUBY_EVAL
end
end
diff --git a/actionpack/lib/action_controller/abstract/helpers.rb b/actionpack/lib/action_controller/abstract/helpers.rb
index 968d3080c1..41decfd0c7 100644
--- a/actionpack/lib/action_controller/abstract/helpers.rb
+++ b/actionpack/lib/action_controller/abstract/helpers.rb
@@ -24,11 +24,30 @@ module AbstractController
super
end
-
+
+ # Makes all the (instance) methods in the helper module available to templates rendered through this controller.
+ # See ActionView::Helpers (link:classes/ActionView/Helpers.html) for more about making your own helper modules
+ # available to the templates.
def add_template_helper(mod)
master_helper_module.module_eval { include mod }
end
-
+
+ # Declare a controller method as a helper. For example, the following
+ # makes the +current_user+ controller method available to the view:
+ # class ApplicationController < ActionController::Base
+ # helper_method :current_user, :logged_in?
+ #
+ # def current_user
+ # @current_user ||= User.find_by_id(session[:user])
+ # end
+ #
+ # def logged_in?
+ # current_user != nil
+ # end
+ # end
+ #
+ # In a view:
+ # <% if logged_in? -%>Welcome, <%= current_user.name %><% end -%>
def helper_method(*meths)
meths.flatten.each do |meth|
master_helper_module.class_eval <<-ruby_eval, __FILE__, __LINE__ + 1
@@ -39,14 +58,14 @@ module AbstractController
end
end
- def helper(*args, &blk)
+ def helper(*args, &block)
args.flatten.each do |arg|
case arg
when Module
add_template_helper(arg)
end
end
- master_helper_module.module_eval(&blk) if block_given?
+ master_helper_module.module_eval(&block) if block_given?
end
end
diff --git a/actionpack/lib/action_controller/abstract/layouts.rb b/actionpack/lib/action_controller/abstract/layouts.rb
index 35d5e85ed9..3d6810bda9 100644
--- a/actionpack/lib/action_controller/abstract/layouts.rb
+++ b/actionpack/lib/action_controller/abstract/layouts.rb
@@ -4,11 +4,19 @@ module AbstractController
depends_on Renderer
+ included do
+ extlib_inheritable_accessor :_layout_conditions
+ self._layout_conditions = {}
+ end
+
module ClassMethods
- def layout(layout)
+ def layout(layout, conditions = {})
unless [String, Symbol, FalseClass, NilClass].include?(layout.class)
raise ArgumentError, "Layouts must be specified as a String, Symbol, false, or nil"
end
+
+ conditions.each {|k, v| conditions[k] = Array(v).map {|a| a.to_s} }
+ self._layout_conditions = conditions
@_layout = layout || false # Converts nil to false
_write_layout_method
@@ -31,15 +39,15 @@ module AbstractController
def _write_layout_method
case @_layout
when String
- self.class_eval %{def _layout() #{@_layout.inspect} end}
+ self.class_eval %{def _layout(details) #{@_layout.inspect} end}
when Symbol
- self.class_eval %{def _layout() #{@_layout} end}
+ self.class_eval %{def _layout(details) #{@_layout} end}
when false
- self.class_eval %{def _layout() end}
+ self.class_eval %{def _layout(details) end}
else
self.class_eval %{
- def _layout
- if view_paths.find_by_parts?("#{_implied_layout_name}", {:formats => formats}, "layouts")
+ def _layout(details)
+ if view_paths.find_by_parts?("#{_implied_layout_name}", details, "layouts")
"#{_implied_layout_name}"
else
super
@@ -49,38 +57,50 @@ module AbstractController
end
end
end
-
- def _render_template(template, options)
- _action_view._render_template_from_controller(template, options[:_layout], options, options[:_partial])
- end
private
- def _layout() end # This will be overwritten
+ def _layout(details) end # This will be overwritten
# :api: plugin
# ====
# Override this to mutate the inbound layout name
- def _layout_for_name(name)
+ def _layout_for_name(name, details = {:formats => formats})
unless [String, FalseClass, NilClass].include?(name.class)
raise ArgumentError, "String, false, or nil expected; you passed #{name.inspect}"
end
- name && view_paths.find_by_parts(name, {:formats => formats}, "layouts")
+ name && view_paths.find_by_parts(name, details, _layout_prefix(name))
+ end
+
+ # TODO: Decide if this is the best hook point for the feature
+ def _layout_prefix(name)
+ "layouts"
end
- def _default_layout(require_layout = false)
- if require_layout && !_layout
+ def _default_layout(require_layout = false, details = {:formats => formats})
+ if require_layout && _action_has_layout? && !_layout(details)
raise ArgumentError,
"There was no default layout for #{self.class} in #{view_paths.inspect}"
end
begin
- layout = _layout_for_name(_layout)
+ _layout_for_name(_layout(details), details) if _action_has_layout?
rescue NameError => e
raise NoMethodError,
"You specified #{@_layout.inspect} as the layout, but no such method was found"
end
end
+
+ def _action_has_layout?
+ conditions = _layout_conditions
+ if only = conditions[:only]
+ only.include?(action_name)
+ elsif except = conditions[:except]
+ !except.include?(action_name)
+ else
+ true
+ end
+ end
end
end \ No newline at end of file
diff --git a/actionpack/lib/action_controller/abstract/logger.rb b/actionpack/lib/action_controller/abstract/logger.rb
index 750a5c9fb6..980ede0bed 100644
--- a/actionpack/lib/action_controller/abstract/logger.rb
+++ b/actionpack/lib/action_controller/abstract/logger.rb
@@ -1,4 +1,5 @@
require 'active_support/core_ext/class/attribute_accessors'
+require 'active_support/core_ext/logger'
module AbstractController
module Logger
diff --git a/actionpack/lib/action_controller/abstract/renderer.rb b/actionpack/lib/action_controller/abstract/renderer.rb
index f2044a35ec..d7c68549e1 100644
--- a/actionpack/lib/action_controller/abstract/renderer.rb
+++ b/actionpack/lib/action_controller/abstract/renderer.rb
@@ -33,16 +33,12 @@ module AbstractController
#
# :api: plugin
def render_to_body(options = {})
- name = options[:_template_name] || action_name
-
# TODO: Refactor so we can just use the normal template logic for this
if options[:_partial_object]
_action_view._render_partial_from_controller(options)
- else
- options[:_template] ||= view_paths.find_by_parts(name.to_s, {:formats => formats},
- options[:_prefix], options[:_partial])
-
- _render_template(options[:_template], options)
+ else
+ _determine_template(options)
+ _render_template(options)
end
end
@@ -56,8 +52,8 @@ module AbstractController
AbstractController::Renderer.body_to_s(render_to_body(options))
end
- def _render_template(template, options)
- _action_view._render_template_from_controller(template, nil, options, options[:_partial])
+ def _render_template(options)
+ _action_view._render_template_from_controller(options[:_template], options[:_layout], options, options[:_partial])
end
def view_paths() _view_paths end
@@ -74,6 +70,16 @@ module AbstractController
end
end
+ private
+
+ def _determine_template(options)
+ name = (options[:_template_name] || action_name).to_s
+
+ options[:_template] ||= view_paths.find_by_parts(
+ name, { :formats => formats }, options[:_prefix], options[:_partial]
+ )
+ end
+
module ClassMethods
def append_view_path(path)