Ruby on rails: Yielding specific views in a specific places in the layout
Look into ActionView::Helpers::CaptureHelper. You can do something like this in your views:
<% content_for :sidebar do %>
<!-- sidebar content specific to this page -->
<% end %>
This will run the template inside the content_for block, but will not output as part of the regular template yield
buffer, it will be stored in a separate buffer for later. Then later on, including in the layout, you can use yield :content_name
to output the content:
<div class="content">
<%= yield %>
</div>
<div class="sidebar">
<%= yield :sidebar %>
</div>
So in a sense you can have different yield
s for different views, you just have to give the differing content a name with content_for
in the views, and yield it with that same name in the layout.
Consider your case, where you want different views in different places. Let's say you have three panels, panel1, panel2, and panel3. You can do this in your layout:
<div id="panel1"><%= yield :panel1 %></div>
<div id="panel2"><%= yield :panel2 %></div>
<div id="panel3"><%= yield :panel3 %></div>
You don't even need to include a plain <%= yield %>
if you don't want to. Then in your views, you can choose which panel to display the content in by surrounding the entire view with the appropriate content_for
. For example, one of your views might be changed like this:
<% content_for :panel2 do %>
<!-- Your View -->
<% end %>
To show in panel 2. Another one might be intended for panel 3, like this:
<% content_for :panel3 do %>
<!-- Your View -->
<% end %>
Rails: Using Yield, Calling Multiple View Pages
You should, as @cdesrosiers said, rename the index.html.erb
file in good_posts
to _index.html.erb
. Then you can render this view in your application like this:
<div class='span10'>
<%= render 'good_posts/index' %>
<%= yield :good_post %>
</div>
<div class='span10'>
<%= yield %>
</div>
Personally, I would change the index.html.erb
file in good_posts
folder to _good_posts.html.erb
file in app/views/posts
folder. Your code will have better meaning, and you can know where to find it after, because it relates to posts
. So, if you change this, use this code:
<div class='span10'>
<%= render 'posts/good_posts' %=
<%= yield :good_post %>
</div>
<div class='span10'>
<%= yield %>
</div>
Another you should change is content_for :good_post
-> content_for :good_posts
, because good posts maybe have many posts, so you should use post in pluralize.
How does the yield magic work in ActionView?
This little tiny method called execute
in ActionView::Base
explains it all.
http://google.com/codesearch/p?hl=en#m8Vht-lU3vE/vendor/rails/actionpack/lib/action_view/base.rb&q=capture_helper.rb&d=5&l=337
def execute(template)
send(template.method, template.locals) do |*names|
instance_variable_get "@content_for_#{names.first || 'layout'}"
end
end
The do |*names|... end
block is the one receiving the yield
. You'll notice that the @content_for_#{names.first}
matches up with the variable being set in the content_for
process.
It's called from AV::TemplateHandlers::Compilable in #render, and I would assume other places as well.
def render(template)
@view.send :execute, template
end
http://google.com/codesearch/p?hl=en#m8Vht-lU3vE/vendor/rails/actionpack/lib/action_view/template_handlers/compilable.rb&q=execute&exact_package=git://github.com/payalgupta/todo-list.git&sa=N&cd=17&ct=rc&l=28
how do I link a layout to a view page on Ruby on Rails
There are many ways layout can be used. If you want to call a specific layout for a given action, you should do that in your controller, not in your view. If you need to call in a view, to give a layout for a partial, then the syntax is different, you call the partial first and then the layout.
<%= render partial: "comments", layout: "two_column_landing" %>
If you just want your 2 column view to render in a particular controller then at the top of the controller before any method definitions call, under the class name
class ArticlesController < ApplicationController
layout "two_column_landing"
end
If you want to only call this layout for a specific action in the controller you can do it in the method render
def index
@people = Person.all
render layout: "multi-column"
end
You may refer to this question here for more details.
If you want to remove layout from all action in a controller, add layout false
after the class name.
class ArticlesController < ApplicationController
layout false
end
or if you can also specify for each action
def login
...
render layout: false
end
Link to documentation
Using multiple yields to insert content
So, when you go to the index
page you will get the piece of html that will be placed in the main layout, and this piece of html look like this:
<div class="container">
<%= render 'admins/menu' %>
<%= yield :admin %>
</div>
This code will yield :admin
properly.
When you go to the test
page you do not have this html code anymore (since it only belongs to the index
method). So, anything you put in the content_for(:admin)
block will be ignored since no-one is printing it.
What you probably want to do is creating a shared layout for all your admin pages. Follow this guide and you'll have your solution.
Solution
Edit the application.html.erb
layout using this:
<%= content_for?(:content) ? yield(:content) : yield %>
instead of
<%= yield %>
Then create an admins.html.erb
file inside the layouts
folder to handle your admin pages' layout. Something like this:
<% content_for :content do %>
<div class="container">
<%= render 'admins/menu' %>
<%= yield %>
</div>
<% end %>
<%= render template: "layouts/application" %>
Will do fine. Then in the index.html.erb
and test.html.erb
just place regular HTML content, without using the content_for(:admin)
block. Everything should work fine and you'll have your custom admin template, with a slightly different look from regular pages.
Possible to create a wrapping partial?
The information is kind of hard to find, but this is covered in the "Rendering partials with layouts" section of the partials documentation. Basically when you do render partial: ...
you can use the layout:
option to give the name of the "wrapper" layout. The partial will be rendered within the wrapper wherever you put <%= yield %>
.
Related Topics
Routing Error - Uninitialized Constant
How to Handle Multiple Models in One Rails Form
How to Run Ruby 2.0 with Jruby 1.7
Find Memory Leak in a Ruby on Rails Project
Why Is This Permissions Error Occurring with Mod_Passenger.So
Ruby on Rails - Devise Users/Sign_Out Not Working
Why I Can Not Call Super in Define_Method with Overloading Method
How to Make a Gemset in Rvm the Default
Unable to Load Gem Cocoa Pods While Creating Repo
Sinatra - Response.Set_Cookie Doesn't Work
How to Remove Repeated Spaces in a String
Use Global or Constant Variable in Ruby/Rails
How to Make Rake Tasks Run Under My Sinantra App/Environment