How Do I "Extend" a view in Rails - ruby-on-rails

So I'm working on an open source project and due to different versions, there's the issue where I can't count on there being a controller for a view. Instead this email would be send out via a rake task for one version and a few others would done via a controller. Now you understand why I'm asking a bad practice question...
I have a layout for a view. Does anyone know a way to specify what the layout is for the view within the view. Some pseudo-code:
<%= extends 'layout/test_mailer` %>
<h1> Hey there! </h1>
And the layout would have the usual yield within it.
I hope I'm explaining the problem good enough.

<%= render partial: "hey_page", layout: "layout/test_mailer" %>
Check part 3.4.3 Partial Layouts at RailsGuides.

I think using yield and content_for should solve the problem. [Guides]
# my_layout.html.erb
<%= yield :mail_view %>
# my_mail_view.html.erb
<%= content_for :mail_view do %>
<!-- html -->
<% end %>
Of-course, if you are using params to get the layout, this would be a wrong answer.
Then, you can also use:
<%= render partial: "link_area", layout: "graybar" %>

You can use
//controller action
def index
render layout: test_mailer
end
//view, index.html.erb
<h1> Hey there! </h1>
//view, layout/test_mail.html.erb
<html>....layout for you test mail
<% yield %>
</html>

Related

DRY view for sidebar

In my quest to keep my application views as DRY as possible I've encountered a little snag. My appliation.html.erb incorporates a static sidebar menu. Each of my main controllers incorporates a secondary sidebar menu (essentially a submenu). I can take the code that renders the menu out of application.html.erb and put it in each of my views and change the secondary sidebar there, but this produces a lot repetition in my views.
I saw this SO post and looked at this page, but I was unable to get either idea to work. I was thinking that I could put something like:
<% provide(:submenu, 'layouts/sidebars/sidebar_customers_contacts') %>
at the top of each view and use that to render the associated partial by doing
<% content_for(:submenu) do %>
<%= render :partial => :submenu %>
<% end %>
from the application.html.erb but of course that didn't work.
This is my current application.html.erb:
<div class="side">
<%= render 'layouts/sidebar' %>
<%= render 'layouts/sidebars/sidebar_dashboard' %><!-- this needs to load a sidebar based on the controller that calls it. Each view of the controller will get the same sidebar. -->
</div>
<div class="main-content">
<%= yield %>
</div>
I feel like I'm making this more difficult than it really is. Is there a simple way to do this?
Rails provides a helper called controller_name which you can read more about here.
Assuming you adhere to your own naming conventions, this should work as-is. If you decide some controllers don't get a sidebar, you may need to throw in some conditionals...
application.html.erb
<div class="side">
<%= render "layouts/sidebar" %>
<%= render "layouts/sidebars/#{ controller_name }" %>
</div>
<div class="main-content">
<%= yield %>
</div>
EDIT
Sorry, my mistake was using single quotes instead of double-quotes. You cannot use #{string interpolation} within single quotes. Source

Default path to look for partial

In my app/views/conversations/index.html.erb, I am writing:
<%= render #conversations %>
hoping that it would find a partial named _conversation.html.erb inside the same directory, and use it to render each elements in #conversations. (The usual Rails way)
But I get a missing template error: Missing partial mailboxer/conversations/_conversation.
I am using a Mailboxer gem, and there were no documentations for this. I know I could render a partial explicitly by <%= render partial: 'conversation', locals: { conversations: #conversations } %>.
Yet still, I would like to know why my app is looking for a partial for #conversations in mailboxer/conversations/, not conversations/, and if there is a way to change this behavior.
More information
<% #conversations.each do |conversation| %>
<%= div_for conversation %>
<% end %>
produces HTML:
<div class="mailboxer_conversation" id="mailboxer_conversation_16"> ... </div>
<div class="mailboxer_conversation" id="mailboxer_conversation_17"> ... </div>
....
Perhaps the mailboxer_ in front of conversation has something to do with this situation also?
This happens because, in later versions of Mailboxer, models are namespaced under Mailboxer. (e.g. Mailboxer::Conversation, Mailboxer::Message.)
I commented on the GitHub issue also.
You could try providing the full path to the partial, e.g.
<%= render :partial => "yourfoldername/conversation", collection: #conversations %>

Application.html.erb template inheritance

I have a situation in rails (version 4.04, ruby version 2.1) where I've been using the standard application.html.erb to define the main framework for my site, header, footer, nav bar, etc. When I got to an inner div, call it, inner-content, thats where I put a <% yield %> statement so that the sub template can take over and place its content in the correct place (for example products#show or products#index have show.html.erb and index.html.erb respectively which just the content for those actions).
The problem is I realized I was duplicated some code in those sub templates. In ever one of them (except one) I always was starting off like this:
<div class="columns large-6 medium-6 center-small">
<div class="inner_wrapper">
And I was always ending like this:
</div>
</div>
So I was thinking, I shouldn't be repeating all this code. I should move this into application.html.erb so that every template automatically gets the inner-content set up correctly.
The problem is that one action I was talking about. There is one action that has a different setup. I don't want to have to type in those extra 2 divs for every sub-layout except one. Is there a better way to do this?
One way could be to check which controller your currently using this in your application.html.erb
<% if params[:controller] == "controller name" %>
<div>
<%= yield %>
</div>
<% else %>
<div class="different div">
<%= yield %>
</div>
<% end %>
Not sure if this the best way, but its one way to do it.
Create a different layout file and call it maybe products_layout.html.erb.
Then in the controller
class ProductsController < ApplicationController
layout: 'products_layout'
....
end
Or do it on a per action
def show
render 'show', layout: 'products_layout'
end
http://guides.rubyonrails.org/layouts_and_rendering.html

Rails 4: Nested Layouts?

I have a main layout (application) and two 'sub' layouts (dashboard and admin). In my dashboard and admin controllers respectively I have a before_filter which render templates: the template I want (either dashboard or admin).
In my dashboard and admin layouts, I am doing something along the lines of:
<% content_for :top_menu do %>
<%= render partial: "layouts/menu/top", locals: {section: 'admin'} %>
<%= render partial: "layouts/menu/sub", locals: {section: 'admin'} %>
<% end %>
So this is including the top partials with a section local which shows the correct options I want.
In my application layout, I have the following:
SOME HTML HERE
<%= yield :top_menu %>
SOME HTML HERE
<%= yield %>
SOME HTML HERE
The problem is that the content from my views isn't being displayed, I'd expect it to be displayed where the 'yield' is in my application layout.
I have read: http://guides.rubyonrails.org/layouts_and_rendering.html#using-nested-layouts - but following that just displays the menus twice and still doesn't display my content.
I think I am failing to understand something here, help would be appreciated.
In short, I want top menus and it's in the controller that I want to specify which menu is to be used. I'm sure there is a better solution to this that I am missing also.
I have fixed this by doing:
layout 'menu/admin'
In my controller, and adding:
<%= render template: "layouts/application" %>
To my layouts.

how to extend child template to parent in rails

I am new to rails. I am having difficulty in understanding template inheritance. Earlier I have worked in django and seen template inheritence there. There I saw child is told about parent using "extends" command. Can anyone explain how it works here. I have gone through guidelines of ruby but it was not clear.
Thanks
It's quite simple to do in Rails.
You simply tell the template you are currently rendering to render another template.
For example layouts/application.html.erb contains something like this:
<% content_for :navigation do %>
<nav>...</nav>
<% end %>
<% content_for :content do %>
<%= yield %>
<% end %>
<%= render :template => 'layouts/main_application' %>
The important part is the render :template part that then delegates this template to also render the layouts/main_application.html.erb that in my case looks something like this:
<header>
...
</header>
<body>
<%= yield :nav %>
<%= content_for?(:content) ? yield(:content) : yield %>
</body>
What I am doing here is having a main template that does not contain the navigation (for things like login etc) and the application.html.erb adds that navigation to the :nav content placeholder.

Resources