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

root/trunk/actionpack/lib/action_view/partials.rb

Revision 9179, 6.5 kB (checked in by pratik, 5 months ago)

Remove unnecessary arguments. References #11491.

Line 
1 module ActionView
2   # There's also a convenience method for rendering sub templates within the current controller that depends on a single object
3   # (we call this kind of sub templates for partials). It relies on the fact that partials should follow the naming convention of being
4   # prefixed with an underscore -- as to separate them from regular templates that could be rendered on their own.
5   #
6   # In a template for Advertiser#account:
7   #
8   #  <%= render :partial => "account" %>
9   #
10   # This would render "advertiser/_account.erb" and pass the instance variable @account in as a local variable +account+ to
11   # the template for display.
12   #
13   # In another template for Advertiser#buy, we could have:
14   #
15   #   <%= render :partial => "account", :locals => { :account => @buyer } %>
16   #
17   #   <% for ad in @advertisements %>
18   #     <%= render :partial => "ad", :locals => { :ad => ad } %>
19   #   <% end %>
20   #
21   # This would first render "advertiser/_account.erb" with @buyer passed in as the local variable +account+, then render
22   # "advertiser/_ad.erb" and pass the local variable +ad+ to the template for display.
23   #
24   # == Rendering a collection of partials
25   #
26   # The example of partial use describes a familiar pattern where a template needs to iterate over an array and render a sub
27   # template for each of the elements. This pattern has been implemented as a single method that accepts an array and renders
28   # a partial by the same name as the elements contained within. So the three-lined example in "Using partials" can be rewritten
29   # with a single line:
30   #
31   #   <%= render :partial => "ad", :collection => @advertisements %>
32   #
33   # This will render "advertiser/_ad.erb" and pass the local variable +ad+ to the template for display. An iteration counter
34   # will automatically be made available to the template with a name of the form +partial_name_counter+. In the case of the
35   # example above, the template would be fed +ad_counter+.
36   #
37   # NOTE: Due to backwards compatibility concerns, the collection can't be one of hashes. Normally you'd also just keep domain objects,
38   # like Active Records, in there.
39   #
40   # == Rendering shared partials
41   #
42   # Two controllers can share a set of partials and render them like this:
43   #
44   #   <%= render :partial => "advertisement/ad", :locals => { :ad => @advertisement } %>
45   #
46   # This will render the partial "advertisement/_ad.erb" regardless of which controller this is being called from.
47   #
48   # == Rendering partials with layouts
49   #
50   # Partials can have their own layouts applied to them. These layouts are different than the ones that are specified globally
51   # for the entire action, but they work in a similar fashion. Imagine a list with two types of users:
52   #
53   #   <%# app/views/users/index.html.erb &>
54   #   Here's the administrator:
55   #   <%= render :partial => "user", :layout => "administrator", :locals => { :user => administrator } %>
56   #
57   #   Here's the editor:
58   #   <%= render :partial => "user", :layout => "editor", :locals => { :user => editor } %>
59   #
60   #   <%# app/views/users/_user.html.erb &>
61   #   Name: <%= user.name %>
62   #
63   #   <%# app/views/users/_administrator.html.erb &>
64   #   <div id="administrator">
65   #     Budget: $<%= user.budget %>
66   #     <%= yield %>
67   #   </div>
68   #
69   #   <%# app/views/users/_editor.html.erb &>
70   #   <div id="editor">
71   #     Deadline: $<%= user.deadline %>
72   #     <%= yield %>
73   #   </div>
74   #
75   # ...this will return:
76   #
77   #   Here's the administrator:
78   #   <div id="administrator">
79   #     Budget: $<%= user.budget %>
80   #     Name: <%= user.name %>
81   #   </div>
82   #
83   #   Here's the editor:
84   #   <div id="editor">
85   #     Deadline: $<%= user.deadline %>
86   #     Name: <%= user.name %>
87   #   </div>
88   #
89   # You can also apply a layout to a block within any template:
90   #
91   #   <%# app/views/users/_chief.html.erb &>
92   #   <% render(:layout => "administrator", :locals => { :user => chief }) do %>
93   #     Title: <%= chief.title %>
94   #   <% end %>
95   #
96   # ...this will return:
97   #
98   #   <div id="administrator">
99   #     Budget: $<%= user.budget %>
100   #     Title: <%= chief.name %>
101   #   </div>
102   #
103   # As you can see, the :locals hash is shared between both the partial and its layout.
104   module Partials
105     private
106       def render_partial(partial_path, object_assigns = nil, local_assigns = {}) #:nodoc:
107         case partial_path
108         when String, Symbol, NilClass
109           # Render the template
110           ActionView::PartialTemplate.new(self, partial_path, object_assigns, local_assigns).render
111         when ActionView::Helpers::FormBuilder
112           builder_partial_path = partial_path.class.to_s.demodulize.underscore.sub(/_builder$/, '')
113           render_partial(builder_partial_path, object_assigns, (local_assigns || {}).merge(builder_partial_path.to_sym => partial_path))
114         when Array, ActiveRecord::Associations::AssociationCollection, ActiveRecord::Associations::HasManyThroughAssociation
115           if partial_path.any?
116             collection = partial_path
117             render_partial_collection(nil, collection, nil, local_assigns)
118           else
119             ""
120           end
121         else
122           render_partial(ActionController::RecordIdentifier.partial_path(partial_path), partial_path, local_assigns)
123         end
124       end
125
126       def render_partial_collection(partial_path, collection, partial_spacer_template = nil, local_assigns = {}) #:nodoc:
127         return " " if collection.empty?
128
129         local_assigns = local_assigns ? local_assigns.clone : {}
130         spacer = partial_spacer_template ? render(:partial => partial_spacer_template) : ''
131
132         if partial_path.nil?
133           render_partial_collection_with_unknown_partial_path(collection, local_assigns)
134         else
135           render_partial_collection_with_known_partial_path(collection, partial_path, local_assigns)
136         end.join(spacer)
137       end
138
139       def render_partial_collection_with_known_partial_path(collection, partial_path, local_assigns)
140         template = ActionView::PartialTemplate.new(self, partial_path, nil, local_assigns)
141         collection.map do |element|
142           template.render_member(element)
143         end
144       end
145
146       def render_partial_collection_with_unknown_partial_path(collection, local_assigns)
147         templates = Hash.new
148         i = 0
149         collection.map do |element|
150           partial_path = ActionController::RecordIdentifier.partial_path(element)
151           template = templates[partial_path] ||= ActionView::PartialTemplate.new(self, partial_path, nil, local_assigns)
152           template.counter = i
153           i += 1
154           template.render_member(element)
155         end
156       end
157   end
158 end
Note: See TracBrowser for help on using the browser.