diff options
author | José Valim <jose.valim@gmail.com> | 2010-03-08 14:46:57 +0100 |
---|---|---|
committer | José Valim <jose.valim@gmail.com> | 2010-03-08 14:46:57 +0100 |
commit | ea68fe59c670dd5580f3aa34fdfa0eb89eb717d3 (patch) | |
tree | 2321ba1aa0e720af1de7c7a87b17fc5075cf07a6 /actionpack/lib | |
parent | 0a85380966e47a38292242e6c3b259d77c738ab5 (diff) | |
download | rails-ea68fe59c670dd5580f3aa34fdfa0eb89eb717d3.tar.gz rails-ea68fe59c670dd5580f3aa34fdfa0eb89eb717d3.tar.bz2 rails-ea68fe59c670dd5580f3aa34fdfa0eb89eb717d3.zip |
More refactoring on the views side of rendering.
Diffstat (limited to 'actionpack/lib')
-rw-r--r-- | actionpack/lib/abstract_controller/layouts.rb | 9 | ||||
-rw-r--r-- | actionpack/lib/action_view.rb | 1 | ||||
-rw-r--r-- | actionpack/lib/action_view/base.rb | 2 | ||||
-rw-r--r-- | actionpack/lib/action_view/render/layouts.rb | 64 | ||||
-rw-r--r-- | actionpack/lib/action_view/render/partials.rb | 33 | ||||
-rw-r--r-- | actionpack/lib/action_view/render/rendering.rb | 95 |
6 files changed, 101 insertions, 103 deletions
diff --git a/actionpack/lib/abstract_controller/layouts.rb b/actionpack/lib/abstract_controller/layouts.rb index 6ac3806149..2f9616124a 100644 --- a/actionpack/lib/abstract_controller/layouts.rb +++ b/actionpack/lib/abstract_controller/layouts.rb @@ -281,14 +281,9 @@ module AbstractController super if _include_layout?(options) - layout = options.key?(:layout) ? options[:layout] : :default + layout = options.key?(:layout) ? options.delete(:layout) : :default value = _layout_for_option(layout) - - # TODO Revisit this. Maybe we should pass a :layout_prefix? - options[:layout] = ((!value || value =~ /\blayouts/) ? value : "layouts/#{value}") - - # TODO Revisit this. :layout with :partial from controllers are not the same as in views - options[:layout] = view_context._find_layout(options[:layout]) if options.key?(:partial) + options[:layout] = (value =~ /\blayouts/ ? value : "layouts/#{value}") if value end end diff --git a/actionpack/lib/action_view.rb b/actionpack/lib/action_view.rb index f5035fe45a..f111950540 100644 --- a/actionpack/lib/action_view.rb +++ b/actionpack/lib/action_view.rb @@ -37,6 +37,7 @@ module ActionView autoload :Helpers autoload_under "render" do + autoload :Layouts autoload :Partials autoload :Rendering end diff --git a/actionpack/lib/action_view/base.rb b/actionpack/lib/action_view/base.rb index 5acd2a8b82..656d73e32d 100644 --- a/actionpack/lib/action_view/base.rb +++ b/actionpack/lib/action_view/base.rb @@ -173,7 +173,7 @@ module ActionView #:nodoc: module Subclasses end - include Helpers, Rendering, Partials, ::ERB::Util + include Helpers, Rendering, Partials, Layouts, ::ERB::Util extend ActiveSupport::Memoizable diff --git a/actionpack/lib/action_view/render/layouts.rb b/actionpack/lib/action_view/render/layouts.rb new file mode 100644 index 0000000000..e1dbd3c120 --- /dev/null +++ b/actionpack/lib/action_view/render/layouts.rb @@ -0,0 +1,64 @@ +require 'active_support/core_ext/object/try' + +module ActionView + module Layouts + + # You can think of a layout as a method that is called with a block. _layout_for + # returns the contents that are yielded to the layout. If the user calls yield + # :some_name, the block, by default, returns content_for(:some_name). If the user + # calls yield, the default block returns content_for(:layout). + # + # The user can override this default by passing a block to the layout. + # + # ==== Example + # + # # The template + # <% render :layout => "my_layout" do %>Content<% end %> + # + # # The layout + # <html><% yield %></html> + # + # In this case, instead of the default block, which would return content_for(:layout), + # this method returns the block that was passed in to render layout, and the response + # would be <html>Content</html>. + # + # Finally, the block can take block arguments, which can be passed in by yield. + # + # ==== Example + # + # # The template + # <% render :layout => "my_layout" do |customer| %>Hello <%= customer.name %><% end %> + # + # # The layout + # <html><% yield Struct.new(:name).new("David") %></html> + # + # In this case, the layout would receive the block passed into <tt>render :layout</tt>, + # and the Struct specified in the layout would be passed into the block. The result + # would be <html>Hello David</html>. + def _layout_for(name = nil, &block) #:nodoc: + if !block || name + @_content_for[name || :layout] + else + capture(&block) + end + end + + # This is the method which actually finds the layout using details in the lookup + # context object. If no layout is found, it checkes if at least a layout with + # the given name exists across all details before raising the error. + def _find_layout(layout) #:nodoc: + begin + find(layout) + rescue ActionView::MissingTemplate => e + update_details(:formats => nil) do + raise unless template_lookup.exists?(layout) + end + end + end + + # Contains the logic that actually renders the layout. + def _render_layout(layout, locals, &block) #:nodoc: + layout.render(self, locals){ |*name| _layout_for(*name, &block) } + end + end +end diff --git a/actionpack/lib/action_view/render/partials.rb b/actionpack/lib/action_view/render/partials.rb index eecc88a1e0..950c9d2cd8 100644 --- a/actionpack/lib/action_view/render/partials.rb +++ b/actionpack/lib/action_view/render/partials.rb @@ -174,9 +174,6 @@ module ActionView class PartialRenderer PARTIAL_NAMES = Hash.new {|h,k| h[k] = {} } - TEMPLATES = Hash.new {|h,k| h[k] = {} } - - attr_reader :template def initialize(view_context, options, block) @view = view_context @@ -225,6 +222,7 @@ module ActionView if !@block && (layout = @options[:layout]) content = @view._render_layout(find_template(layout), @locals){ content } end + content end end @@ -241,9 +239,9 @@ module ActionView end def collection_with_template(template = @template) - segments, locals, as = [], @locals, @options[:as] || template.variable_name + segments, locals, as, template = [], @locals, @options[:as] || @template.variable_name, @template - counter_name = template.counter_name + counter_name = template.counter_name locals[counter_name] = -1 @collection.each do |object| @@ -253,7 +251,6 @@ module ActionView segments << template.render(@view, locals) end - @template = template segments end @@ -274,7 +271,7 @@ module ActionView end def render_partial(object = @object) - locals, view = @locals, @view + locals, view, template = @locals, @view, @template object ||= locals[template.variable_name] locals[@options[:as] || template.variable_name] = object @@ -285,6 +282,7 @@ module ActionView end private + def collection if @object.respond_to?(:to_ary) @object @@ -295,11 +293,7 @@ module ActionView def find_template(path=@path) return path unless path.is_a?(String) - - if controller = @view.controller - prefix = controller.controller_path unless path.include?(?/) - end - + prefix = @view.controller_path unless path.include?(?/) @view.find(path, prefix, true) end @@ -315,21 +309,8 @@ module ActionView end end - def render_partial(options) - _evaluate_assigns_and_ivars - - details = options[:_details] - - # TODO This should happen automatically as well - self.formats = details[:formats] if details[:formats] - renderer = PartialRenderer.new(self, options, nil) - text = renderer.render - options[:_template] = renderer.template - text - end - def _render_partial(options, &block) #:nodoc: - if defined? @renderer + if defined?(@renderer) @renderer.setup(options, block) else @renderer = PartialRenderer.new(self, options, block) diff --git a/actionpack/lib/action_view/render/rendering.rb b/actionpack/lib/action_view/render/rendering.rb index c6d95e88e2..61fea6f49e 100644 --- a/actionpack/lib/action_view/render/rendering.rb +++ b/actionpack/lib/action_view/render/rendering.rb @@ -15,17 +15,12 @@ module ActionView def render(options = {}, locals = {}, &block) #:nodoc: case options when Hash - layout = options[:layout] - options[:locals] ||= {} - if block_given? - return safe_concat(_render_partial(options.merge(:partial => layout), &block)) - elsif options.key?(:partial) - return _render_partial(options) + content = _render_partial(options.merge(:partial => options[:layout]), &block) + safe_concat(content) + else + _render(options) end - - template = _determine_template(options) - _render_template(template, layout, :locals => options[:locals]) if template when :update update_page(&block) else @@ -33,50 +28,24 @@ module ActionView end end - # You can think of a layout as a method that is called with a block. _layout_for - # returns the contents that are yielded to the layout. If the user calls yield - # :some_name, the block, by default, returns content_for(:some_name). If the user - # calls yield, the default block returns content_for(:layout). - # - # The user can override this default by passing a block to the layout. - # - # ==== Example - # - # # The template - # <% render :layout => "my_layout" do %>Content<% end %> - # - # # The layout - # <html><% yield %></html> - # - # In this case, instead of the default block, which would return content_for(:layout), - # this method returns the block that was passed in to render layout, and the response - # would be <html>Content</html>. - # - # Finally, the block can take block arguments, which can be passed in by yield. - # - # ==== Example - # - # # The template - # <% render :layout => "my_layout" do |customer| %>Hello <%= customer.name %><% end %> - # - # # The layout - # <html><% yield Struct.new(:name).new("David") %></html> - # - # In this case, the layout would receive the block passed into <tt>render :layout</tt>, - # and the Struct specified in the layout would be passed into the block. The result - # would be <html>Hello David</html>. - def _layout_for(name = nil, &block) - return @_content_for[name || :layout] if !block_given? || name - capture(&block) - end - # This is the API to render a ViewContext's template from a controller. - # - # Internal Options: - # _template:: The Template object to render - # _layout:: The layout, if any, to wrap the Template in - def render_template(options) + # TODO Review this name since it does not render only templates, but also + # partials, files and so forth. + def render_template(options, &block) _evaluate_assigns_and_ivars + + # TODO Layout for partials should be handled here, because inside the + # partial renderer it looks for the layout as a partial. + if options.key?(:partial) && options[:layout] + options[:layout] = _find_layout(options[:layout]) + end + + _render(options, &block) + end + + # This method holds the common render logic for both controllers and + # views rendering stacks. + def _render(options) #:nodoc: if options.key?(:partial) _render_partial(options) else @@ -86,14 +55,13 @@ module ActionView end end - def _determine_template(options) + # Determine the template to be rendered using the given options. + def _determine_template(options) #:nodoc: if options.key?(:inline) handler = Template.handler_class_for_extension(options[:type] || "erb") Template.new(options[:inline], "inline template", handler, {}) elsif options.key?(:text) Template::Text.new(options[:text], self.formats.try(:first)) - elsif options.key?(:_template) - options[:_template] elsif options.key?(:file) find(options[:file], options[:_prefix]) elsif options.key?(:template) @@ -101,24 +69,16 @@ module ActionView end end - def _find_layout(layout) - begin - find(layout) - rescue ActionView::MissingTemplate => e - update_details(:formats => nil) do - raise unless template_lookup.exists?(layout) - end - end - end - - def _render_template(template, layout = nil, options = {}) + # Renders the given template. An string representing the layout can be + # supplied as well. + def _render_template(template, layout = nil, options = {}) #:nodoc: locals = options[:locals] || {} layout = _find_layout(layout) if layout ActiveSupport::Notifications.instrument("action_view.render_template", :identifier => template.identifier, :layout => layout.try(:identifier)) do - content = template.render(self, locals) {|*name| _layout_for(*name) } + content = template.render(self, locals) { |*name| _layout_for(*name) } @_content_for[:layout] = content if layout @@ -130,8 +90,5 @@ module ActionView end end - def _render_layout(layout, locals, &block) - layout.render(self, locals){ |*name| _layout_for(*name, &block) } - end end end |