Shared Layouts

I have a very simple question about shared_layouts - how do I use it? I
saw the readme and it says that it Allows Rails controllers/actions to
use Radiant layouts as their “layout”. I already have a Radiant app
directory called newsite. Should I also do a rails newsite so that the
default Rails stuff is created there?

I’m sorry this sounds like a real newbie :slight_smile: but I’ve either done 100%
Rails or done 100% Radiant so far!

Thanks,
Mohit.
7/6/2008 | 11:55 PM.

Mohit S. wrote:

I have a very simple question about shared_layouts - how do I use it?
I saw the readme and it says that it Allows Rails controllers/actions
to use Radiant layouts as their “layout”. I already have a Radiant
app directory called newsite. Should I also do a rails newsite so
that the default Rails stuff is created there?

I’m sorry this sounds like a real newbie :slight_smile: but I’ve either done 100%
Rails or done 100% Radiant so far!
Since there seems to be some confusion about how to use share_layouts
lately, I’ll break it down into steps for you and everyone.

  1. Create an extension and a controller in it that you want to render
    views within a Radiant layout.

  2. Create the layout in the Radiant interface, paying close attention to
    the page parts that you are rendering with the <r:content /> tag.
    Example:

Save that as a layout called ‘Two-Column’.

  1. Add the radiant_layout declaration to your controller(s), like so:

radiant_layout ‘Two-Column’

In this case, I would be referring to the Radiant layout stored in the
database called ‘Two-Column’ that we created above. There are other
ways to determine which layout to use, and I’ll discuss some of those at
the end.

  1. Now, construct your view to create captured blocks that correspond to
    the page parts. The default ‘yield’ or ‘content_for_layout’ in a Rails
    view corresponds to the Radiant ‘body’ part. Example:

<% content_for :sidebar do %>

This is the sidebar. It will be rendered inside an r:content tag that refers to the 'sidebar' part.

<% end %>

Hello World!

This is the main content. It is outside any content_for block but will be turned into the 'body' part.

  1. Check that your routes are properly defined to point to your
    controller and then hit the appropriate action in your browser. Et
    voila! Here’s what the rendered view might look like:

Hello World!

This is the main content. It is outside any content_for block but will be turned into the 'body' part.

This is the sidebar. It will be rendered inside an r:content tag that refers to the 'sidebar' part.

That’s the basics.

Now, I promised that there were some other tricks, so I ought to explain
those.

First, similarly to the Rails ‘layout’ declaration, you can pass a block
that will be executed at runtime to determine the proper layout. A good
use-case for this would be to specify the layout you want to use in a
Radiant::Config key. Example:

radiant_layout { |controller| Radiant::Config[‘my_extension.layout’] }

Given the controller gets passed in as well, you can monkey with
whatever you need there, including the path parameters, session, etc.

Second, if you want your controllers to have more context within the
rest of the site’s static content, you can create what I like to call
“application endpoints”. Essentially, create a page within the page
tree that is of type ‘Application’ (classname RailsPage) at a URL that
matches your controller’s route(s). Then when you hit your controller
action, anything that is not directly specified by your view or
controller, including title, breadcrumbs, page parts, etc will be
derived from the existing page. This allows you to keep context within
generated navigation or provide static text within your view that is
editable from the Radiant UI. I don’t think I have it implemented
correctly, but ideally one should be able to select a layout on the page
in the tree and have it set the controller’s layout (I’ll probably fix
that today).

Third, you can manually define the title and breadcrumbs from within
your view or controller. Setting @title and @breadcrumbs or creating
content blocks for them will override the title and breadcrumbs for a
found “endpoint” or define them for a controller without an “endpoint”.
Example:

<% content_for :title do %>My beautiful web page<% end %>
<% content_for :breadcrumbs do %>Home > My beautiful web page<% end
%>

Another neat trick you can do with share_layouts is to generate Radius
code from your controller’s views. Since essentially anything generated
by the Rails view gets inserted into page parts and then rendered as if
it were a page, you can put anything you want in there that is valid
Radius code. Additionally, if you create an “endpoint” in the tree and
specify some filters on parts that will be overridden, your view can be
filtered with those filters. This means you could write your views in
Textile, Markdown, or whatever other filter you want!

I know that’s a lot to take in, so I’ll try to write up a tutorial on
the wiki for it. Hope this explanation helps you!

Cheers,

Sean

On Jul 6, 2008, at 1:06 PM, Sean C. wrote:

Since there seems to be some confusion about how to use
share_layouts lately, I’ll break it down into steps for you and
everyone.

I hope this makes it on the wiki somewhere. :slight_smile:


John L.
http://wiseheartdesign.com

I thought when you built an “endpoint” all its parts were removed and
only your controller’s views were used, instead. How can I edit the
static text in my view via the Radiant UI? That would be awesome.

That was a recent addition. Someone (I don’t recall who) was annoyed by
it clearing all existing parts. We discussed and mulled it over, and I
decided that, as long as they aren’t saved, it’s ok to overwrite
existing parts. Take a look at RailsPage#build_parts_from_hash to see
how that works.

So, in your example above, you created a “sidebar” and a “body” part
within your rails views. And I wanted to write the sidebar using
Textile and the body using Markdown, I would create an Endpoint Page
via the Radiant UI corresponding to my controller and in it create two
Page Parts - “sidebar” and “body” and assign each part the correct
filter.

Is this correct?

Exactly, except that the “endpoint” page is going to be called
“Application” in the UI. I’m open to changes on this if someone has a
better name.

Sean

Thanks for the write-up. I’ve been using Shared Layouts but I learned
a few things I didn’t know from this.

I do have two questions from what you’ve said, though

Sean C. wrote:

Second, if you want your controllers to have more context within the
rest of the site’s static content, you can create what I like to call
“application endpoints”. Essentially, create a page within the page
tree that is of type ‘Application’ (classname RailsPage) at a URL that
matches your controller’s route(s). Then when you hit your controller
action, anything that is not directly specified by your view or
controller, including title, breadcrumbs, page parts, etc will be
derived from the existing page. This allows you to keep context
within generated navigation or provide static text within your view
that is editable from the Radiant UI.

I thought when you built an “endpoint” all its parts were removed and
only your controller’s views were used, instead. How can I edit the
static text in my view via the Radiant UI? That would be awesome.

Another neat trick you can do with share_layouts is to generate Radius
code from your controller’s views. Since essentially anything
generated by the Rails view gets inserted into page parts and then
rendered as if it were a page, you can put anything you want in there
that is valid Radius code. Additionally, if you create an “endpoint”
in the tree and specify some filters on parts that will be overridden,
your view can be filtered with those filters.

So, in your example above, you created a “sidebar” and a “body” part
within your rails views. And I wanted to write the sidebar using
Textile and the body using Markdown, I would create an Endpoint Page via
the Radiant UI corresponding to my controller and in it create two Page
Parts - “sidebar” and “body” and assign each part the correct filter.

Is this correct?

-Chris

Sean C. wrote:

Since there seems to be some confusion about how to use share_layouts
lately, I’ll break it down into steps for you and everyone.

Thanks a lot, Sean for this post and the article on the wiki. I shall
definitely try this in the next few days, and make modifications to the
wiki, if needed.

Best wishes
Mohit.

I got one started with a lot more detail than the email message. I’ll
try to finish the rest tonight:

http://wiki.radiantcms.org/Creating_an_extension_VI

Cheers,

Sean

That’s strange… maybe I was logged in at the time I hit that action.
I’ll update the wiki to add that line.

Sean

In your example, Sean, you create a StatsController that inherits from
ApplicationController (which is the default if you use Radiant’s
controller generators). Anyway I’ve been getting all kinds of errors
with my specs and banging my head against a wall only to finally
realize that ApplicationController includes the LoginSystem. (I’m
always logged in so I never noticed).

I’d like to save others the bloody foreheads since most using the Shared
Layouts extension will be designing public-facing controllers.
Thoughts?

For others, I fixed this by simply adding:
no_login_required

to my controller.

In fact, other than maybe rescue_action_in_public, is there any real
benefit to inheriting from ApplicationController vs. good ol’
ActionController::Base for a Shared Layouts Controller?

-Chris