Ruby on Rails | Screencasts | Download | Documentation | Weblog | Community | Source

root/trunk/actionpack/lib/action_controller/components.rb

Revision 2749, 3.1 kB (checked in by david, 5 years ago)

Fixed docs (closes #2468)

Line 
1 module ActionController #:nodoc:
2   # Components allows you to call other actions for their rendered response while executing another action. You can either delegate
3   # the entire response rendering or you can mix a partial response in with your other content.
4   #
5   #   class WeblogController < ActionController::Base
6   #     # Performs a method and then lets hello_world output its render
7   #     def delegate_action
8   #       do_other_stuff_before_hello_world
9   #       render_component :controller => "greeter",  :action => "hello_world", :params => { "person" => "david" }
10   #     end
11   #   end
12   #
13   #   class GreeterController < ActionController::Base
14   #     def hello_world
15   #       render_text "#{@params['person']} says, Hello World!"
16   #     end
17   #   end
18   #
19   # The same can be done in a view to do a partial rendering:
20   #
21   #   Let's see a greeting:
22   #   <%= render_component :controller => "greeter", :action => "hello_world" %>
23   module Components
24     def self.append_features(base) #:nodoc:
25       super
26       base.helper do
27         def render_component(options)
28           @controller.send(:render_component_as_string, options)
29         end
30       end
31     end
32
33     protected
34       # Renders the component specified as the response for the current method
35       def render_component(options = {}) #:doc:
36         component_logging(options) { render_text(component_response(options).body, response.headers["Status"]) }
37       end
38
39       # Returns the component response as a string
40       def render_component_as_string(options) #:doc:
41         component_logging(options) do
42           response = component_response(options, false)
43           unless response.redirected_to.nil?
44             render_component_as_string response.redirected_to
45           else
46             response.body
47           end
48        end
49       end
50  
51     private
52       def component_response(options, reuse_response = true)
53         begin
54           ActionController::Flash::FlashHash.avoid_sweep = true
55           Thread.current[:p] = component_class(options).process(request_for_component(options), reuse_response ? @response : response_for_component)
56         ensure
57           ActionController::Flash::FlashHash.avoid_sweep = false
58         end
59         Thread.current[:p]
60       end
61    
62       def component_class(options)
63         options[:controller] ? (options[:controller].camelize + "Controller").constantize : self.class
64       end
65      
66       def request_for_component(options)
67         request_for_component = @request.dup
68         request_for_component.send(
69           :instance_variable_set, :@parameters,
70           (options[:params] || {}).merge({ "controller" => options[:controller], "action" => options[:action], "id" => options[:id] }).with_indifferent_access
71         )
72         return request_for_component
73       end
74      
75       def response_for_component
76         @response.dup
77       end
78      
79       def component_logging(options)
80         logger.info("Start rendering component (#{options.inspect}): ") unless logger.nil?
81         result = yield
82         logger.info("\n\nEnd of component rendering") unless logger.nil?
83         return result
84       end
85   end
86 end
Note: See TracBrowser for help on using the browser.