From 13df194c002f362556560303da9c73a24ebb189e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Valim?= Date: Sun, 1 May 2011 19:39:57 +0200 Subject: Tidy up pending TODOs after discussion with Mr. Gatoz (@wycats). --- actionpack/lib/action_view.rb | 1 - actionpack/lib/action_view/base.rb | 9 +-- actionpack/lib/action_view/context.rb | 76 ++++-------------- actionpack/lib/action_view/helpers.rb | 2 + .../lib/action_view/helpers/rendering_helper.rb | 92 ++++++++++++++++++++++ actionpack/lib/action_view/rendering.rb | 33 -------- .../controller/new_base/render_context_test.rb | 14 ++-- 7 files changed, 120 insertions(+), 107 deletions(-) create mode 100644 actionpack/lib/action_view/helpers/rendering_helper.rb delete mode 100644 actionpack/lib/action_view/rendering.rb (limited to 'actionpack') diff --git a/actionpack/lib/action_view.rb b/actionpack/lib/action_view.rb index 69c50a056c..92b6f7c770 100644 --- a/actionpack/lib/action_view.rb +++ b/actionpack/lib/action_view.rb @@ -35,7 +35,6 @@ module ActionView autoload :Helpers autoload :LookupContext autoload :PathSet - autoload :Rendering autoload :Template autoload :TestCase diff --git a/actionpack/lib/action_view/base.rb b/actionpack/lib/action_view/base.rb index baa2c5729f..ca0a89c8a5 100644 --- a/actionpack/lib/action_view/base.rb +++ b/actionpack/lib/action_view/base.rb @@ -131,7 +131,7 @@ module ActionView #:nodoc: # # More builder documentation can be found at http://builder.rubyforge.org. class Base - include Helpers, Rendering, ::ERB::Util, Context + include Helpers, ::ERB::Util, Context # Specify the proc used to decorate input tags that refer to attributes with errors. cattr_accessor :field_error_proc @@ -186,11 +186,6 @@ module ActionView #:nodoc: assign(assigns_for_first_render) self.helpers = Module.new unless self.class.helpers - # Context vars initialization - @view_flow = OutputFlow.new - @output_buffer = nil - @virtual_path = nil - @_config = {} if @_controller = controller @_request = controller.request if controller.respond_to?(:request) @@ -207,6 +202,8 @@ module ActionView #:nodoc: lookup_context.formats = formats if formats @view_renderer = ActionView::Renderer.new(lookup_context, controller) end + + _prepare_context end # TODO Is this needed anywhere? Maybe deprecate it? diff --git a/actionpack/lib/action_view/context.rb b/actionpack/lib/action_view/context.rb index d501a6eaf9..083856b2ca 100644 --- a/actionpack/lib/action_view/context.rb +++ b/actionpack/lib/action_view/context.rb @@ -10,71 +10,27 @@ module ActionView # # In order to work with ActionController, a Context must just include this module. # The initialization of the variables used by the context (@output_buffer, @view_flow, - # and @virtual_path) is responsibility of the object that includes this module. + # and @virtual_path) is responsibility of the object that includes this module + # (although you can call _prepare_context defined below). module Context include CompiledTemplates attr_accessor :output_buffer, :view_flow - # TODO Provide an easy method that initializes all variables? - - # Returns the contents that are yielded to a layout, given a name or a block. - # - # You can think of a layout as a method that is called with a block. If the user calls - # yield :some_name, the block, by default, returns content_for(:some_name). - # If the user calls simply +yield+, the default block returns content_for(:layout). - # - # The user can override this default by passing a block to the layout: - # - # # The template - # <%= render :layout => "my_layout" do %> - # Content - # <% end %> - # - # # The layout - # - # <%= yield %> - # - # - # 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 - # - # - # Content - # - # - # Finally, the block can take block arguments, which can be passed in by +yield+: - # - # # The template - # <%= render :layout => "my_layout" do |customer| %> - # Hello <%= customer.name %> - # <% end %> - # - # # The layout - # - # <%= yield Struct.new(:name).new("David") %> - # - # - # In this case, the layout would receive the block passed into render :layout, - # and the struct specified would be passed into the block as an argument. The result - # would be - # - # - # Hello David - # - # - def _layout_for(*args, &block) - name = args.first + # Prepares the context by setting the appropriate instance variables. + # :api: plugin + def _prepare_context + @view_flow = OutputFlow.new + @output_buffer = nil + @virtual_path = nil + end - if name.is_a?(Symbol) - view_flow.get(name).html_safe - elsif block - # TODO Import capture into AV::Context or - # leave it as implicit dependency? - capture(*args, &block) - else - view_flow.get(:layout).html_safe - end + # Encapsulates the interaction with the view flow so it + # returns the correct buffer on yield. This is usually + # overwriten by helpers to add more behavior. + # :api: plugin + def _layout_for(name=nil) + name ||= :layout + view_flow.get(name).html_safe end end end \ No newline at end of file diff --git a/actionpack/lib/action_view/helpers.rb b/actionpack/lib/action_view/helpers.rb index 205116f610..3ef9826d30 100644 --- a/actionpack/lib/action_view/helpers.rb +++ b/actionpack/lib/action_view/helpers.rb @@ -19,6 +19,7 @@ module ActionView #:nodoc: autoload :NumberHelper autoload :OutputSafetyHelper autoload :RecordTagHelper + autoload :RenderingHelper autoload :SanitizeHelper autoload :SprocketsHelper autoload :TagHelper @@ -48,6 +49,7 @@ module ActionView #:nodoc: include NumberHelper include OutputSafetyHelper include RecordTagHelper + include RenderingHelper include SanitizeHelper include SprocketsHelper include TagHelper diff --git a/actionpack/lib/action_view/helpers/rendering_helper.rb b/actionpack/lib/action_view/helpers/rendering_helper.rb new file mode 100644 index 0000000000..c91e03b7e8 --- /dev/null +++ b/actionpack/lib/action_view/helpers/rendering_helper.rb @@ -0,0 +1,92 @@ +module ActionView + module Helpers + # = Action View Rendering + # + # Implements methods that allow rendering from a view context. + # In order to use this module, all you need is to implement + # view_renderer that returns an ActionView::Renderer object. + module RenderingHelper + # Returns the result of a render that's dictated by the options hash. The primary options are: + # + # * :partial - See ActionView::Partials. + # * :file - Renders an explicit template file (this used to be the old default), add :locals to pass in those. + # * :inline - Renders an inline template similar to how it's done in the controller. + # * :text - Renders the text passed in out. + # + # 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 = {}, locals = {}, &block) + case options + when Hash + if block_given? + view_renderer.render_partial(self, options.merge(:partial => options[:layout]), &block) + elsif options.key?(:partial) + view_renderer.render_partial(self, options) + else + view_renderer.render_template(self, options) + end + else + view_renderer.render_partial(self, :partial => options, :locals => locals) + end + end + + # Overwrites _layout_for in the context object so it supports the case a block is + # passed to a partial. Returns the contents that are yielded to a layout, given a + # name or a block. + # + # You can think of a layout as a method that is called with a block. If the user calls + # yield :some_name, the block, by default, returns content_for(:some_name). + # If the user calls simply +yield+, the default block returns content_for(:layout). + # + # The user can override this default by passing a block to the layout: + # + # # The template + # <%= render :layout => "my_layout" do %> + # Content + # <% end %> + # + # # The layout + # + # <%= yield %> + # + # + # 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 + # + # + # Content + # + # + # Finally, the block can take block arguments, which can be passed in by +yield+: + # + # # The template + # <%= render :layout => "my_layout" do |customer| %> + # Hello <%= customer.name %> + # <% end %> + # + # # The layout + # + # <%= yield Struct.new(:name).new("David") %> + # + # + # In this case, the layout would receive the block passed into render :layout, + # and the struct specified would be passed into the block as an argument. The result + # would be + # + # + # Hello David + # + # + def _layout_for(*args, &block) + name = args.first + + if block && !name.is_a?(Symbol) + capture(*args, &block) + else + super + end + end + end + end +end \ No newline at end of file diff --git a/actionpack/lib/action_view/rendering.rb b/actionpack/lib/action_view/rendering.rb deleted file mode 100644 index 25ec450e6e..0000000000 --- a/actionpack/lib/action_view/rendering.rb +++ /dev/null @@ -1,33 +0,0 @@ -module ActionView - # = Action View Rendering - # - # Implements methods that allow rendering from a view context. - # In order to use this module, all you need is to implement - # view_renderer that returns an ActionView::Renderer object. - module Rendering - # Returns the result of a render that's dictated by the options hash. The primary options are: - # - # * :partial - See ActionView::Partials. - # * :file - Renders an explicit template file (this used to be the old default), add :locals to pass in those. - # * :inline - Renders an inline template similar to how it's done in the controller. - # * :text - Renders the text passed in out. - # - # 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 = {}, locals = {}, &block) - def render(options = {}, locals = {}, &block) - case options - when Hash - if block_given? - view_renderer.render_partial(self, options.merge(:partial => options[:layout]), &block) - elsif options.key?(:partial) - view_renderer.render_partial(self, options) - else - view_renderer.render_template(self, options) - end - else - view_renderer.render_partial(self, :partial => options, :locals => locals) - end - end - end -end \ No newline at end of file diff --git a/actionpack/test/controller/new_base/render_context_test.rb b/actionpack/test/controller/new_base/render_context_test.rb index 3174bf42ab..f41b14d5d6 100644 --- a/actionpack/test/controller/new_base/render_context_test.rb +++ b/actionpack/test/controller/new_base/render_context_test.rb @@ -1,5 +1,8 @@ require 'abstract_unit' +# This is testing the decoupling of view renderer and view context +# by allowing the controller to be used as view context. This is +# similar to the way sinatra renders templates. module RenderContext class BasicController < ActionController::Base self.view_paths = [ActionView::FixtureResolver.new( @@ -7,15 +10,11 @@ module RenderContext "layouts/basic.html.erb" => "?<%= yield %>?" )] - # Include ViewContext + # 1) Include ActionView::Context to bring the required dependencies include ActionView::Context - # And initialize the required variables - before_filter do - @output_buffer = nil - @virtual_path = nil - @view_flow = ActionView::OutputFlow.new - end + # 2) Call _prepare_context that will do the required initialization + before_filter :_prepare_context def hello_world @value = "Hello" @@ -29,6 +28,7 @@ module RenderContext protected + # 3) Set view_context to self def view_context self end -- cgit v1.2.3