From 2995d24a259cc7b2163686fb660e5a73da9974bd Mon Sep 17 00:00:00 2001 From: Federico Brubacher Date: Fri, 14 May 2010 23:46:06 -0300 Subject: [PATCH] if an action doesn't match the layout condition, it should render its parent layout --- actionpack/lib/abstract_controller/layouts.rb | 15 ++++++- actionpack/test/abstract/layouts_test.rb | 53 +++++++++++++++++++++++++ 2 files changed, 65 insertions(+), 3 deletions(-) diff --git a/actionpack/lib/abstract_controller/layouts.rb b/actionpack/lib/abstract_controller/layouts.rb index 319472c..a4ab9e7 100644 --- a/actionpack/lib/abstract_controller/layouts.rb +++ b/actionpack/lib/abstract_controller/layouts.rb @@ -136,8 +136,8 @@ module AbstractController # # end # - # This will assign "weblog_standard" as the WeblogController's layout except for the +rss+ action, which will not wrap a layout - # around the rendered view. + # This will assign "weblog_standard" as the WeblogController's layout except for the +rss+ action, which will use whatever layout + # applies from the superclass. # # Both the :only and :except condition can accept an arbitrary number of method references, so # #:except => [ :rss, :text_only ] is valid, as is :except => :rss. @@ -309,6 +309,11 @@ module AbstractController # This will be overwritten by _write_layout_method def _layout; end + def _parent_layout + parent_layout = self.class.superclass.instance_variable_get(:@_layout) + parent_layout.is_a?(Proc)? parent_layout.call(self) : parent_layout + end + # Determine the layout for a given name and details, taking into account # the name type. # @@ -343,7 +348,11 @@ module AbstractController # Template:: The template object for the default layout (or nil) def _default_layout(require_layout = false) begin - layout_name = _layout if action_has_layout? + if action_has_layout? + layout_name = _layout + else + layout_name = _parent_layout + end rescue NameError => e raise NoMethodError, "You specified #{@_layout.inspect} as the layout, but no such method was found" diff --git a/actionpack/test/abstract/layouts_test.rb b/actionpack/test/abstract/layouts_test.rb index f580ad4..b4d9de5 100644 --- a/actionpack/test/abstract/layouts_test.rb +++ b/actionpack/test/abstract/layouts_test.rb @@ -11,6 +11,8 @@ module AbstractControllerTests self.view_paths = [ActionView::FixtureResolver.new( "layouts/hello.erb" => "With String <%= yield %>", "layouts/hello_override.erb" => "With Override <%= yield %>", + "layouts/will_only_show_on_index.erb" => "I'm in index <%= yield %>", + "layouts/will_not_show_on_new.erb" => "I'm not in new <%= yield %>", "layouts/overwrite.erb" => "Overwrite <%= yield %>", "layouts/with_false_layout.erb" => "False Layout <%= yield %>", "abstract_controller_tests/layouts/with_string_implied_child.erb" => @@ -57,6 +59,20 @@ module AbstractControllerTests layout "hello_override" end + class WithStringOverriddenChildWithOnlyCondition < WithString + layout "will_only_show_on_index", :only => :index + def new + render :template => ActionView::Template::Text.new("Hello string!") + end + end + + class WithStringOverriddenChildWithExceptCondition < WithString + layout "will_not_show_on_new", :except => :new + def new + render :template => ActionView::Template::Text.new("Hello string!") + end + end + class WithNilChild < WithString layout nil end @@ -75,6 +91,13 @@ module AbstractControllerTests end end + class WithProcOverriddenChildWithOnlyCondition < WithProc + layout "will_only_show_on_index", :only => :index + def new + render :template => ActionView::Template::Text.new("Hello proc!") + end + end + class WithSymbol < Base layout :hello @@ -244,6 +267,36 @@ module AbstractControllerTests assert_equal "With Override Hello string!", controller.response_body end + test "when a child controller has specified a layout with an 'only' condition, use that layout and not the parent controller in the specified conditon action" do + controller = WithStringOverriddenChildWithOnlyCondition.new + controller.process(:index) + assert_equal "I'm in index Hello string!", controller.response_body + end + + test "when a child controller has specified a layout with an 'only' condition, and the action does not fit in the condition, it should render the parent action" do + controller = WithStringOverriddenChildWithOnlyCondition.new + controller.process(:new) + assert_equal "With String Hello string!", controller.response_body + end + + test "when a child controller has specified a layout with an 'only' condition, and the action does not fit in the condition, it should render the parent action, when the parent layout is a proc" do + controller = WithProcOverriddenChildWithOnlyCondition.new + controller.process(:new) + assert_equal "Overwrite Hello proc!", controller.response_body + end + + test "when a child controller has specified a layout with a 'except' condition, and the action does not fit in the condition, it should render the parent action" do + controller = WithStringOverriddenChildWithExceptCondition.new + controller.process(:index) + assert_equal "I'm not in new Hello string!", controller.response_body + end + + test "when a child controller has specified a layout with a 'except' condition, use that layout and not the parent controller in the specified conditon action" do + controller = WithStringOverriddenChildWithExceptCondition.new + controller.process(:new) + assert_equal "With String Hello string!", controller.response_body + end + test "when a child controller has an implied layout, use that layout and not the parent controller layout" do controller = WithStringImpliedChild.new controller.process(:index) -- 1.7.0.5