Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

content_for vs yield in partials

In rails 3.0 with HAML (3.1.4) I have

  1. some template-like partial, like _template.html.haml:

    .panel.top
      = yield :panel_top
    
    .content
      = yield
    
  2. some another partial which will be displayed using prev template (all this stuff is rendered using AJAX, but this doesn't matter)

    - content_for :panel_top do
     .title.left
       = title
    
    content text
    

and this worked like a charm in Rails 3.0

But, after upgrade to 3.2 this fails! Yiels just yields "content text", so I have "content text" twice and no title at all

only changing = yield :panel_top to = content_for :panel_top works for 3.2

I am not sure that this solution is ok, and if it is stable or recommended, I cannot find any notes about changes in yield processing nor in Rails 3.1 release notes, nor in 3.2 ones.

Can you help what is the best way to organize yielding inside partials?

like image 586
Wile E. Avatar asked Feb 07 '12 22:02

Wile E.


People also ask

What is the difference between Content_for and yield?

They are opposite ends of the rendering process, with yield specifying where content goes, and content_for specifying what the actual content is.

What is render partial Rails?

Rails Guides describes partials this way: Partial templates - usually just called "partials" - are another device for breaking the rendering process into more manageable chunks. With a partial, you can move the code for rendering a particular piece of a response to its own file.

How should you use nested layouts in rails?

Rails provides us great functionality for managing layouts in a web application. The layouts removes code duplication in view layer. You are able to slice all your application pages to blocks such as header, footer, sidebar, body and etc.


1 Answers

From Rails 3.0 to Rails 3.2 content_for was really changed:

3.0:

def content_for(name, content = nil, &block)
    content = capture(&block) if block_given?
    @_content_for[name] << content if content
    @_content_for[name] unless content
end

3.2:

def content_for(name, content = nil, &block)
  if content || block_given?
    content = capture(&block) if block_given?
    @view_flow.append(name, content) if content
    nil
  else
    @view_flow.get(name)
  end
end

This shows us, that from 3.2 content_for works for showing/inserting content too, not only store it for named section.

Also, if you make an attempt to debug yield logic you'll se that it yields before content_for is correctly initialized.

So, leaving fragment caching out of this discussion I can conclude that content_for is preferrable way to insert named sections anywhere except top-level layouts. In helpers and other situations yield should render wrong results.

like image 131
Wile E. Avatar answered Oct 04 '22 02:10

Wile E.