diff options
author | Yehuda Katz <wycats@gmail.com> | 2009-08-10 02:54:17 -0400 |
---|---|---|
committer | Yehuda Katz <wycats@gmail.com> | 2009-08-11 15:03:53 -0700 |
commit | 4945d8223964d4ccb3c0a0f4107f15ae1c6c4a09 (patch) | |
tree | e283f8192ea7d4563926b91e5a430e3462999090 /actionpack | |
parent | bef7576c09bbd51aeeb8e83b4cf24a994a0256b0 (diff) | |
download | rails-4945d8223964d4ccb3c0a0f4107f15ae1c6c4a09.tar.gz rails-4945d8223964d4ccb3c0a0f4107f15ae1c6c4a09.tar.bz2 rails-4945d8223964d4ccb3c0a0f4107f15ae1c6c4a09.zip |
Further experimentation. Was able to cut the cost of rendering 100 partials in a collection in half.
To discuss: What are the desired semantics (if any) for layouts in a collection. There are no
tests for it at present, and I'm not sure if it's needed at all.
Deprecated on this branch: `object` pointing at the current object in partials. You can still
use the partial name, or use :as to achieve the same thing. This is obviously up for discussion.
Diffstat (limited to 'actionpack')
-rw-r--r-- | actionpack/examples/minimal.rb | 4 | ||||
-rw-r--r-- | actionpack/examples/views/_hundred_partials.erb | 12 | ||||
-rw-r--r-- | actionpack/lib/action_view/render/partials.rb | 49 | ||||
-rw-r--r-- | actionpack/lib/action_view/test_case.rb | 20 |
4 files changed, 65 insertions, 20 deletions
diff --git a/actionpack/examples/minimal.rb b/actionpack/examples/minimal.rb index c4e5ffd36e..90435d0b89 100644 --- a/actionpack/examples/minimal.rb +++ b/actionpack/examples/minimal.rb @@ -104,22 +104,22 @@ ActionController::Base.use_accept_header = false unless ENV["PROFILE"] Runner.run(BasePostController.action(:overhead), N, 'overhead', false) Runner.run(BasePostController.action(:index), N, 'index', false) + Runner.run(BasePostController.action(:show_template), N, 'template', false) Runner.run(BasePostController.action(:partial), N, 'partial', false) Runner.run(BasePostController.action(:many_partials), N, 'many_partials', false) Runner.run(BasePostController.action(:partial_collection), N, 'collection', false) Runner.run(BasePostController.action(:hundred_partials), N, 'hundred_partials', false) Runner.run(BasePostController.action(:large_collection), N, 'large_collection', false) - Runner.run(BasePostController.action(:show_template), N, 'template', false) (ENV["M"] || 1).to_i.times do Runner.run(BasePostController.action(:overhead), N, 'overhead') Runner.run(BasePostController.action(:index), N, 'index') + Runner.run(BasePostController.action(:show_template), N, 'template') Runner.run(BasePostController.action(:partial), N, 'partial') Runner.run(BasePostController.action(:many_partials), N, 'many_partials') Runner.run(BasePostController.action(:partial_collection), N, 'collection') Runner.run(BasePostController.action(:hundred_partials), N, 'hundred_partials') Runner.run(BasePostController.action(:large_collection), N, 'large_collection') - Runner.run(BasePostController.action(:show_template), N, 'template') end else Runner.run(BasePostController.action(ENV["PROFILE"].to_sym), N, ENV["PROFILE"]) diff --git a/actionpack/examples/views/_hundred_partials.erb b/actionpack/examples/views/_hundred_partials.erb new file mode 100644 index 0000000000..15e99c1b68 --- /dev/null +++ b/actionpack/examples/views/_hundred_partials.erb @@ -0,0 +1,12 @@ +<% 10.times do %> + <%= render :partial => '/hello' %> + <%= render :partial => '/hello' %> + <%= render :partial => '/hello' %> + <%= render :partial => '/hello' %> + <%= render :partial => '/hello' %> + <%= render :partial => '/hello' %> + <%= render :partial => '/hello' %> + <%= render :partial => '/hello' %> + <%= render :partial => '/hello' %> + <%= render :partial => '/hello' %> +<% end %>
\ No newline at end of file diff --git a/actionpack/lib/action_view/render/partials.rb b/actionpack/lib/action_view/render/partials.rb index 64f08c447d..2aa3bd7db8 100644 --- a/actionpack/lib/action_view/render/partials.rb +++ b/actionpack/lib/action_view/render/partials.rb @@ -207,9 +207,7 @@ module ActionView end def render_collection - # Even if no template is rendered, this will ensure that the MIME type - # for the empty response is the same as the provided template - @options[:_template] = default_template = find_template + @options[:_template] = template = find_template return nil if collection.blank? @@ -217,15 +215,48 @@ module ActionView spacer = find_template(@options[:spacer_template]).render(@view, @locals) end - segments = [] + result = template ? collection_with_template(template) : collection_without_template + result.join(spacer) + end + + def collection_with_template(template) + options = @options + + segments, locals, as = [], @locals, options[:as] + + [].tap do |segments| + variable_name = template.variable_name + counter_name = template.counter_name + locals[counter_name] = -1 - collection.each_with_index do |object, index| - template = default_template || find_template(partial_path(object)) - @locals[template.counter_name] = index - segments << render_template(template, object) + collection.each do |object| + locals[counter_name] += 1 + locals[variable_name] = object + locals[as] = object if as + + segments << template.render(@view, locals) + end end + end - segments.join(spacer) + def collection_without_template + options = @options + + segments, locals, as = [], @locals, options[:as] + index, template = -1, nil + + [].tap do |segments| + collection.each do |object| + template = find_template(partial_path(object)) + locals[template.counter_name] = (index += 1) + locals[template.variable_name] = object + locals[as] = object if as + + segments << template.render(@view, locals) + end + + @options[:_template] = template + end end def render_template(template, object = @object) diff --git a/actionpack/lib/action_view/test_case.rb b/actionpack/lib/action_view/test_case.rb index e51744d095..b317b6dc1a 100644 --- a/actionpack/lib/action_view/test_case.rb +++ b/actionpack/lib/action_view/test_case.rb @@ -9,14 +9,16 @@ module ActionView end attr_internal :rendered - alias_method :_render_template_without_template_tracking, :_render_single_template - def _render_single_template(template, local_assigns, &block) - if template.respond_to?(:identifier) && template.present? - @_rendered[:partials][template] += 1 if template.partial? - @_rendered[:template] ||= [] - @_rendered[:template] << template - end - _render_template_without_template_tracking(template, local_assigns, &block) + end + + class Template + alias_method :render_without_tracking, :render + def render(view, locals, &blk) + rendered = view.rendered + rendered[:partials][self] += 1 if partial? + rendered[:template] ||= [] + rendered[:template] << self + render_without_tracking(view, locals, &blk) end end @@ -68,7 +70,7 @@ module ActionView def initialize @request = ActionController::TestRequest.new @response = ActionController::TestResponse.new - + @params = {} send(:initialize_current_url) end |