One of the most useful discoveries I have made with Rails is the ability to pass variables from a layout to a view and vice versa.
This means I can set Body ID's, for example, in my views that are used in the layout. To achieve this I would put the following in my layout:
<body id="<%= @bodyid %>">
And in my view I would put at the top:
<% @bodyid = "body_home" %>
Obviously it doesn't have to be a Body Id, it could be a page title, description, rss feed path, anything. This is really powerfull because it allows you to take advantage of the template system with no need to repeat the code on every page.
You may also have noticed that it doesn't matter that the layout calls the variable before the view, Rails is clever like that. Also, it wont error if the variable doesn't get set in the view.
Personally I find setting Body IDs on pages to be really poweful in CSS styling. You can use the Body ID to highlight navigation elements to show the page you are on or render completely different page layouts. Find out more about how I do this.
About Paul
Paul works for Kyan web design agency in Surrey, UK as a Ruby on Rails developer.
Follow Paul on Twitter
Email: paulsturgess [at] gmail.com
Comments...
Neat. I was abusing content_for to get a similar effect...
For example...
In the layout:
<body>In the view:
<% give_focus 'user_username' %>
<% form_for :user do |form| %>
<%= form.text_field :username %>
...
In the helper:
def give_focus(element_id)content_for :onload do
"document.getElementById('#{element_id}').focus()"
end
end
----
Curiously, in give_focus() using braces instead of do...end didn't work, not quite sure why.
Mike Tunnicliffe at 09 Dec 07 at 19:41
Not having much luck with putting code in my comments, sorry for the mess.
Mike Tunnicliffe at 09 Dec 07 at 19:43
This works because Rails renders the view BEFORE the layout. It doesn't work the other way around (passing variables form the layout to the view). At least I haven't figured out how to do this; I would like to...
Peter at 06 May 09 at 17:02
Thanks!
this was very useful, I've been using/abusing content_for as well for things like html title
house9 at 10 Nov 09 at 17:57
well you guys weren't really abusing the content_for / yield patterns.
but for simple strings this surely is way cleaner.
i'm using this for filling the title tag. but for more complex things like adding some specific CSS/JS/RSS "content_for :head" still is the correct way.
i suggest adding a fallback into the layout like
<title><%= @page_title || 'Default Title' %></title>
wherever you use such things
neongrau at 11 Feb 10 at 06:35
I think that it is most important to have your code clean and use content_for instead of doing some savings.
Having instance variables on top of your view is more like calling a method from a class without a parameters relying on the some object /mistery/ state instead of calling the method with nice parameters.
gudata at 07 Apr 10 at 05:35
Obviously this article is some 4 years old now so there are plenty of alternative methods out there.
However, the main point still stands. You can pass instance variables from out of your view and into your template. There's no denying it's a very simple, concise and easy method for doing so.
Paul at 07 Apr 10 at 05:55
Does this work on non-PHP sites? The forum is PHP so it is working but what about the home page?
New York Forum at 29 May 10 at 00:02
Got something to say?