diff options
Diffstat (limited to 'actionpack/lib/action_view/render/rendering.rb')
-rw-r--r-- | actionpack/lib/action_view/render/rendering.rb | 104 |
1 files changed, 63 insertions, 41 deletions
diff --git a/actionpack/lib/action_view/render/rendering.rb b/actionpack/lib/action_view/render/rendering.rb index 162e38c484..9c25fab6bb 100644 --- a/actionpack/lib/action_view/render/rendering.rb +++ b/actionpack/lib/action_view/render/rendering.rb @@ -10,24 +10,25 @@ module ActionView # # If no options hash is passed or :update specified, the default is to render a partial and use the second parameter # as the locals hash. - def render(options = {}, local_assigns = {}, &block) #:nodoc: - local_assigns ||= {} - - @exempt_from_layout = true - + def render(options = {}, locals = {}, &block) #:nodoc: case options + when String, NilClass + _render_partial(:partial => options, :locals => locals || {}) when Hash - options[:locals] ||= {} layout = options[:layout] - - return _render_partial_with_layout(layout, options) if options.key?(:partial) - return _render_partial_with_block(layout, block, options) if block_given? - + + if block_given? + return concat(_render_partial(options.merge(:partial => layout), &block)) + elsif options.key?(:partial) + layout = _pick_partial_template(layout) if layout + return _render_content(_render_partial(options), layout, options[:locals]) + end + layout = find_by_parts(layout, {:formats => formats}) if layout - + if file = options[:file] template = find_by_parts(file, {:formats => formats}) - _render_template_with_layout(template, layout, :locals => options[:locals]) + _render_template(template, layout, :locals => options[:locals] || {}) elsif inline = options[:inline] _render_inline(inline, layout, options) elsif text = options[:text] @@ -35,35 +36,33 @@ module ActionView end when :update update_page(&block) - when String, NilClass - _render_partial(:partial => options, :locals => local_assigns) end end - - def _render_content_with_layout(content, layout, locals) + + def _render_content(content, layout, locals) return content unless layout - + locals ||= {} if controller && layout @_layout = layout.identifier logger.info("Rendering template within #{layout.identifier}") if logger end - + begin old_content, @_content_for[:layout] = @_content_for[:layout], content @cached_content_for_layout = @_content_for[:layout] - _render_template(layout, locals) + _render_single_template(layout, locals) ensure @_content_for[:layout] = old_content end end - # You can think of a layout as a method that is called with a block. This method - # returns the block that the layout is called with. 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). + # 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. # @@ -92,15 +91,28 @@ module ActionView # 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_proc(name) - @_default_layout ||= proc { |*names| @_content_for[names.first || :layout] } - !@_content_for.key?(name) && @_proc_for_layout || @_default_layout + def _layout_for(names, &block) + with_output_buffer do + # This is due to the potentially ambiguous use of yield when + # a block is passed in to a template *and* there is a content_for() + # of the same name. Suggested solution: require explicit use of content_for + # in these ambiguous cases. + # + # We would be able to continue supporting yield in all non-ambiguous + # cases. Question: should we deprecate yield in favor of content_for + # and reserve yield for cases where there is a yield into a real block? + if @_content_for.key?(names.first) || !block_given? + return @_content_for[names.first || :layout] + else + return yield(names) + end + end end - def _render_template(template, local_assigns = {}) + def _render_single_template(template, locals = {}, &block) with_template(template) do - template.render(self, local_assigns) do |*names| - capture(*names, &layout_proc(names.first)) + template.render(self, locals) do |*names| + _layout_for(names, &block) end end rescue Exception => e @@ -115,32 +127,42 @@ module ActionView def _render_inline(inline, layout, options) handler = Template.handler_class_for_extension(options[:type] || "erb") template = Template.new(options[:inline], "inline #{options[:inline].inspect}", handler, {}) - content = _render_template(template, options[:locals] || {}) - layout ? _render_content_with_layout(content, layout, options[:locals]) : content + content = _render_single_template(template, options[:locals] || {}) + layout ? _render_content(content, layout, options[:locals]) : content end def _render_text(text, layout, options) - layout ? _render_content_with_layout(text, layout, options[:locals]) : text + layout ? _render_content(text, layout, options[:locals]) : text end - def _render_template_from_controller(*args) + # 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 + # _partial:: true if the template is a partial + def render_template(options) @assigns_added = nil - _render_template_with_layout(*args) + template, layout, partial = options.values_at(:_template, :_layout, :_partial) + _render_template(template, layout, options, partial) end - def _render_template_with_layout(template, layout = nil, options = {}, partial = false) - logger && logger.info("Rendering #{template.identifier}#{' (#{options[:status]})' if options[:status]}") + def _render_template(template, layout = nil, options = {}, partial = nil) + logger && logger.info do + msg = "Rendering #{template.identifier}" + msg << " (#{options[:status]})" if options[:status] + msg + end locals = options[:locals] || {} content = if partial - object = partial unless partial == true - _render_partial_object(template, options, object) + _render_partial_object(template, options) else - _render_template(template, locals) + _render_single_template(template, locals) end - - layout ? _render_content_with_layout(content, layout, locals) : content + + _render_content(content, layout, locals) end end end
\ No newline at end of file |