From 137794310b02840773213c81c86411b43935db90 Mon Sep 17 00:00:00 2001 From: David Heinemeier Hansson Date: Sun, 12 Feb 2006 00:46:01 +0000 Subject: The components module should also contain the options that pertain to it, so collect it all with ClassMethods and InstanceMethods git-svn-id: http://svn-commit.rubyonrails.org/rails/trunk@3576 5ecf4fe2-1ee6-0310-87b1-e25e094e27de --- actionpack/lib/action_controller/components.rb | 126 ++++++++++++++----------- 1 file changed, 73 insertions(+), 53 deletions(-) (limited to 'actionpack/lib/action_controller/components.rb') diff --git a/actionpack/lib/action_controller/components.rb b/actionpack/lib/action_controller/components.rb index 7cbbe3edd2..ba08670610 100644 --- a/actionpack/lib/action_controller/components.rb +++ b/actionpack/lib/action_controller/components.rb @@ -28,8 +28,10 @@ module ActionController #:nodoc: # # would work as well and be slightly faster. module Components - def self.append_features(base) #:nodoc: - super + def self.included(base) #:nodoc: + base.extend(ClassMethods) + base.send(:include, InstanceMethods) + base.helper do def render_component(options) @controller.send(:render_component_as_string, options) @@ -37,68 +39,86 @@ module ActionController #:nodoc: end end - protected - # Renders the component specified as the response for the current method - def render_component(options) #:doc: - component_logging(options) do - render_text(component_response(options, true).body, response.headers["Status"]) - end + module ClassMethods + # Set the template root to be one directory behind the root dir of the controller. Examples: + # /code/weblog/components/admin/users_controller.rb with Admin::UsersController + # will use /code/weblog/components as template root + # and find templates in /code/weblog/components/admin/users/ + # + # /code/weblog/components/admin/parties/users_controller.rb with Admin::Parties::UsersController + # will also use /code/weblog/components as template root + # and find templates in /code/weblog/components/admin/parties/users/ + def uses_component_template_root + path_of_calling_controller = File.dirname(caller[0].split(/:\d+:/).first) + path_of_controller_root = path_of_calling_controller.sub(/#{controller_path.split("/")[0..-2]}$/, "") # " (for ruby-mode) + self.template_root = path_of_controller_root end + end - # Returns the component response as a string - def render_component_as_string(options) #:doc: - component_logging(options) do - response = component_response(options, false) - if redirected = response.redirected_to - render_component_as_string redirected - else - response.body + module InstanceMethods + protected + # Renders the component specified as the response for the current method + def render_component(options) #:doc: + component_logging(options) do + render_text(component_response(options, true).body, response.headers["Status"]) end - end - end + end + + # Returns the component response as a string + def render_component_as_string(options) #:doc: + component_logging(options) do + response = component_response(options, false) + if redirected = response.redirected_to + render_component_as_string redirected + else + response.body + end + end + end - private - def component_response(options, reuse_response) - c_class = component_class(options) - c_request = request_for_component(c_class.controller_name, options) - c_response = reuse_response ? @response : @response.dup - c_class.process(c_request, c_response, self) - end + private + def component_response(options, reuse_response) + c_class = component_class(options) + c_request = request_for_component(c_class.controller_name, options) + c_response = reuse_response ? @response : @response.dup + c_class.process(c_request, c_response, self) + end - # determine the controller class for the component request - def component_class(options) - if controller = options[:controller] - if controller.is_a? Class - controller + # determine the controller class for the component request + def component_class(options) + if controller = options[:controller] + if controller.is_a? Class + controller + else + "#{controller.camelize}Controller".constantize + end else - "#{controller.camelize}Controller".constantize + self.class end - else - self.class end - end - # Create a new request object based on the current request. - # The new request inherits the session from the current request, - # bypassing any session options set for the component controller's class - def request_for_component(controller_name, options) - sub_request = @request.dup - sub_request.session = @request.session - sub_request.instance_variable_set(:@parameters, - (options[:params] || {}).with_indifferent_access.regular_update( - "controller" => controller_name, "action" => options[:action], "id" => options[:id]) - ) - sub_request - end + # Create a new request object based on the current request. + # The new request inherits the session from the current request, + # bypassing any session options set for the component controller's class + def request_for_component(controller_name, options) + sub_request = @request.dup + sub_request.session = @request.session + sub_request.instance_variable_set(:@parameters, + (options[:params] || {}).with_indifferent_access.regular_update( + "controller" => controller_name, "action" => options[:action], "id" => options[:id]) + ) + sub_request + end - def component_logging(options) - unless logger then yield else - logger.info("Start rendering component (#{options.inspect}): ") - result = yield - logger.info("\n\nEnd of component rendering") - result + def component_logging(options) + unless logger then yield else + logger.info("Start rendering component (#{options.inspect}): ") + result = yield + logger.info("\n\nEnd of component rendering") + result + end end - end + end end end -- cgit v1.2.3