aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Heinemeier Hansson <david@loudthinking.com>2007-08-02 20:10:03 +0000
committerDavid Heinemeier Hansson <david@loudthinking.com>2007-08-02 20:10:03 +0000
commitbbbc45156bb2f903513116036619b78065f6d7e8 (patch)
tree85a3e79931142fe229c15ff04185c57272f4e0b3
parentbe196f3f7ec86e072d455cdca6acae1fd8782066 (diff)
downloadrails-bbbc45156bb2f903513116036619b78065f6d7e8.tar.gz
rails-bbbc45156bb2f903513116036619b78065f6d7e8.tar.bz2
rails-bbbc45156bb2f903513116036619b78065f6d7e8.zip
Added partial layouts (see example in action_view/lib/partials.rb) [DHH]
git-svn-id: http://svn-commit.rubyonrails.org/rails/trunk@7261 5ecf4fe2-1ee6-0310-87b1-e25e094e27de
-rw-r--r--actionpack/CHANGELOG2
-rw-r--r--actionpack/lib/action_view/base.rb12
-rw-r--r--actionpack/lib/action_view/partials.rb57
-rw-r--r--actionpack/test/controller/new_render_test.rb20
-rw-r--r--actionpack/test/fixtures/test/_layout_for_partial.html.erb3
-rw-r--r--actionpack/test/fixtures/test/_partial_for_use_in_layout.html.erb1
-rw-r--r--actionpack/test/fixtures/test/calling_partial_with_layout.html.erb1
-rw-r--r--actionpack/test/fixtures/test/using_layout_around_block.html.erb1
8 files changed, 95 insertions, 2 deletions
diff --git a/actionpack/CHANGELOG b/actionpack/CHANGELOG
index 9fbcc58ea7..48f46479b6 100644
--- a/actionpack/CHANGELOG
+++ b/actionpack/CHANGELOG
@@ -1,5 +1,7 @@
*SVN*
+* Added partial layouts (see example in action_view/lib/partials.rb) [DHH]
+
* Allow you to set custom :conditions on resource routes. [Rick]
* Fixed that file.content_type for uploaded files would include a trailing \r #9053 [bgreenlee]
diff --git a/actionpack/lib/action_view/base.rb b/actionpack/lib/action_view/base.rb
index 63ec0021b0..a8e6655bd6 100644
--- a/actionpack/lib/action_view/base.rb
+++ b/actionpack/lib/action_view/base.rb
@@ -304,7 +304,17 @@ module ActionView #:nodoc:
elsif options.is_a?(Hash)
options = options.reverse_merge(:type => :erb, :locals => {}, :use_full_path => true)
- if options[:file]
+ if options[:layout]
+ path, partial_name = partial_pieces(options.delete(:layout))
+
+ if block_given?
+ @content_for_layout = capture(&block)
+ concat(render(options.merge(:partial => "#{path}/#{partial_name}")), block.binding)
+ else
+ @content_for_layout = render(options)
+ render(options.merge(:partial => "#{path}/#{partial_name}"))
+ end
+ elsif options[:file]
render_file(options[:file], options[:use_full_path], options[:locals])
elsif options[:partial] && options[:collection]
render_partial_collection(options[:partial], options[:collection], options[:spacer_template], options[:locals])
diff --git a/actionpack/lib/action_view/partials.rb b/actionpack/lib/action_view/partials.rb
index 9da33d2ac8..e26ca499d0 100644
--- a/actionpack/lib/action_view/partials.rb
+++ b/actionpack/lib/action_view/partials.rb
@@ -44,6 +44,63 @@ module ActionView
# <%= render :partial => "advertisement/ad", :locals => { :ad => @advertisement } %>
#
# This will render the partial "advertisement/_ad.erb" regardless of which controller this is being called from.
+ #
+ # == Rendering partials with layouts
+ #
+ # Partials can have their own layouts applied to them. These layouts are different than the ones that are specified globally
+ # for the entire action, but they work in a similar fashion. Imagine a list with two types of users:
+ #
+ # <!-- app/views/users/index.html.erb -->
+ # Here's the administrator:
+ # <%= render :partial => "user", :layout => "administrator", :locals => { :user => administrator } %>
+ #
+ # Here's the editor:
+ # <%= render :partial => "user", :layout => "editor", :locals => { :user => editor } %>
+ #
+ # <!-- app/views/users/_user.html.erb -->
+ # Name: <%= user.name %>
+ #
+ # <!-- app/views/users/_administrator.html.erb -->
+ # <div id="administrator">
+ # Budget: $<%= user.budget %>
+ # <%= yield %>
+ # </div>
+ #
+ # <!-- app/views/users/_editor.html.erb -->
+ # <div id="editor">
+ # Deadline: $<%= user.deadline %>
+ # <%= yield %>
+ # </div>
+ #
+ # ...this will return:
+ #
+ # Here's the administrator:
+ # <div id="administrator">
+ # Budget: $<%= user.budget %>
+ # Name: <%= user.name %>
+ # </div>
+ #
+ # Here's the editor:
+ # <div id="editor">
+ # Deadline: $<%= user.deadline %>
+ # Name: <%= user.name %>
+ # </div>
+ #
+ # You can also apply a layout to a block within any template:
+ #
+ # <!-- app/views/users/_chief.html.erb -->
+ # <% render(:layout => "administrator", :locals => { :user => chief }) do %>
+ # Title: <%= chief.title %>
+ # <% end %>
+ #
+ # ...this will return:
+ #
+ # <div id="administrator">
+ # Budget: $<%= user.budget %>
+ # Title: <%= chief.name %>
+ # </div>
+ #
+ # As you can see, the :locals hash is shared between both the partial and its layout.
module Partials
private
# Deprecated, use render :partial
diff --git a/actionpack/test/controller/new_render_test.rb b/actionpack/test/controller/new_render_test.rb
index b1069ca820..ce254cbf0d 100644
--- a/actionpack/test/controller/new_render_test.rb
+++ b/actionpack/test/controller/new_render_test.rb
@@ -349,6 +349,14 @@ class NewRenderTestController < ActionController::Base
render :text => "hello world!"
end
+ def render_call_to_partial_with_layout
+ render :action => "calling_partial_with_layout"
+ end
+
+ def render_using_layout_around_block
+ render :action => "using_layout_around_block"
+ end
+
def rescue_action(e) raise end
private
@@ -793,4 +801,14 @@ EOS
get :render_with_object_location
assert_equal "http://www.nextangle.com/customers/1", @response.headers["Location"]
end
-end
+
+ def test_render_call_to_partial_with_layout
+ get :render_call_to_partial_with_layout
+ assert_equal "Before (David)\nInside from partial (David)\nAfter", @response.body
+ end
+
+ def test_using_layout_around_block
+ get :using_layout_around_block
+ assert_equal "Before (David)\nInside from block\nAfter", @response.body
+ end
+end \ No newline at end of file
diff --git a/actionpack/test/fixtures/test/_layout_for_partial.html.erb b/actionpack/test/fixtures/test/_layout_for_partial.html.erb
new file mode 100644
index 0000000000..666efadbb6
--- /dev/null
+++ b/actionpack/test/fixtures/test/_layout_for_partial.html.erb
@@ -0,0 +1,3 @@
+Before (<%= name %>)
+<%= yield %>
+After \ No newline at end of file
diff --git a/actionpack/test/fixtures/test/_partial_for_use_in_layout.html.erb b/actionpack/test/fixtures/test/_partial_for_use_in_layout.html.erb
new file mode 100644
index 0000000000..3a03a64e31
--- /dev/null
+++ b/actionpack/test/fixtures/test/_partial_for_use_in_layout.html.erb
@@ -0,0 +1 @@
+Inside from partial (<%= name %>) \ No newline at end of file
diff --git a/actionpack/test/fixtures/test/calling_partial_with_layout.html.erb b/actionpack/test/fixtures/test/calling_partial_with_layout.html.erb
new file mode 100644
index 0000000000..ac44bc0d81
--- /dev/null
+++ b/actionpack/test/fixtures/test/calling_partial_with_layout.html.erb
@@ -0,0 +1 @@
+<%= render(:layout => "layout_for_partial", :partial => "partial_for_use_in_layout", :locals => { :name => "David" }) %> \ No newline at end of file
diff --git a/actionpack/test/fixtures/test/using_layout_around_block.html.erb b/actionpack/test/fixtures/test/using_layout_around_block.html.erb
new file mode 100644
index 0000000000..a93fa02c9c
--- /dev/null
+++ b/actionpack/test/fixtures/test/using_layout_around_block.html.erb
@@ -0,0 +1 @@
+<% render(:layout => "layout_for_partial", :locals => { :name => "David" }) do %>Inside from block<% end %> \ No newline at end of file