diff options
Diffstat (limited to 'actionpack/lib/abstract_controller')
-rw-r--r-- | actionpack/lib/abstract_controller/base.rb | 38 | ||||
-rw-r--r-- | actionpack/lib/abstract_controller/callbacks.rb | 4 | ||||
-rw-r--r-- | actionpack/lib/abstract_controller/helpers.rb | 24 | ||||
-rw-r--r-- | actionpack/lib/abstract_controller/layouts.rb | 6 | ||||
-rw-r--r-- | actionpack/lib/abstract_controller/rendering.rb | 99 | ||||
-rw-r--r-- | actionpack/lib/abstract_controller/view_paths.rb | 29 |
6 files changed, 118 insertions, 82 deletions
diff --git a/actionpack/lib/abstract_controller/base.rb b/actionpack/lib/abstract_controller/base.rb index 0951267fea..f67d0e558e 100644 --- a/actionpack/lib/abstract_controller/base.rb +++ b/actionpack/lib/abstract_controller/base.rb @@ -130,27 +130,39 @@ module AbstractController self.class.action_methods 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. + # Returns true if a method for the action is available and + # can be dispatched, false otherwise. # - # 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) + # Notice that <tt>action_methods.include?("foo")</tt> may return + # false and <tt>available_action?("foo")</tt> returns true because + # available action consider actions that are also available + # through other means, for example, implicit render ones. + def available_action?(action_name) + method_for_action(action_name).present? end private + # Returns true if the name can be considered an action because + # it has a method defined in the controller. + # + # ==== Parameters + # * <tt>name</tt> - The name of an action to be tested + # + # ==== Returns + # * <tt>TrueClass</tt>, <tt>FalseClass</tt> + # + # :api: private + def action_method?(name) + self.class.action_methods.include?(name) + end + # Call the action. Override this in a subclass to modify the # behavior around processing an action. This, and not #process, # is the intended way to override action dispatching. + # + # Notice that the first argument is the method to be dispatched + # which is *not* necessarily the same as the action name. def process_action(method_name, *args) send_action(method_name, *args) end diff --git a/actionpack/lib/abstract_controller/callbacks.rb b/actionpack/lib/abstract_controller/callbacks.rb index f7b2b7ff53..e8426bc52b 100644 --- a/actionpack/lib/abstract_controller/callbacks.rb +++ b/actionpack/lib/abstract_controller/callbacks.rb @@ -13,8 +13,8 @@ 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, method_name) do + def process_action(*args) + run_callbacks(:process_action, action_name) do super end end diff --git a/actionpack/lib/abstract_controller/helpers.rb b/actionpack/lib/abstract_controller/helpers.rb index 20f8601a8e..dc9778a416 100644 --- a/actionpack/lib/abstract_controller/helpers.rb +++ b/actionpack/lib/abstract_controller/helpers.rb @@ -4,8 +4,6 @@ module AbstractController module Helpers extend ActiveSupport::Concern - include Rendering - included do class_attribute :_helpers self._helpers = Module.new @@ -112,17 +110,6 @@ module AbstractController default_helper_module! unless anonymous? end - private - # Makes all the (instance) methods in the helper module available to templates - # rendered through this controller. - # - # ==== Parameters - # * <tt>module</tt> - The module to include into the current helper module - # for the class - def add_template_helper(mod) - _helpers.module_eval { include mod } - end - # Returns a list of modules, normalized from the acceptable kinds of # helpers with the following behavior: # @@ -155,6 +142,17 @@ module AbstractController end end + private + # Makes all the (instance) methods in the helper module available to templates + # rendered through this controller. + # + # ==== Parameters + # * <tt>module</tt> - The module to include into the current helper module + # for the class + def add_template_helper(mod) + _helpers.module_eval { include mod } + end + def default_helper_module! module_name = name.sub(/Controller$/, '') module_path = module_name.underscore diff --git a/actionpack/lib/abstract_controller/layouts.rb b/actionpack/lib/abstract_controller/layouts.rb index d1b87b67ee..8f73e244d7 100644 --- a/actionpack/lib/abstract_controller/layouts.rb +++ b/actionpack/lib/abstract_controller/layouts.rb @@ -292,15 +292,15 @@ module AbstractController end end - attr_writer :action_has_layout + attr_internal_writer :action_has_layout def initialize(*) - @action_has_layout = true + @_action_has_layout = true super end def action_has_layout? - @action_has_layout + @_action_has_layout end private diff --git a/actionpack/lib/abstract_controller/rendering.rb b/actionpack/lib/abstract_controller/rendering.rb index ecd0c4fb73..ab2c532859 100644 --- a/actionpack/lib/abstract_controller/rendering.rb +++ b/actionpack/lib/abstract_controller/rendering.rb @@ -32,9 +32,13 @@ module AbstractController module Rendering extend ActiveSupport::Concern - include AbstractController::ViewPaths + included do + config_accessor :protected_instance_variables, :instance_reader => false + self.protected_instance_variables = [] + end + # Overwrite process to setup I18n proxy. def process(*) #:nodoc: old_config, I18n.config = I18n.config, I18nProxy.new(I18n.config, lookup_context) @@ -46,46 +50,27 @@ module AbstractController module ClassMethods def view_context_class @view_context_class ||= begin - controller = self - Class.new(ActionView::Base) do - if controller.respond_to?(:_routes) && controller._routes - include controller._routes.url_helpers - include controller._routes.mounted_helpers - end - - if controller.respond_to?(:_helpers) - include controller._helpers - - # TODO: Fix RJS to not require this - self.helpers = controller._helpers - end - end + routes = _routes if respond_to?(:_routes) + helpers = _helpers if respond_to?(:_helpers) + ActionView::Base.prepare(routes, helpers) end end + end - def parent_prefixes - @parent_prefixes ||= begin - parent_controller = superclass - prefixes = [] - - until parent_controller.abstract? - prefixes << parent_controller.controller_path - parent_controller = parent_controller.superclass - end + attr_internal_writer :view_context_class - prefixes - end - end + # Explicitly define protected_instance_variables so it can be + # inherited and overwritten by other modules if needed. + def protected_instance_variables + config.protected_instance_variables end - attr_writer :view_context_class - def view_context_class - @view_context_class || self.class.view_context_class + @_view_context_class || self.class.view_context_class end def initialize(*) - @view_context_class = nil + @_view_context_class = nil super end @@ -99,22 +84,27 @@ module AbstractController # # Override this method in a module to change the default behavior. def view_context - view_context_class.new(lookup_context, view_assigns, self) + view_context_class.new(view_renderer, view_assigns, self) + end + + # Returns an object that is able to render templates. + def view_renderer + @_view_renderer ||= ActionView::Renderer.new(lookup_context) end # Normalize arguments, options and then delegates render_to_body and # sticks the result in self.response_body. def render(*args, &block) - self.response_body = render_to_string(*args, &block) + options = _normalize_render(*args, &block) + self.response_body = render_to_body(options) end # Raw rendering of a template to a string. Just convert the results of - # render_to_body into a String. + # render_response into a String. # :api: plugin def render_to_string(*args, &block) - options = _normalize_args(*args, &block) - _normalize_options(options) - render_to_body(options).tap { self.response_body = nil } + options = _normalize_render(*args, &block) + render_to_body(options) end # Raw rendering of a template to a Rack-compatible body. @@ -127,32 +117,39 @@ module AbstractController # Find and renders a template based on the options given. # :api: private def _render_template(options) #:nodoc: - view_context.render(options) - end - - # The prefixes used in render "foo" shortcuts. - def _prefixes - @_prefixes ||= begin - parent_prefixes = self.class.parent_prefixes - parent_prefixes.dup.unshift(controller_path) - end + view_renderer.render(view_context, options) end private + DEFAULT_PROTECTED_INSTANCE_VARIABLES = %w( + @_action_name @_response_body @_formats @_prefixes @_config + @_view_context_class @_view_renderer @_lookup_context + ) + # This method should return a hash with assigns. # You can overwrite this configuration per controller. # :api: public def view_assigns hash = {} variables = instance_variable_names - variables -= protected_instance_variables if respond_to?(:protected_instance_variables) + variables -= protected_instance_variables + variables -= DEFAULT_PROTECTED_INSTANCE_VARIABLES variables.each { |name| hash[name.to_s[1, name.length]] = instance_variable_get(name) } hash end - # Normalize options by converting render "foo" to render :action => "foo" and + # Normalize args and options. + # :api: private + def _normalize_render(*args, &block) + options = _normalize_args(*args, &block) + _normalize_options(options) + options + end + + # Normalize args by converting render "foo" to render :action => "foo" and # render "foo/bar" to render :file => "foo/bar". + # :api: plugin def _normalize_args(action=nil, options={}) case action when NilClass @@ -169,12 +166,14 @@ module AbstractController options end + # Normalize options. + # :api: plugin def _normalize_options(options) if options[:partial] == true options[:partial] = action_name end - if (options.keys & [:partial, :file, :template, :once]).empty? + if (options.keys & [:partial, :file, :template]).empty? options[:prefixes] ||= _prefixes end @@ -182,6 +181,8 @@ module AbstractController options end + # Process extra options. + # :api: plugin def _process_options(options) end end diff --git a/actionpack/lib/abstract_controller/view_paths.rb b/actionpack/lib/abstract_controller/view_paths.rb index cea0f5ad1e..6b7aae8c74 100644 --- a/actionpack/lib/abstract_controller/view_paths.rb +++ b/actionpack/lib/abstract_controller/view_paths.rb @@ -11,11 +11,36 @@ module AbstractController delegate :find_template, :template_exists?, :view_paths, :formats, :formats=, :locale, :locale=, :to => :lookup_context + module ClassMethods + def parent_prefixes + @parent_prefixes ||= begin + parent_controller = superclass + prefixes = [] + + until parent_controller.abstract? + prefixes << parent_controller.controller_path + parent_controller = parent_controller.superclass + end + + prefixes + end + end + end + + # The prefixes used in render "foo" shortcuts. + def _prefixes + @_prefixes ||= begin + parent_prefixes = self.class.parent_prefixes + parent_prefixes.dup.unshift(controller_path) + end + end + # LookupContext is the object responsible to hold all information required to lookup # templates, i.e. view paths and details. Check ActionView::LookupContext for more # information. def lookup_context - @lookup_context ||= ActionView::LookupContext.new(self.class._view_paths, details_for_lookup) + @_lookup_context ||= + ActionView::LookupContext.new(self.class._view_paths, details_for_lookup, _prefixes) end def details_for_lookup @@ -67,4 +92,4 @@ module AbstractController end end end -end
\ No newline at end of file +end |