From 130fe74d17404e5c06353526c7b20beb4019cb69 Mon Sep 17 00:00:00 2001 From: David Heinemeier Hansson Date: Wed, 19 Nov 2008 14:00:16 +0100 Subject: Changed the default of ActionView#render to assume partials instead of files when not given an options hash [DHH] --- actionpack/CHANGELOG | 16 +++++++++++ actionpack/lib/action_view/base.rb | 23 +++++++++++----- actionpack/lib/action_view/partials.rb | 32 ++++++++++++++++++++++ actionpack/test/fixtures/test/hello.builder | 2 +- .../test/template/compiled_templates_test.rb | 14 +++++----- actionpack/test/template/render_test.rb | 22 ++++++++++----- 6 files changed, 87 insertions(+), 22 deletions(-) (limited to 'actionpack') diff --git a/actionpack/CHANGELOG b/actionpack/CHANGELOG index 4ed39133db..94a02c5325 100644 --- a/actionpack/CHANGELOG +++ b/actionpack/CHANGELOG @@ -1,5 +1,21 @@ *2.3.0/3.0* +* Changed the default of ActionView#render to assume partials instead of files when not given an options hash [DHH]. Examples: + + # Instead of <%= render :partial => "account" %> + <%= render "account" %> + + # Instead of <%= render :partial => "account", :locals => { :account => @buyer } %> + <%= render "account", :account => @buyer %> + + # @account is an Account instance, so it uses the RecordIdentifier to replace + # <%= render :partial => "accounts/account", :locals => { :account => @account } %> + <%= render(@account) %> + + # @posts is an array of Post instances, so it uses the RecordIdentifier to replace + # <%= render :partial => "posts/post", :collection => @posts %> + <%= render(@posts) %> + * Fixed RedCloth and BlueCloth shouldn't preload. Instead just assume that they're available if you want to use textilize and markdown and let autoload require them [DHH] diff --git a/actionpack/lib/action_view/base.rb b/actionpack/lib/action_view/base.rb index 511858dd9b..0d3752d875 100644 --- a/actionpack/lib/action_view/base.rb +++ b/actionpack/lib/action_view/base.rb @@ -234,16 +234,21 @@ module ActionView #:nodoc: @view_paths = self.class.process_view_paths(paths) end - # Renders the template present at template_path (relative to the view_paths array). - # The hash in local_assigns is made available as local variables. + # Returns the result of a render that's dictated by the options hash. The primary options are: + # + # * :partial - See ActionView::Partials. + # * :update - Calls update_page with the block given. + # * :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 = {}, local_assigns = {}, &block) #:nodoc: local_assigns ||= {} - if options.is_a?(String) - render(:file => options, :locals => local_assigns) - elsif options == :update - update_page(&block) - elsif options.is_a?(Hash) + case options + when Hash options = options.reverse_merge(:locals => {}) if options[:layout] _render_with_layout(options, local_assigns, &block) @@ -256,6 +261,10 @@ module ActionView #:nodoc: elsif options[:text] options[:text] end + when :update + update_page(&block) + else + render_partial(:partial => options, :locals => local_assigns) end end diff --git a/actionpack/lib/action_view/partials.rb b/actionpack/lib/action_view/partials.rb index 8841099900..bbc995a340 100644 --- a/actionpack/lib/action_view/partials.rb +++ b/actionpack/lib/action_view/partials.rb @@ -46,6 +46,38 @@ module ActionView # # This will render the partial "advertisement/_ad.erb" regardless of which controller this is being called from. # + # == Rendering objects with the RecordIdentifier + # + # Instead of explicitly naming the location of a partial, you can also let the RecordIdentifier do the work if + # you're following its conventions for RecordIdentifier#partial_path. Examples: + # + # # @account is an Account instance, so it uses the RecordIdentifier to replace + # # <%= render :partial => "accounts/account", :locals => { :account => @buyer } %> + # <%= render :partial => @account %> + # + # # @posts is an array of Post instances, so it uses the RecordIdentifier to replace + # # <%= render :partial => "posts/post", :collection => @posts %> + # <%= render :partial => @posts %> + # + # == Rendering the default case + # + # If you're not going to be using any of the options like collections or layouts, you can also use the short-hand + # defaults of render to render partials. Examples: + # + # # Instead of <%= render :partial => "account" %> + # <%= render "account" %> + # + # # Instead of <%= render :partial => "account", :locals => { :account => @buyer } %> + # <%= render "account", :account => @buyer %> + # + # # @account is an Account instance, so it uses the RecordIdentifier to replace + # # <%= render :partial => "accounts/account", :locals => { :account => @account } %> + # <%= render(@account) %> + # + # # @posts is an array of Post instances, so it uses the RecordIdentifier to replace + # # <%= render :partial => "posts/post", :collection => @posts %> + # <%= render(@posts) %> + # # == Rendering partials with layouts # # Partials can have their own layouts applied to them. These layouts are different than the ones that are diff --git a/actionpack/test/fixtures/test/hello.builder b/actionpack/test/fixtures/test/hello.builder index 86a8bb3d7b..a471553941 100644 --- a/actionpack/test/fixtures/test/hello.builder +++ b/actionpack/test/fixtures/test/hello.builder @@ -1,4 +1,4 @@ xml.html do xml.p "Hello #{@name}" - xml << render("test/greeting") + xml << render(:file => "test/greeting") end \ No newline at end of file diff --git a/actionpack/test/template/compiled_templates_test.rb b/actionpack/test/template/compiled_templates_test.rb index e005aa0f03..f7688b2072 100644 --- a/actionpack/test/template/compiled_templates_test.rb +++ b/actionpack/test/template/compiled_templates_test.rb @@ -12,30 +12,30 @@ uses_mocha 'TestTemplateRecompilation' do def test_template_gets_compiled assert_equal 0, @compiled_templates.instance_methods.size - assert_equal "Hello world!", render("test/hello_world.erb") + assert_equal "Hello world!", render(:file => "test/hello_world.erb") assert_equal 1, @compiled_templates.instance_methods.size end def test_template_gets_recompiled_when_using_different_keys_in_local_assigns assert_equal 0, @compiled_templates.instance_methods.size - assert_equal "Hello world!", render("test/hello_world.erb") - assert_equal "Hello world!", render("test/hello_world.erb", {:foo => "bar"}) + assert_equal "Hello world!", render(:file => "test/hello_world.erb") + assert_equal "Hello world!", render(:file => "test/hello_world.erb", :locals => {:foo => "bar"}) assert_equal 2, @compiled_templates.instance_methods.size end def test_compiled_template_will_not_be_recompiled_when_rendered_with_identical_local_assigns assert_equal 0, @compiled_templates.instance_methods.size - assert_equal "Hello world!", render("test/hello_world.erb") + assert_equal "Hello world!", render(:file => "test/hello_world.erb") ActionView::Template.any_instance.expects(:compile!).never - assert_equal "Hello world!", render("test/hello_world.erb") + assert_equal "Hello world!", render(:file => "test/hello_world.erb") end def test_compiled_template_will_always_be_recompiled_when_eager_loaded_templates_is_off ActionView::PathSet::Path.expects(:eager_load_templates?).times(4).returns(false) assert_equal 0, @compiled_templates.instance_methods.size - assert_equal "Hello world!", render("#{FIXTURE_LOAD_PATH}/test/hello_world.erb") + assert_equal "Hello world!", render(:file => "#{FIXTURE_LOAD_PATH}/test/hello_world.erb") ActionView::Template.any_instance.expects(:compile!).times(3) - 3.times { assert_equal "Hello world!", render("#{FIXTURE_LOAD_PATH}/test/hello_world.erb") } + 3.times { assert_equal "Hello world!", render(:file => "#{FIXTURE_LOAD_PATH}/test/hello_world.erb") } assert_equal 1, @compiled_templates.instance_methods.size end diff --git a/actionpack/test/template/render_test.rb b/actionpack/test/template/render_test.rb index 476e651757..0323c33b95 100644 --- a/actionpack/test/template/render_test.rb +++ b/actionpack/test/template/render_test.rb @@ -8,7 +8,7 @@ class ViewRenderTest < Test::Unit::TestCase end def test_render_file - assert_equal "Hello world!", @view.render("test/hello_world.erb") + assert_equal "Hello world!", @view.render(:file => "test/hello_world.erb") end def test_render_file_not_using_full_path @@ -16,11 +16,11 @@ class ViewRenderTest < Test::Unit::TestCase end def test_render_file_without_specific_extension - assert_equal "Hello world!", @view.render("test/hello_world") + assert_equal "Hello world!", @view.render(:file => "test/hello_world") end def test_render_file_at_top_level - assert_equal 'Elastica', @view.render('/shared') + assert_equal 'Elastica', @view.render(:file => '/shared') end def test_render_file_with_full_path @@ -29,20 +29,20 @@ class ViewRenderTest < Test::Unit::TestCase end def test_render_file_with_instance_variables - assert_equal "The secret is in the sauce\n", @view.render("test/render_file_with_ivar.erb") + assert_equal "The secret is in the sauce\n", @view.render(:file => "test/render_file_with_ivar.erb") end def test_render_file_with_locals locals = { :secret => 'in the sauce' } - assert_equal "The secret is in the sauce\n", @view.render("test/render_file_with_locals.erb", locals) + assert_equal "The secret is in the sauce\n", @view.render(:file => "test/render_file_with_locals.erb", :locals => locals) end def test_render_file_not_using_full_path_with_dot_in_path - assert_equal "The secret is in the sauce\n", @view.render("test/dot.directory/render_file_with_ivar") + assert_equal "The secret is in the sauce\n", @view.render(:file => "test/dot.directory/render_file_with_ivar") end def test_render_has_access_current_template - assert_equal "test/template.erb", @view.render("test/template.erb") + assert_equal "test/template.erb", @view.render(:file => "test/template.erb") end def test_render_update @@ -51,6 +51,10 @@ class ViewRenderTest < Test::Unit::TestCase assert_equal 'alert("Hello, World!");', @view.render(:update) { |page| page.alert('Hello, World!') } end + def test_render_partial_from_default + assert_equal "only partial", @view.render("test/partial_only") + end + def test_render_partial assert_equal "only partial", @view.render(:partial => "test/partial_only") end @@ -73,6 +77,10 @@ class ViewRenderTest < Test::Unit::TestCase assert_equal "5", @view.render(:partial => "test/counter", :locals => { :counter_counter => 5 }) end + def test_render_partial_with_locals_from_default + assert_equal "only partial", @view.render("test/partial_only", :counter_counter => 5) + end + def test_render_partial_with_errors @view.render(:partial => "test/raise") flunk "Render did not raise TemplateError" -- cgit v1.2.3