diff options
author | José Valim <jose.valim@gmail.com> | 2010-10-07 15:50:20 +0200 |
---|---|---|
committer | José Valim <jose.valim@gmail.com> | 2010-10-07 21:31:31 +0200 |
commit | b2600bfc181664fcfe448d100ca054017b0576dd (patch) | |
tree | fab6f7d40c19288ef2447266eedefb0527ed7167 /actionpack/lib/action_view/render | |
parent | ad13eb72959f685927b5212ed387d51142d51805 (diff) | |
download | rails-b2600bfc181664fcfe448d100ca054017b0576dd.tar.gz rails-b2600bfc181664fcfe448d100ca054017b0576dd.tar.bz2 rails-b2600bfc181664fcfe448d100ca054017b0576dd.zip |
Remove locals dependency from template.
This means that templates does not need to store its source anymore, allowing us to reduce the ammount of memory taken by our Rails processes. Naively speaking, if your app/views contains 2MB of files, each of your processes (after being hit by a bunch of requests) will take 2MB less of memory after this commit.
This is extremely important for the upcoming features. Since Rails will also render CSS and JS files, their source won't be stored as well allowing us to decrease the ammount of memory taken.
Diffstat (limited to 'actionpack/lib/action_view/render')
-rw-r--r-- | actionpack/lib/action_view/render/layouts.rb | 4 | ||||
-rw-r--r-- | actionpack/lib/action_view/render/partials.rb | 80 | ||||
-rw-r--r-- | actionpack/lib/action_view/render/rendering.rb | 10 |
3 files changed, 53 insertions, 41 deletions
diff --git a/actionpack/lib/action_view/render/layouts.rb b/actionpack/lib/action_view/render/layouts.rb index 8882acca31..08162f7fd5 100644 --- a/actionpack/lib/action_view/render/layouts.rb +++ b/actionpack/lib/action_view/render/layouts.rb @@ -62,11 +62,11 @@ module ActionView # This is the method which actually finds the layout using details in the lookup # context object. If no layout is found, it checks if at least a layout with # the given name exists across all details before raising the error. - def find_layout(layout) + def find_layout(layout, keys) begin with_layout_format do layout =~ /^\// ? - with_fallbacks { find_template(layout) } : find_template(layout) + with_fallbacks { find_template(layout, nil, false, keys) } : find_template(layout, nil, false, keys) end rescue ActionView::MissingTemplate => e update_details(:formats => nil) do diff --git a/actionpack/lib/action_view/render/partials.rb b/actionpack/lib/action_view/render/partials.rb index cc9b444837..07e844afc2 100644 --- a/actionpack/lib/action_view/render/partials.rb +++ b/actionpack/lib/action_view/render/partials.rb @@ -218,7 +218,6 @@ module ActionView def initialize(view_context, options, block) @view = view_context @partial_names = PARTIAL_NAMES[@view.controller.class.name] - setup(options, block) end @@ -237,16 +236,28 @@ module ActionView @object = partial if @collection = collection - paths = @collection_paths = @collection.map { |o| partial_path(o) } + paths = @collection_data = @collection.map { |o| partial_path(o) } @path = paths.uniq.size == 1 ? paths.first : nil else @path = partial_path end end + + if @path + @variable, @variable_counter = retrieve_variable(@path) + else + paths.map! { |path| retrieve_variable(path).unshift(path) } + end + end + + def retrieve_variable(path) + variable = @options[:as] || path[%r'_?(\w+)(\.\w+)*$', 1].to_sym + variable_counter = :"#{variable}_counter" if @collection + [variable, variable_counter] end def render - identifier = ((@template = find_template) ? @template.identifier : @path) + identifier = ((@template = find_partial) ? @template.identifier : @path) if @collection ActiveSupport::Notifications.instrument("render_collection.action_view", @@ -254,15 +265,16 @@ module ActionView render_collection end else + if !@block && (layout = @options[:layout]) + layout = find_template(layout) + end + content = ActiveSupport::Notifications.instrument("render_partial.action_view", :identifier => identifier) do render_partial end - if !@block && (layout = @options[:layout]) - content = @view._render_layout(find_template(layout), @locals){ content } - end - + content = @view._render_layout(layout, @locals){ content } if layout content end end @@ -278,16 +290,9 @@ module ActionView result.join(spacer).html_safe end - def collection_with_template(template = @template) + def collection_with_template segments, locals, template = [], @locals, @template - - if @options[:as] - as = @options[:as] - counter = "#{as}_counter".to_sym - else - as = template.variable_name - counter = template.counter_name - end + as, counter = @variable, @variable_counter locals[counter] = -1 @@ -300,20 +305,16 @@ module ActionView segments end - def collection_without_template(collection_paths = @collection_paths) - segments, locals = [], @locals + def collection_without_template + segments, locals, collection_data = [], @locals, @collection_data index, template = -1, nil - - if @options[:as] - as = @options[:as] - counter = "#{as}_counter" - end + keys = @locals.keys @collection.each_with_index do |object, i| - template = find_template(collection_paths[i]) - locals[as || template.variable_name] = object - locals[counter || template.counter_name] = (index += 1) - + path, *data = collection_data[i] + template = find_template(path, keys + data) + locals[data[0]] = object + locals[data[1]] = (index += 1) segments << template.render(@view, locals) end @@ -321,13 +322,14 @@ module ActionView segments end - def render_partial(object = @object) - locals, view, template = @locals, @view, @template + def render_partial + locals, view = @locals, @view + object, as = @object, @variable - object ||= locals[template.variable_name] - locals[@options[:as] || template.variable_name] = object + object ||= locals[as] + locals[as] = object - template.render(view, locals) do |*name| + @template.render(view, locals) do |*name| view._layout_for(*name, &@block) end end @@ -342,10 +344,18 @@ module ActionView end end - def find_template(path=@path) - return path unless path.is_a?(String) + def find_partial + if path = @path + locals = @locals.keys + locals << @variable + locals << @variable_counter if @collection + find_template(path, locals) + end + end + + def find_template(path=@path, locals=@locals.keys) prefix = @view.controller_path unless path.include?(?/) - @view.find_template(path, prefix, true) + @view.find_template(path, prefix, true, locals) end def partial_path(object = @object) diff --git a/actionpack/lib/action_view/render/rendering.rb b/actionpack/lib/action_view/render/rendering.rb index 5320245173..0771b40c37 100644 --- a/actionpack/lib/action_view/render/rendering.rb +++ b/actionpack/lib/action_view/render/rendering.rb @@ -34,16 +34,18 @@ module ActionView # Determine the template to be rendered using the given options. def _determine_template(options) #:nodoc: + keys = (options[:locals] ||= {}).keys + if options.key?(:inline) handler = Template.handler_class_for_extension(options[:type] || "erb") - Template.new(options[:inline], "inline template", handler, {}) + Template.new(options[:inline], "inline template", handler, { :locals => keys }) elsif options.key?(:text) Template::Text.new(options[:text], formats.try(:first)) elsif options.key?(:file) - with_fallbacks { find_template(options[:file], options[:prefix]) } + with_fallbacks { find_template(options[:file], options[:prefix], false, keys) } elsif options.key?(:template) options[:template].respond_to?(:render) ? - options[:template] : find_template(options[:template], options[:prefix]) + options[:template] : find_template(options[:template], options[:prefix], false, keys) end end @@ -51,7 +53,7 @@ module ActionView # supplied as well. def _render_template(template, layout = nil, options = {}) #:nodoc: locals = options[:locals] || {} - layout = find_layout(layout) if layout + layout = find_layout(layout, locals.keys) if layout ActiveSupport::Notifications.instrument("render_template.action_view", :identifier => template.identifier, :layout => layout.try(:virtual_path)) do |