diff options
Diffstat (limited to 'actionpack/lib/action_controller/abstract')
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) |