What is the difference between render and yield in Rails

15,486

Solution 1

First of all, yield is ruby, render is rails. Usually one uses a common layout for the application whose inner content changes according to action/context. The problem usually lies in defining where our layout ends and context-specific template begins. Take, for instance, the HTML title tag. Let's say you have an application called Cities. In most cases, you want your page title to be "Cities" all the time. But, if you're for instance, inside Amsterdam page, then you would like the have "Amsterdam" as your page title.

# application.html.erb
<html>
  <head>
    <%= content_for?(:page_title) ? yield(:page_title) : "Cities" %>
    ......

# city/index.html.erb
<% content_for :page_title do %>
  <%= @city.name %> 
<% end %>

<div class="bla"...

Within Rails you usually define your application title in your application layout. One strategy for changing the page title would be to use content_for in the specific cities template and change accordingly.

Render, on the other hand, accomplishes different rendering strategies. Straight. When you call render, it renders. content_for/yield doesn't render automatically, it is stored somewhere and then fills up the missing spots in the due places. So, you can think of it as more as a "store/search/replace" in comparison to render, which just plain renders.

Good rule of thumb to use one over the other is: if the template you are writing needs to present different information per context, strongly consider using content_for.

Solution 2

yield

Ruby code (Proc class) and takes your block and does what it is supposed to do with it. Yield is also fast compared with other Ruby based ways of doing the same thing. I'd assume (and I only) use it in the layouts because it's quick and I mindlessly do what's normal in Rails. yield is also used to pass content to a specific spot in your layout. I often have <%= yield :head %> in the head, just above the head tag, so that I can pass random weirdness that sometimes comes up.

Common Uses:

  • Mostly just used in layouts
  • (if you are fancy/inclined to do so in a Model) as a true Ruby Proc statement.

render

Rails code that you pass arguments to that, as the docs say, "Renders the content that will be returned to the browser as the response body". partials, actions, text, files...etc.

Common Uses:

Used in both views and the controller.

Solution 3

When your controller method exits, it renders the associated file. So the edit controller renders edit.html.erb. It uses the specified layout or application.html.erb if none is specified.

Within your layout file, when you call yield it will fill in the information from your render. If you call yield with a parameter, it will look for a content_for section in your render file matching that parameter. I'm not completely sure, but I don't think you can call yield from outside of your layout file, and I don't think it will fill in any information except that found in your render file.

Anywhere in your layout file or your rendered file, you can render a partial by calling render with the partial name minus the underscore.

I hope that helps.

Edit to answer question in comment:

yield and render perform similar functions however yield only looks in the render file whereas render specifies which file to render. Also, render outputs the entire file, but yield with a parameter can output just a subsection of the file.

Share:
15,486

Related videos on Youtube

chris Frisina
Author by

chris Frisina

Me, Smiling! stackexchange @ specialorange . org

Updated on September 14, 2022

Comments

  • chris Frisina
    chris Frisina over 1 year

    Can someone explain the difference between "<%= render %>" and "<%= yield %> with <% content_for :partial do %>/<% end %>"? specifically how the routing changes when switching from one to another, the benefits of using one over the other, when is it practical to use one over the other. THIS is the closest explanation I have found, but isn't quite clear enough for me.

    I have been trying for several days to wrap my head around this, but it seems that each configuration I try either comes close, or errors out.

    If theres are three views, aaa and bbb and ccc, and each has an index.html.erb, but bbb and ccc have a _content.html.erb partial (signified by the underscore) how can you accomplish getting the bbb or ccc partial in aaa using either render or yield?

    The following works:

    aaa's index.html.erb :

    <div">
      <%= render 'bbb/content' %>
    </div>
    

    and bbbs _content.html/erb :

    <p>Content from bbb.</p>  
    

    BUT this does NOT:

    aaa's index.html.erb :

    <div">
      <%= yield :container %>
    </div>
    

    and bbbs _content.html/erb :

    <% content_for :container do %>
      <p>Content from bbb.</p>   ### viewed in aaa
    <% end>
    

    and cccs _content.html.erb would have nothing, or the content_for, but I still dont get aaa's index.html to be populated with content.

    If I use the render, I can explicitly place the content in. But I thought that the benefit of using the yield :whatever would allow me to choose what to populate it with, and I can't get it to populate anything as soon as I change it from render to yield. Do I also have to update the routes file? If so, how do I choose which one to populate it with? Does that mean its in the controller? and needs an action?

    I also have though that it depends on which file is initially routed to, but like I said, I think I need to understand the difference between the two before I can begin to use the partials to my advantage.

  • chris Frisina
    chris Frisina about 11 years
    can you better differentiate between what you call layout file and rendered file
  • chris Frisina
    chris Frisina about 11 years
    can you give an example using yield/content_for that also could be accomplished using render, or a two different examples that explain why they are not the same?
  • Geoff
    Geoff about 11 years
    Assuming controller of :users and method of :new with no calls to render or layout in your controller the layout file is in app/views/layouts/application.html.erb and the render file is in app/views/users/new.html.erb.
  • chris Frisina
    chris Frisina about 11 years
    so it is not possible to use yield from other views?
  • Geoff
    Geoff about 11 years
    That is certainly not the intent, but as with most things in Rails you could probably find a way to do it if you were stubborn.
  • Ankit Dhingra
    Ankit Dhingra over 10 years
    Shouldn't the content_for in city/index.html be something like <%content_for :page_title do %> ?