#99
Mar 31, 2008

Complex Partials

How do you handle partials which have differences depending on the action which is rendering them? Here's three suggestions for this problem.
Download (14.7 MB, 8:56)
alternative download for iPod & Apple TV (11.5 MB, 8:56)

I should have mentioned, not all of the tips work best for this specific example. I would probably stop after the first tip. But I wanted to give you some more ideas for solving this problem which may work well in your situation.

<!-- index.html.erb -->
<% for article in @articles %>
  <% render :layout => 'article', :object => article do %>
    <p><%=h article.description %></p>
    <p><%= link_to "Read More...", article %></p>
  <% end %>
<% end %>

<!-- show.html.erb -->
<% stylesheet 'article' %>
<% render :layout => 'article', :object => @article do %>
  <%= simple_format(h(@article.content)) %>
<% end %>

<!-- _article.html.erb -->
<div class="article">
  <h2><%= link_to_unless_current h(article.name), article %></h2>
  <div class="info">
    by <%= article.author %> on <%= article.created_at.to_s(:long) %>
    <span class="comments">
      <%= link_to pluralize(article.comments.size, 'Comment'), article %>
    </span>
  </div>
  <div class="content">
    <%= yield %>
  </div>
</div>

<!-- layouts/application.html.erb -->
<%= yield(:head) %>
# application_helper.rb
def stylesheet(*args)
  content_for(:head) { stylesheet_link_tag(*args) }
end
/* article.css */
.article .comments_link {
  display: none;
}

RSS Feed for Episode Comments 14 comments

1. Olli Mar 31, 2008 at 02:10

The first thing i do on monday morning is check the new railscasts episode. Thank you for your little but powerful tips and hints :D
Greetings from Germany


2. nicolash Mar 31, 2008 at 04:08

the third example (style-sheet trick) has some negative implications for the accessibility as screenreaders still don't treat display:none consitantly.
Some will still read the link to the user, this may not be as bad in a single occasion but makes this technic to an anti-pattern in my view as this will accumulate to many wrong placed/unnecessary content for some of the users.


3. peter Mar 31, 2008 at 10:43

I'd have to agree with Nicolash, hiding content that should never be displayed through css seems like a bad idea. Also having partials specify what stylesheets to load sounds like asking for problems maintaining the app later on but maybe that's just me ;)

Other than that another great 'cast! Hard to believe it'll be 100 next week already.


4. Ted Mar 31, 2008 at 11:10

Good stuff as always, but ERB is so 2007... how about some HAML!? ;-) Jack will back me up on this.


5. Aaron H. Mar 31, 2008 at 12:30

Love the RailsCasts. I also look for them every Monday morning.

I also have to agree that hiding things via CSS that really shouldn't be displayed just strikes me as a bad idea. There may be situations where it might be OK, but I really can't think of any offhand.

However, I did love the 2nd example. How is it I've made it this far without realizing I could pass blocks to a yield in a partial? THAT is going to be extremely helpful, I think.

Thanks again for the great screencasts.


6. JEF Mar 31, 2008 at 13:24

Is it possible to make groups in a partials (maybe with header and footer)

Thanks for the great work you accomplish.


7. DAZ Apr 01, 2008 at 03:19

Great screencast - thanks Ryan. I loved method 2 - something that I'll look at using a bit more.

You seem to have 2 helper methods in your view code:
current_page?
and
simple_format

...are these helpers that you have written yourself or are they built into Rails?

cheers,

DAZ


8. Neil Apr 01, 2008 at 05:00

@DAZ - both of those helpers are built in to Rails. Check them out on the API.

Great episode, Ryan. I'll be coming back to this one a few more times. I'd agree with the other guys about the display:none, though.

I started using the current_page? method for css hooks on navigation and subsequently ran in to the appended url issue during search/pagination. I've yet to find a clean solution for a two tier tabbed navigation with highlighted current tabs - maybe this would make a good follow-up episode? I'd be interested in seeing the workarounds for the url comparison...

p.s. I find it strange that current_page? (:controller => :users) only returns true on the index action. Has anyone else noticed this?


9. Aaron H. Apr 01, 2008 at 08:10

@Neil - To answer the PS, the reason it does that is the route builder defaults to :index if you do not pass an action. When you want to ask if something is the current page it compares the route to the hash passed. If you don't pass an action, it assumes you mean index.

If you want to check the current controller only you could use something like

def current_controller?(*attrs)
  attrs.collect{|a| a.to_s}.include?(@controller.controller_name)
end

Then, in your view you can find out if you are in a particular controller (or even array of controllers) like...

link_to_unless current_controller?('home'), 'Home', home_path

link_to_unless current_controller?('admin_users', 'admin_posts'), 'Admin', admin_path


10. Robby Apr 03, 2008 at 19:14

Ryan, I am fairly a newcomer to the Ruby on Rails world over from Coldfusion. I must admit that your 'FREE' Railscasts are simply superb! Keep up the good work, you have my support!


11. test Apr 06, 2008 at 19:24

test


12. Tom Harrison May 06, 2008 at 13:41

First, thank you!

I have been noodling on how to handle various forms of similar views and think this topic warrants more episodes up here. While it's great that examples are simple by necessity, they may fall down in practice when reality strikes :-)

It's certainly the case that new vs edit forms warrant a form partial, for example. But in almost all cases it seems like there's some conditional logic depending on newness. So this means some logic in the controller, a helper or in the partial via locals, in other partials, etc. But what's the best practice?

For example, I have projects that HABTM resources. A resource can exist without a project, but is often created to be associated to that project when saved. The forms for editing are all one partial, but my Save and Back links are all a little different, and some wording and even UI varies a little depending on context. There's too much repetition to keep it DRY, but enough logic to be hairy.

It would be great to hear more about how things can be kept clean in slightly more complicated cases.

Thanks again for doing what you do.

Tom


13. Sig May 12, 2008 at 16:39

Hello Ryan (and railscasts guys),
I'm trying to render a layout through rjs but it looks like Rails doesn't render it.

page.replace_html :wrap, :layout => "details", :object => @task do
 ...
end

Am I missing something or Rails doesn't allow rendering a layout into a rjs file?

THANKS


14. kino May 23, 2008 at 01:57

As is evident upon close examination, our sense perceptions exist in the Ideal; however, natural causes are the clue to the discovery of metaphysics.

Add your comment:

(SKIP THIS ONE)

(required)

(not shown)


(use pastie or gist for code)

sponsored by:
if you want to help:
required:
Get Quicktime Player