How to prevent style duplication in Rails HTML emails? - ruby-on-rails-3

I am trying to build rails HTML emails, but the structure (header and footer) of the emails is duplicated in each one. Typically it's not a problem, but with the inline styles as well, it seems like it can be an issue if I want to change the color. How can I pull these elements out of each file and into one?
Also, is there anyway to eliminate the duplication of text between the html.erb and text.erb files.

A simple way to do it is to reference a couple of partials. Let's say they're named something like this:
_email_header.html.erb
_email_footer.html.erb
Then you can refer to them inside each of your emails:
<%= render :partial => 'email_header' %>
Blah, email-specific content here...
<%= render :partial => 'email_footer' %>
That will work, but will still lead to a bunch of copy-paste, albeit less than the original version with the full structure inlined. A cleaner way to manage this is to set up a custom layout for these emails.
The "Layout and Rendering" Rails Guide and the layouts section of the "Action Mailer" Rails Guide are helpful backgrounders for this, if you haven't done this before.
You will see from those references that there are multiple ways to invoke a layout within Action Mailer (and more ways still, outside of a mail context), but to take one example usage, you can create a layout template file here: app/views/layouts/{your_mailer_name}.html.erb. E.g., "user_mailer.html.erb"
Its contents could look something like this:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>My Fancy Email</title>
</head>
<body>
<%= render :partial => 'email_header' %>
<%= yield %>
<%= render :partial => 'email_footer' %>
</body>
</html>
Note the yield call, that's where your specific email content will render.
This approach keeps your content "DRY".

Related

How to integrate custom meta tags with Rails 5 + webpacker + Vue.js

Just like in title: What is the proper way to integrate SEO stuff like Facebook OpenGraph tags in apps that use rails backend API (installed with webpacker) with a framework like Vue?
This is how part of my config/routes.rb looks like:
namespace :api, defaults: { format: :json } do
namespace :v1 do
resources :posts, only: [:index, :show]
end
end
get '/', to: 'front#index', format: false
get '/*path', to: 'front#index', format: false
For now app is designed in the way, where all requests on front-end part are handled by vue-router.
My layouts/application.html looks almost, like on the attached snippet:
<html>
<head>
<%= javascript_pack_tag 'front' %>
<%= stylesheet_pack_tag 'front' %>
</head>
<body>
<div id="app">
<%= yield %>
</div>
</body>
</html>
My question is, what is the proper way to manage stuff like Facebook Open Graph when there is no straight forward access to <head> section?
I can't use fairly default rails stuff like content_for because everything happens inside script.
Or maybe am I wrong? Missing something fancy, important here?
It would be grateful to get any advice, thanks.

How to avoid newlines being added by HAML ruby block evaluation

I'm using the content_for helper to e.g. set a page title in my rails 3 app. One snippet of erb I'm still using in some places is
<title><%= yield(:title) -></title>
or written in HAML would be
%title= yield(:title)
Now I have a HAML template setting this title:
- content_for :title do
My awesome title
- content_for :something_else do
which results in
<title>My awesome title
</title>
How can I avoid the newline before </title>? It's definitely set in :title – adding +"X" will put the X behind the newline.
I already tried
-< content_for :title do
-> content_for :title do
but either one leads to an error. Whitespace removal seems to be not working with ruby evaluation.
In your layout template, do:
%title= content_for?(:title) ? "#{yield(:title)}" : "Default Title"
Then in your content templates, do:
= content_for(:title, "Welcome to my home page!")

Title not displaying correctly

I have set up a title instance variable in application_helper.rb, but the base_title does not display in the browser. Can you tell me what's wrong?
application_helper.rb
module ApplicationHelper
# Return a title on a per-page basis
def title
base_title = "Ruby on Rails Tutorial Sample App"
if #title.nil?
base_title
else
"#{base_title} | #{#title}"
end
end
end
application.html.erb
<!DOCTYPE html>
<html>
<head>
<title><%= #title %></title>
<%= csrf_meta_tag %>
</head>
<body>
<%= yield %>
</body>
</html>
In the view you're not actually calling the helper function, it's just trying to output the instance variable (#title), don't prefix a function call with #:
<title><%= title %></title>

Rendering layouts/partials includes HTML tags in text after transitioning from Rails 3.0.x to 3.1

I'm trying to transition an application from 3.0.7 to 3.1. I've moved around the assets to the app/assets directory and I thought that I have everything configured correctly.
My problem is that the layout file won't correctly render partials and other layout files. If all I have inside my layout is <%= yield %> then it correctly renders the view files.
But if I try to render another layout file inside layouts/omega/application.html.erb like:
<%= render "layouts/omega/head" %>
<%= yield %>
Then it dumps the html onto the page with all of the elements and html tags included in the text:
<div id="top-pane"> <div class="center-content">.....
"Some text that was correctly displayed from the view file that was called through yield"
If I try to render another file, say in home/index.html.erb:
<p> this is home/index </p>
<%= render 'omega/test' %>
Then the output will be:
"this is home/index
<p> this is a test layout </p> "
Where again, the text from home/index is outputted correctly, but the rendered partial still includes the html elements. What's changed in 3.1 that's making this happen?
(By the way, I'm working inside a Rails Engine, which is why I have everything namespaced with omega)

How to include code in only one controller action?

I have only a single page that requires jquery ui in my entire application. How can conditionally include the javascript files in that single page?
I believe in Rails 2 I could use: (in application.html.erb)
<%- if controller.controller_name == "posts" && controller.controller_action == "new" -%>
<%= stylesheet_link_tag 'jquery-ui-1.8.13.custom.css' %>
<%= javascript_include_tag 'jquery-ui-1.8.13.custom.min.js', 'autocomplete-rails.js' %>
<%- end -%>
But controller.controller_action throws an undefined method error. And after looking at the API, it looks like it's been removed?
Maybe it would be best to remove the conditional from application.html.erb altogether and just put it at the top of posts/new.html.erb ?
I would avoid delegating responsibility for this to your application layout. If you don't need jQuery UI on more than a single view, you are best off letting the view handle that. The following let's you do just that while still keeping your output HTML clean and sensible (ie. not putting JS all over the place willy nilly).
In your layout (application.html.erb):
<head>
<title>Foo Bar</title>
<%= yield :page_specific_assets %>
</head>
In your view that requires jQuery UI (posts/new.html.erb):
<% content_for :page_specific_assets do %>
<%= stylesheet_link_tag 'jquery-ui-1.8.13.custom.css' %>
<%= javascript_include_tag 'jquery-ui-1.8.13.custom.min.js', 'autocomplete-rails.js' %>
<% end %>
Note: despite convention, putting unnecessary javascript in the <head> degrades performance.
I believe it's:
controller.action_name