Writing a helper method for page headers - ruby-on-rails

I am currently integrating twitter bootstrap.
My application layout currently includes my flash messages right above the yield:
<div class="container">
<%= render 'layouts/header' %>
<div class="content" role="main">
<%= render :partial => 'shared/flash', :object => flash %>
<%= yield %>
</div>
<%= render 'layouts/footer' %>
</div> <!--! end of #container -->
However, I am also using the bootstrap Page Headers in my individual views
<div class="page-header">
<h1>Sign In <small>through one of these services:</small></h1>
</div>
I would like my flash messages to be below these page headers when page headers are set. So I'm thinking the best way to do this is to create a helper method and edit my application layout to be something like:
<%= render 'layouts/header' %>
<div class="content" role="main">
<%= pageHeader %>
<%= render :partial => 'shared/flash', :object => flash %>
<%= yield %>
</div>
How would I go about writing the helper for this. Would the best way to just have instance variables for #page_header and #page_header_small in my controller? Or is there a better rails way to handle this situation?

You can user content_for combined with yield.
In your layout you can put this block with headline above flash message
<%= yield :page_header %>
<%= render :partial => 'shared/flash', :object => flash %>
<%= yield %>
and in your template for action
<% content_for :page_header do %>
<div class="page-header">
<h1>Sign In <small>through one of these services:</small></h1>
</div>
<% end %>
Check it out at Ruby Guides

Related

Rails yield and content_for wieird behaviour, `yield :filter` only work if placed after default yield

Lets say i have this partial i am trying to render
#layouts/_subheader.html.erb
<div class="subheader">
<%= yield %>
<%= yield :filters %>
</div>
when i use this partial in a view like this
<%= render 'layouts/sub_header' do %>
<h2> Content For Yield </h2>
<% content_for :filters do %>
<h2> Content for Filters </h2>
<% end %>
<% end %>
i am getting the HTML output as
<div class="subheader">
<h2> Content For Yield </h2>
<h2> Content for Filters </h2>
</div>
this works as expected, but the problem arises when i change the order of the yield tags in the partial
instead of the above, if i rewrite the partial as
#layouts/_subheader.html.erb
<div class="subheader">
<%= yield :filters %>
<%= yield %>
</div>
i am getting output as
<div class="subheader">
<h2> Content For Yield </h2>
</div>
the content_for :filters is not being rendered.
what an i doing wrong here ? is this the correct behavior or am i doing something wrong ?
what should i do if i have to make the content of the yield :filters appear before the plain yield
EDIT:-
I have tried
#layouts/_subheader.html.erb
<div class="subheader">
<%= content_for :filters %>
<%= yield %>
</div>
but it seems to be not working as well.
Thanks everyone on reddit and #Ezhil i found a solution, this is what i did
what i did is i placed the content_for capture group before the render like this
#index.html.erb
<% content_for :filters do %>
<h2> Content for Filters </h2>
<% end %>
<%= render 'layouts/sub_header' do %>
<h2> Content For Yield </h2>
<% end %>
and in my partial
#layouts/_subheader.html.erb
<div class="subheader">
<%= content_for :filters %>
<%= yield %>
</div>
It's because the block isn't executed until the first yield, so there's no content captured until that runs.

Rails 4 - Multiple yield blocks on a partial

Is it possible to have a partial using more than one yield block? I wanted to use it to implement bootstrap modal boxes on my project, kinda like this:
<div class="modal fade" role="dialog" aria-labelledby="myModalLabel">
<div class="modal-dialog modal-lg" role="document">
<div class="modal-content">
<div class="modal-header">
<%= yield :header %>
</div>
<div class="modal-body">
<%= yield :body %>
</div>
<div class="modal-footer">
<%= yield :footer %>
</div>
</div>
</div>
</div>
And this is more or less how I was thinking of using it
<%= render partial: "shared/modal" do %>
<% content_for :header do %>
...
<% end %> %>
<% content_for :body do %>
...
<% end %> %>
<% content_for :footer do %>
...
<% end %> %>
<% end %>
Is there a way to do this? Is this maybe a bad approach for some reason?
Through much trial and error, I think I solved this in Rails 5 but needed to insert a blank yield in my partial in order to get it to work:
_partial.html.erb
<div class="partial">
<%= yield %> <!--Does not do anything-->
<div class="header">
<%= yield :header %>
</div>
<div class="text">
<%= yield :text %>
</div>
</div>
Implemented as:
full_layout.html.erb
<%= render "partial" do %>
<% content_for :header do %>
<h1>Header content</h1>
<% end %>
<% content_for :text do %>
<p>Text content</p>
<% end %>
<% end %>
I think you have an issue with your render partial. Notice you have all of your content_for blocks within the render partial block.
<%= content_for :thing do %>
Some content
<% end %>
<%= render partial: "blah" %>
It's no problem to use multiple yield blocks in your partial. Only thing is to make sure that many is actually needed. For an example content_for sections are basically placeholders for content that could vary based on the logic of the application. So, it's totally fine to use multiple yields in one page.
You can also just run put an yield there withouth the output. This way you can also use the default block.
<div>
<% yield %>
<div class="mt-3">
<div class="text-2xl tracking-wide font-bold text-gray-900">
heading
<%= yield :heading %>
</div>
</div>
<div class="relative bg-white rounded-xl shadow-xl mb-8 min-h-28">
<%= yield %>
</div>
...

Partial with multiple yields in rails

I'm looking for solution to have partial with multiple yields.
In real example I have this views structure:
Basic application.erb (/views/layouts/application.erb):
<!DOCTYPE html>
<head>
<title>Some title</title>
</head>
<body>
<div class="page">
<%= yield %>
</div>
</body>
</html>
Some partial to DRY my code (/views/shared/content.erb):
<div class="content">
<div class="sidebar">
<%= yield :sidebar %>
</div>
<div class="main">
<%= yield %>
</div>
</div>
And controller view (/views/home/index.erb):
<%= render :partial => 'layouts/header' %>
<%= render :partial => 'shared/navigation' %>
<% # It is close to what I want to do %>
<%= render :layout => 'shared/content' do %>
<% content_for :sidebar do %>
<%# This is will go to application.erb, not in content.erb %>
<%= render :partial => 'shared/menu' %>
<% end %>
<%= yield %>
<% end %>
<%= render :partial => 'layouts/footer' %>
So the main issue here is to have a template block with multiple yield areas and ability to pass custom html or render another partial.
This question is old, however, it's still relevant when I was searching for an answer on Google.
I've come up with a solution, while still not beautiful, works very well. The idea uses Rails' capture method, which takes a block and stores its contents into a variable:
controller.html.erb
<%= render 'shared/partial', body: capture { %>
My body content
<% }, footer: capture { %>
My footer content
<% } %>
shared/_partial.html.erb
<div id="body"><%= body %></div>
<div id="footer"><%= footer %></div>
Hope this helps someone!
In my case I've found solution like this.
On my controller view (/views/home/index.erb):
<% sidebar_content = render :partial => 'shared/slider' %>
<%= render :layout => 'shared/content', :locals => {:sidebar => sidebar_content} do %>
<%= yield %>
<% end %>
The partial with multiple areas (/views/shared/content.erb):
<div class="content">
<div class="sidebar">
<%= sidebar %>
</div>
<div class="main">
<%= yield %>
</div>
</div>
This solution doesn't look pretty, but it works. I hope to find something better in near future.
Here is my solution:
/views/shared/_content.erb
<div class="content">
<div class="sidebar">
<%= yield :sidebar %>
</div>
<div class="main">
<%= yield %>
</div>
</div>
views/home/index.erb
<%= my_content_tag do %>
<% content_for :sidebar do %>
<%= render :partial => 'shared/menu' %>
<% end %>
<%= yield %>
<% end %>
app/helpers/my_tags_helper.rb
module MyTagsHelper
def my_content_tag(&block)
sidebar_backup = #view_flow.content.delete(:sidebar)
x = capture(&block)
html = render('shared/content') { x }
#view_flow.content[:sidebar] = sidebar_backup if sidebar_backup
html
end
end
The key is using capture to extract content_for block and pass it into #view_flow

AJAX call not rendering my partial rails 3

I am trying to get an Ajax call working in rails, not quite sure what im doing wrong
So in my index I have a form that calls an api then returns the result to the results path. so what i want to do is to get the results rendered on the index page
What i have so far is
Controller
def index
end
def results
results = contact_search(params[:search])
#results = results
end
Index
<div class="container">
<div class="row">
<div class="span6 offset3">
<h2>Search for a contact</h2>
<%= form_tag results_path, :method => "get", :remote => true do %>
<%= text_field_tag 'search', nil, :placeholder => "Enter Email Address here...." %>
<%= submit_tag 'Search' , :id => "submitForm" %>
<% end %>
</div>
</div>
</div>
<div class="container">
<div class="row">
<div class="span6 offset3">
<div class="cResults">
</div>
</div>
</div>
</div>
Partial _contactResults.html.erb
<h1>The Results</h1>
<%= #results["contactInfo"]["familyName"] %><br>
<img src= <%= #results["photos"].first["url"] %> />
Index.js.erb
$('.cResults').html("<%= escape_javascript(render partial: 'contactResults') %>");
Am i missing anything?
Your javascript file should be named as the action that "computed" the results:
# in results.js.erb, not index.js.erb
$('.cResults').html("<%= escape_javascript(render partial: 'contactResults') %>");
If you need to execute Javascript for a controller's action, you can name the file as the action, with .js.erb instead of common .html.erb. This file will be executed when the controller receive a request for this action, interpreted as JS.

Passing markup into a Rails Partial

Is there any way of doing something equivilant to this:
<%= render partial: 'shared/outer' do %>
<%= render partial: 'shared/inner' %>
<% end %>
Resulting in
<div class="outer">
<div class="inner">
</div>
</div>
Obviously there would need to be a way of marking up 'shared/outer.html.erb' to indicate where the passed in partial should be rendered:
<div class="outer">
<% render Here %>
</div>
In my specific case I have a generic page header, consisting of a header and subheader, that is shared across all pages, but would like the option of passing in page-specific markup to that header to be rendered below the title and subtitle.
I'd use content_for :
<% content_for :subheader do %>
<%= render partial: 'shared/inner' do %>
<% end %>
<%= render partial: 'shared/outer' %>
Then in shared/outer :
<div class="outer">
<%= yield(:subheader) %>
</div>
You can put whatever you'd like in the content_for block and use it as many times as you'd like, just change the key name (here subheader)

Resources