diff --git a/actionpack/CHANGELOG b/actionpack/CHANGELOG index 165db916eedbf72dd32d3610af2818d29043b0e5..5a5895d9b45da4af08623369c2e24ddf728c822d 100644 --- a/actionpack/CHANGELOG +++ b/actionpack/CHANGELOG @@ -1,5 +1,11 @@ *Edge* +* Add :as option to render a collection of partials with a custom local variable name. #509 [Simon Jefford, Pratik Naik] + + render :partial => 'other_people', :collection => @people, :as => :person + + This will let you access objects of @people as 'person' local variable inside 'other_people' partial template. + * time_zone_select: support for regexp matching of priority zones. Resolves #195 [Ernie Miller] * Made ActionView::Base#render_file private [Josh Peek] diff --git a/actionpack/lib/action_controller/base.rb b/actionpack/lib/action_controller/base.rb index a7b2f147e874520ceb859a4588be838373dc0e0f..209cdfa686bd82ca4b38a38a77b49367274a6fc6 100755 --- a/actionpack/lib/action_controller/base.rb +++ b/actionpack/lib/action_controller/base.rb @@ -702,6 +702,9 @@ def append_view_path(path) # # builds the complete response. # render :partial => "person", :collection => @winners # + # # Renders a collection of partials but with a custom local variable name + # render :partial => "admin_person", :collection => @winners, :as => :person + # # # Renders the same collection of partials, but also renders the # # person_divider partial between each person partial. # render :partial => "person", :collection => @winners, :spacer_template => "person_divider" @@ -889,7 +892,7 @@ def render(options = nil, extra_options = {}, &block) #:doc: if collection = options[:collection] render_for_text( @template.send!(:render_partial_collection, partial, collection, - options[:spacer_template], options[:locals]), options[:status] + options[:spacer_template], options[:locals], options[:as]), options[:status] ) else render_for_text( diff --git a/actionpack/lib/action_view/base.rb b/actionpack/lib/action_view/base.rb index 40b808a61e396a537b3ac208ba281818b6288bfb..40a3b16e9f257be7244fd738c1e732aa318bfc5d 100644 --- a/actionpack/lib/action_view/base.rb +++ b/actionpack/lib/action_view/base.rb @@ -252,7 +252,7 @@ def render(options = {}, local_assigns = {}, &block) #:nodoc: elsif options[:file] render_file(options[:file], use_full_path || false, options[:locals]) elsif options[:partial] && options[:collection] - render_partial_collection(options[:partial], options[:collection], options[:spacer_template], options[:locals]) + render_partial_collection(options[:partial], options[:collection], options[:spacer_template], options[:locals], options[:as]) elsif options[:partial] render_partial(options[:partial], ActionView::Base::ObjectWrapper.new(options[:object]), options[:locals]) elsif options[:inline] diff --git a/actionpack/lib/action_view/partial_template.rb b/actionpack/lib/action_view/partial_template.rb index 0cf996ca0464a1c516deb9e5d2276dd1d2a46202..3513244ecbfde4b17e5bf836d4400eb94d7de99a 100644 --- a/actionpack/lib/action_view/partial_template.rb +++ b/actionpack/lib/action_view/partial_template.rb @@ -1,9 +1,10 @@ module ActionView #:nodoc: class PartialTemplate < Template #:nodoc: - attr_reader :variable_name, :object + attr_reader :variable_name, :object, :as - def initialize(view, partial_path, object = nil, locals = {}) + def initialize(view, partial_path, object = nil, locals = {}, as = nil) @view_controller = view.controller if view.respond_to?(:controller) + @as = as set_path_and_variable_name!(partial_path) super(view, @path, true, locals) add_object_to_local_assigns!(object) @@ -22,10 +23,11 @@ def render end def render_member(object) - @locals[:object] = @locals[@variable_name] = object + @locals[:object] = @locals[@variable_name] = @locals[as] = object template = render_template @locals[@counter_name] += 1 + @locals.delete(as) @locals.delete(@variable_name) @locals.delete(:object) @@ -45,6 +47,7 @@ def add_object_to_local_assigns!(object) else object end || @view_controller.instance_variable_get("@#{variable_name}") + @locals[as] ||= @locals[:object] if as end def set_path_and_variable_name!(partial_path) diff --git a/actionpack/lib/action_view/partials.rb b/actionpack/lib/action_view/partials.rb index 6b294be6bd8427e0d6ebe7e9d0ea0a6eaa31053f..7c6c98d6116c08675dc8fb3758f593a5f67f4678 100644 --- a/actionpack/lib/action_view/partials.rb +++ b/actionpack/lib/action_view/partials.rb @@ -123,32 +123,32 @@ def render_partial(partial_path, object_assigns = nil, local_assigns = {}) #:nod end end - def render_partial_collection(partial_path, collection, partial_spacer_template = nil, local_assigns = {}) #:nodoc: + def render_partial_collection(partial_path, collection, partial_spacer_template = nil, local_assigns = {}, as = nil) #:nodoc: return " " if collection.empty? local_assigns = local_assigns ? local_assigns.clone : {} spacer = partial_spacer_template ? render(:partial => partial_spacer_template) : '' if partial_path.nil? - render_partial_collection_with_unknown_partial_path(collection, local_assigns) + render_partial_collection_with_unknown_partial_path(collection, local_assigns, as) else - render_partial_collection_with_known_partial_path(collection, partial_path, local_assigns) + render_partial_collection_with_known_partial_path(collection, partial_path, local_assigns, as) end.join(spacer) end - def render_partial_collection_with_known_partial_path(collection, partial_path, local_assigns) - template = ActionView::PartialTemplate.new(self, partial_path, nil, local_assigns) + def render_partial_collection_with_known_partial_path(collection, partial_path, local_assigns, as) + template = ActionView::PartialTemplate.new(self, partial_path, nil, local_assigns, as) collection.map do |element| template.render_member(element) end end - def render_partial_collection_with_unknown_partial_path(collection, local_assigns) + def render_partial_collection_with_unknown_partial_path(collection, local_assigns, as) templates = Hash.new i = 0 collection.map do |element| partial_path = ActionController::RecordIdentifier.partial_path(element, controller.class.controller_path) - template = templates[partial_path] ||= ActionView::PartialTemplate.new(self, partial_path, nil, local_assigns) + template = templates[partial_path] ||= ActionView::PartialTemplate.new(self, partial_path, nil, local_assigns, as) template.counter = i i += 1 template.render_member(element) diff --git a/actionpack/test/controller/new_render_test.rb b/actionpack/test/controller/new_render_test.rb index eac36a04cb19acc6fc9c2539fba77286b788b6af..5a7da57559e5af15cee93fa195bcae572f5b57ca 100644 --- a/actionpack/test/controller/new_render_test.rb +++ b/actionpack/test/controller/new_render_test.rb @@ -152,6 +152,10 @@ def partial_collection render :partial => "customer", :collection => [ Customer.new("david"), Customer.new("mary") ] end + def partial_collection_with_as + render :partial => "customer_with_var", :collection => [ Customer.new("david"), Customer.new("mary") ], :as => :customer + end + def partial_collection_with_spacer render :partial => "customer", :spacer_template => "partial_only", :collection => [ Customer.new("david"), Customer.new("mary") ] end @@ -763,6 +767,11 @@ def test_partial_collection assert_equal "Hello: davidHello: mary", @response.body end + def test_partial_collection_with_as + get :partial_collection_with_as + assert_equal "david david davidmary mary mary", @response.body + end + def test_partial_collection_with_counter get :partial_collection_with_counter assert_equal "david0mary1", @response.body diff --git a/actionpack/test/fixtures/test/_customer_with_var.erb b/actionpack/test/fixtures/test/_customer_with_var.erb new file mode 100644 index 0000000000000000000000000000000000000000..3379246b7efd6e3dd98df9d7039085e06549bdf6 --- /dev/null +++ b/actionpack/test/fixtures/test/_customer_with_var.erb @@ -0,0 +1 @@ +<%= customer.name %> <%= object.name %> <%= customer_with_var.name %> \ No newline at end of file diff --git a/actionpack/test/template/render_test.rb b/actionpack/test/template/render_test.rb index 54e4bbda1b19597a1e08d5292286aec2dfd9206b..64244e50f7cde510a676b176e544510c3f4aad7b 100644 --- a/actionpack/test/template/render_test.rb +++ b/actionpack/test/template/render_test.rb @@ -54,6 +54,11 @@ def test_render_partial_with_errors def test_render_partial_collection assert_equal "Hello: davidHello: mary", @view.render(:partial => "test/customer", :collection => [ Customer.new("david"), Customer.new("mary") ]) end + + def test_render_partial_collection_as + assert_equal "david david davidmary mary mary", + @view.render(:partial => "test/customer_with_var", :collection => [ Customer.new("david"), Customer.new("mary") ], :as => :customer) + end # TODO: The reason for this test is unclear, improve documentation def test_render_partial_and_fallback_to_layout