On 20 Dec 2010, at 22:03, Wes Gamble wrote:
> I was reading through this post on Shared Layouts
> (http://www.ruby-forum.com/topic/158686),
>
> and came across the explanation of the "Application" page type.
That was a while ago and what Sean was referring to is now just called a
RailsPage. Still not a very good name but share_layouts is a very useful tool.
Essentially, it undoes the twist that radiant has applied to the normal rails
MVC. In radiant the Page model class acts like a controller, the page content
acts like a view template and the layout content acts as a layout template.
There are no real view templates (outside admin) and the SiteController is just
a page-picker: rendering is delegated to the requested page. You can add more
public-facing controllers and views, but they exist in the normal rails world,
cut off from the rendering of radiant content.
Share_layouts fixes that by letting your normal rails controller wrap radiant
layouts around view-rendered content, and by letting your views define
pseudo-page-parts for use in those layouts.
Here's a rough hello world:
# in app/controllers/greetings_controller.rb
class GreetingsController < ApplicationController
radiant_layout "standard"
def index
@greeting = "Hello World"
end
end
# in views/greetings/index.html.haml:
%p
The :main page part is populated for you.
- content_for :title do
%h1
= @greeting
- content_for :introduction do
%p
This is the intro.
# in the "standard" layout:
<r:title />
<r:content part="introduction" />
<r:content />
The output from this, given a route to GreetingsController#index, will be:
<h1>Hello World</h1>
<p> This is the intro.</p>
<p>The :main page part is created automatically.</p>
As you see, the overall rendering of the view template is captured as a :main
page page part, and any other page part you want to bring into the template can
be declared with a content_for block. Title, :breadcrumbs and I think :slug are
treated specially.
If you don't want to hard-code the name of your radiant layout in the
controller, you can supply a block that optionally takes the controller as
argument:
radiant_layout { Radiant::Config['configured.layout'] }
or
radiant_layout { |controller| controller.choose_layout }
def choose_layout
# here all the usual request machinery is available
# include current_user and current_site, if relevant
end
Note that the block must return the name of a layout, not the layout itself.
You may also be interested in Dirk's amalgamation of this and nested_layouts
into a single layouts extension or my mailer_layouts which lets you build email
messages the same way.
best,
will