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 bbb
s _content.html/erb :
<p>Content from bbb.</p>
BUT this does NOT:
aaa
's index.html.erb :
<div">
<%= yield :container %>
</div>
and bbb
s _content.html/erb :
<% content_for :container do %>
<p>Content from bbb.</p> ### viewed in aaa
<% end>
and ccc
s _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.
They are opposite ends of the rendering process, with yield specifying where content goes, and content_for specifying what the actual content is.
It tells Rails to put your view content to this block (which is called by yield ) at that place in the layout file.
Rendering is the ultimate goal of your Ruby on Rails application. You render a view, usually . html. erb files, which contain a mix of HMTL & Ruby code. A view is what the user sees.
There is an important difference between render and redirect_to: render will tell Rails what view it should use (with the same parameters you may have already sent) but redirect_to sends a new request to the browser.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With