ERB showing through in multipart e-mail using HAML and ActionMailer - ruby-on-rails-3

I'm trying to build a multipart e-mail using Rails 3 ActionMailer and HAML. I'm not sure if it's the naming convention or what the issue is, the HAML part of the view is being rendered correctly, but the plain text (with ERB) is not. I'm seeing actual ERB code in the plain text version of my outbound emails.
I have the following files defined:
app/views/layouts/email.html.haml
app/views/layouts/email.text.erb
app/views/user_mailer/password_reset_instructions.html.haml
app/views/user_mailer/password_reset_instructions.text.erb
My mailer looks like this:
class UserMailer < ActionMailer::Base
helper :application
helper :user_mailer
layout "email"
#layout "email"
# single method for either a password reset or initial account activation
def password_reset_instructions(user)
setup_email(user)
user.reload
subject = (user.confirmed? ? "Password Reset Instructions" : "New Account Information")
#user = user
#edit_password_reset_url = url_for( :controller => "password_resets",
:id => user.perishable_token,
:action => 'edit',
:host => "#{user.subdomain}.#{Assignr::HOST_NAME}")
#assignor_name = user.creator ? user.first_last_name : 'Your assignor'
#site = user.site
mail :to => #setup[:to], :from => #setup[:from], :subject => #setup[:subject] + subject
end
protected
def setup_email(user)
# send to one or both e-mail addresses
user.reload
recipients = []
recipients << user.first_last_name + " <" + user.email + ">" if user.email
recipients << user.first_last_name + " <" + user.email2 + ">" if user.email2
#recipients = recipients.join(", ")
#setup = {:to => #recipients, :from => email_address_for(user) , :subject => "assignr.com: "}
#user = user
end
def email_address_for(user)
"assignr.com <#{user.site_id}-#{user.id}#email.#{Assignr::HOST_NAME}>"
end
end
My ERB plain text version looks like this:
<% if #user.confirmed? -%>
A request to reset your password has been made.
If you did not make this request, simply ignore this email.
If you did make this request just click the link below:
<% else -%>
An account with assignr.com has been created for you by <%= #user.creator ? #user.creator.first_last_name : 'your assignor'%>.
assignr.com is a web-based service used to help referee and umpire assignors with game scheduling.
Please visit the following URL to begin:
<% end -%>
<%= #edit_password_reset_url %>
If the above URL does not work try copying and pasting it into your browser.
If you continue to have problem please feel free to contact us.
<% if !#user.confirmed? and #upcoming_game_count > 0 %>
<%= #user.creator ? #user.creator.first_last_name : 'Your assignor'%> has assigned you to <%= pluralize( #upcoming_game_count, 'game') %>, beginning <%= humanize_time(#next_game.date) %>. To view detailed information on these assignments, you will need to click the URL above and follow the on-screen instructions to register.
<% end %>
<%= render :partial => "footer"%>
The actual multipart delivered e-mail looks like this (note the ERB code in the generated email):
Delivered-To: <snip>
Received: by 10.216.163.14 with SMTP id z14cs47630wek;
Mon, 7 Feb 2011 06:21:54 -0800 (PST)
Received: by 10.142.141.16 with SMTP id o16mr4281923wfd.390.1297088513239;
Mon, 07 Feb 2011 06:21:53 -0800 (PST)
Return-Path: <snip>
Received: from assignr.com (email.assignr.com [0.0.0.0])
by mx.google.com with ESMTPS id g39si10275834yhd.193.2011.02.07.06.21.52
(version=TLSv1/SSLv3 cipher=RC4-MD5);
Mon, 07 Feb 2011 06:21:53 -0800 (PST)
Received-SPF: pass (google.com: domain of <snip> designates 0.0.0.0 as permitted sender) client-ip=0.0.0.0;
Authentication-Results: mx.google.com; spf=pass (google.com: domain of snip designates 0.0.0.0 as permitted sender) smtp.mail=snip
Received-SPF: pass (assignr.com: domain of snip designates 127.0.0.1 as permitted sender) receiver=assignr.com; client-ip=127.0.0.1; helo=localhost.localdomain; envelope-from=snip; x-software=spfmilter 0.97 http://www.acme.com/software/spfmilter/ with libspf2-1.0.0;
Received: from localhost.localdomain (localhost.localdomain [127.0.0.1])
by assignr.com (8.14.4/8.14.3) with ESMTP id p17ELhYP013916
for <snip>; Mon, 7 Feb 2011 09:21:43 -0500
Date: Mon, 07 Feb 2011 09:21:43 -0500
From: "assignr.com" <snip>
To: Jeff Wigal <snip>
Message-ID: <4d4ffff7d072_362b55b3bbe40347#assignr.com.mail>
Subject: assignr.com: Password Reset Instructions
Mime-Version: 1.0
Content-Type: multipart/alternative;
boundary="--==_mimepart_4d4ffff6d6fb6_362b55b3bbe4000";
charset=UTF-8
Content-Transfer-Encoding: 7bit
----==_mimepart_4d4ffff6d6fb6_362b55b3bbe4000
Date: Mon, 07 Feb 2011 09:21:43 -0500
Mime-Version: 1.0
Content-Type: text/plain;
charset=UTF-8
Content-Transfer-Encoding: 7bit
Content-ID: <4d4ffff78acc_362b55b3bbe40119#assignr.com.mail>
<% if #user.confirmed? -%>
A request to reset your password has been made.
If you did not make this request, simply ignore this email.
If you did make this request just click the link below:
<% else -%>
An account with assignr.com has been created for you by <%= #user.creator ? #user.creator.first_last_name : 'your assignor'%>.
assignr.com is a web-based service used to help referee and umpire assignors with game scheduling.
Please visit the following URL to begin:
<% end -%>
<%= #edit_password_reset_url %>
If the above URL does not work try copying and pasting it into your browser.
If you continue to have problem please feel free to contact us.
<% if !#user.confirmed? and #upcoming_game_count > 0 %>
<%= #user.creator ? #user.creator.first_last_name : 'Your assignor'%> has assigned you to <%= pluralize( #upcoming_game_count, 'game') %>, beginning <%= humanize_time(#next_game.date) %>. To view detailed information on these assignments, you will need to click the URL above and follow the on-screen instructions to register.
<% end %>
<%= render :partial => "footer"%>
CIM Test Site
=======================================
assignr.com
Referee and Umpire Assigning Made Easy
----==_mimepart_4d4ffff6d6fb6_362b55b3bbe4000
Date: Mon, 07 Feb 2011 09:21:43 -0500
Mime-Version: 1.0
Content-Type: text/html;
charset=UTF-8
Content-Transfer-Encoding: 7bit
Content-ID: <4d4ffff7b0aa_362b55b3bbe4023d#assignr.com.mail>
<html>
<body>
<style media='screen' type='text/css'>
a { color: #39B2E5; font-weight: bold; }
a:hover { color: #0a97d2; }
p, ul { font: 13px 'Lucida Grande', Lucida Grande, Helvetica, Arial, sans-serif; line-height: 18px; color: #56594c; }
h2 { font: 18px 'Lucida Grande', Lucida Grande, Helvetica, Arial, sans-serif; line-height: 18px; font-weight: bold; color: #56594c; }
h3 { font: 14px 'Lucida Grande', Lucida Grande, Helvetica, Arial, sans-serif; line-height: 14px; font-weight: bold; color: #56594c; }
.clearfix:after { content: "."; display: block; height: 0; clear: both; visibility: hidden; }
.clearfix { display: inline-block; }
</style>
<div style='padding: 10px; background-color:#ececdf;'>
<table style='margin-bottom: 10px;' width='100%'>
<tr>
<td align='center'>
<img alt='assignr.com' height='50' src='http://assignr.com/images/assignr_com_logo_50.png' width='136'>
</td>
</tr>
</table>
<table style='background: #fff;padding: 20px 10px 10px 10px;border-bottom: 1px solid #e5e7e0;' width='100%'>
<tr width='100%'>
<td style='background:#617494;height: 10px;'> </td>
</tr>
<tr width='100%'>
<td style=' padding: 20px 0px'>
<h2>
Hi
Jeff,
</h2>
<div style="width: 100%; font: 13px 'Lucida Grande', Lucida Grande, Helvetica, Arial, sans-serif; padding-right: 10px; color: #56594c;">
.. assume valid HTML goes here.
<p>
Follow
<a href='http://twitter.com/assignr'>assignr.com on Twitter</a>
<br>
Keep up with the latest news
<a href='http://dropkickstudios.com?utm_source=outbound-email'>on our blog</a>
<br>
Share your
<a href='http://assignr.zendesk.com/forums?utm_source=outbound-email'>questions and feedback</a>
<br>
View
<a href='http://twitter.com/assignr'>assignr.com system status</a>
</p>
</td>
</tr>
<tr width='100%'>
<td style='background:#617494;height: 10px;'> </td>
</tr>
<tr width='100%'>
<td>
<p style='font-size: 11px; color: #b7b9ad; padding-top: 10px; border-top: 1px solid #f5f7f0; '>
Want to modify your assignr.com email address? Visit your
<a href='https://assignr.com/login?utm_source=outbound-email' style='font-weight: normal;'>settings</a>
page.
<br>
assignr.com is a trademark of Dropkick Studios, LLC, all rights reserved.
</p>
</td>
</tr>
</table>
</div>
</body>
</html>
----==_mimepart_4d4ffff6d6fb6_362b55b3bbe4000--
What am I missing?
EDIT: Not sure what I did, but it seems to be working now... updated to latest version of Haml but I'm not sure that was the problem.

Related

Page number in asp.net core footer (partial view)

I am using jsreport with my Asp.Net Core MVC project. It is working all right except for page numbers.
I am using a partial view for footer.
Here is the partial view:
<table style="font-size: 10px; padding-bottom: 5px; padding-top: 0in; padding-left: 0.25in; padding-right: 0.25in;">
<tbody>
<tr>
<td style="width: 1.5in; text-align: left;"><b>#($"{DateTime.Now}")</b></td>
<td style="width: 8.2in; text-align: center;">Brand Name</td>
<td style="width: 1.5in; text-align: right;">Page <span class="pageNumber"></span> of <span class="totalPages"></span></td>
</tr>
</tbody>
</table>
Unfortunately, the page number part is not working at all. I just see "Page of " in the rendered PDF.
I am using the Chrome-PDF recipe and do not wish to use pdf-utils for the footer.
Even if I put the following line in the main report body view, I still do not get any page numbers.
Page <span class="pageNumber"></span> of <span class="totalPages"></span>
Any help will be appreciated.
The header html needs to be passed to the Template.Chrome.HeaderTemplate property, you need to also enable header printing using Template.Chrome.DisplayHeaderFooter and also make a space for the header using margins.
Here is how the controller action can look like
[MiddlewareFilter(typeof(JsReportPipeline))]
public async Task<IActionResult> InvoiceWithHeader()
{
var header = await JsReportMVCService.RenderViewToStringAsync(HttpContext, RouteData, "Header", new { });
HttpContext.JsReportFeature()
.Recipe(Recipe.ChromePdf)
.Configure((r) => r.Template.Chrome = new Chrome {
HeaderTemplate = header,
DisplayHeaderFooter = true,
MarginTop = "1cm",
MarginLeft = "1cm",
MarginBottom = "1cm",
MarginRight = "1cm"
});
return View("Invoice", InvoiceModel.Example());
}
And how the Header view
<div style='text-align:center; font-size: 10px; width:100%'>Page number <span class="pageNumber"></span> of <span class="totalPages"></span></div>
You can find an example repository here
https://github.com/jsreport/jsreport-dotnet-example-webapp

Styling form error message - bootstrap/rails

The error messages for my rails form look terrible with bootstrap. Does anyone know a solution for better (nice looking) error messages? I use Rails and Bootstrap.
My form (it's a helper) is like this:
<%= form_for(#user) do |f| %>
<% if #user.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#user.errors.count, "error") %> prohibited this user from being saved:</h2>
<ul>
<% #user.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="form-inline">
<%= f.text_field :email, class:'input-large', placeholder:'Test' %>
<!-- </div>
<div class="actions"> -->
<%= f.submit class:'btn btn-large btn-success' %>
</div>
<% end %>
Take a look at how Michael Hartl does it in railstutorial.
And thats the used css:
#error_explanation {
color: #f00;
ul {
list-style: none;
margin: 0 0 18px 0;
}
}
.field_with_errors {
#extend .control-group;
#extend .error;
}
He describes everything here.
If you also want the little star at the beginning of every line you have to include it in your form:
<div id="error_explanation">
<h2><%= pluralize(#user.errors.count, "error") %> prohibited this user from being saved:</h2>
<ul>
<% #user.errors.full_messages.each do |msg| %>
<li> * <%= msg %></li> <--- insert here
<% end %>
</ul>
</div>
...
A little late I realize, but I just ran into this today with Rails 4 and Bootstrap 3, I ended up making a view helper to display errors using a panel:
Rails 4 / Bootstrap 3
def errors_for(object)
if object.errors.any?
content_tag(:div, class: "panel panel-danger") do
concat(content_tag(:div, class: "panel-heading") do
concat(content_tag(:h4, class: "panel-title") do
concat "#{pluralize(object.errors.count, "error")} prohibited this #{object.class.name.downcase} from being saved:"
end)
end)
concat(content_tag(:div, class: "panel-body") do
concat(content_tag(:ul) do
object.errors.full_messages.each do |msg|
concat content_tag(:li, msg)
end
end)
end)
end
end
end
Rails 4 / Bootstrap 4 Beta
def errors_for(object)
if object.errors.any?
content_tag(:div, class: "card border-danger") do
concat(content_tag(:div, class: "card-header bg-danger text-white") do
concat "#{pluralize(object.errors.count, "error")} prohibited this #{object.class.name.downcase} from being saved:"
end)
concat(content_tag(:div, class: "card-body") do
concat(content_tag(:ul, class: 'mb-0') do
object.errors.full_messages.each do |msg|
concat content_tag(:li, msg)
end
end)
end)
end
end
end
Rails 4 / Bootstrap 4 Beta List Group Variation
def errors_for(object)
if object.errors.any?
content_tag(:div, class: "card border-danger") do
concat(content_tag(:div, class: "card-header bg-danger text-white") do
concat "#{pluralize(object.errors.count, "error")} prohibited this #{object.class.name.downcase} from being saved:"
end)
concat(content_tag(:ul, class: 'mb-0 list-group list-group-flush') do
object.errors.full_messages.each do |msg|
concat content_tag(:li, msg, class: 'list-group-item')
end
end)
end
end
end
I dropped it in application_helper and call it in my form views
<%= errors_for(#user) %>
Maybe someone will stumble upon this and find it useful.
Just in case someone stumbles here and is using Bootstrap 4 alpha with rails 5 and bootstrap_form_for gem.
I use:
<div class="form-group">
<%= f.alert_message "Please fix the errors below." %>
</div>
which looks really nice.
I have implemented Rabbott's view helper in Rails 5 and Bootstrap 4:
def errors_for(object)
if object.errors.any?
content_tag(:div, class: 'card text-white bg-danger mb-3') do
concat(content_tag(:div, class: 'card-header') do
concat(content_tag(:h4) do
concat "#{pluralize(object.errors.count, 'error')} prohibited this #{object.class.name.downcase} from being saved:"
end)
end)
concat(content_tag(:div, class: 'card-body') do
concat(content_tag(:ul) do
object.errors.full_messages.each do |msg|
concat content_tag(:li, msg)
end
end)
end)
end
end
end
And it looks like this:
Bootstrap 4 Alpha 6
I copied the compiled Bootstrap CSS from
https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.6/css/bootstrap.css
Searched for .has-danger, copied all the classes, did a search & replace on .has-danger for .field_with_errors, and I also added .field_with_errors label
.field_with_errors label,
.field_with_errors .form-control-feedback,
.field_with_errors .form-control-label,
.field_with_errors .col-form-label,
.field_with_errors .form-check-label,
.field_with_errors .custom-control {
color: #d9534f;
}
.field_with_errors .form-control {
border-color: #d9534f;
}
.field_with_errors .input-group-addon {
color: #d9534f;
border-color: #d9534f;
background-color: #fdf7f7;
}
.field_with_errors .form-control-danger {
background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='%23d9534f' viewBox='-2 -2 7 7'%3E%3Cpath stroke='%23d9534f' d='M0 0l3 3m0-3L0 3'/%3E%3Ccircle r='.5'/%3E%3Ccircle cx='3' r='.5'/%3E%3Ccircle cy='3' r='.5'/%3E%3Ccircle cx='3' cy='3' r='.5'/%3E%3C/svg%3E");
}
I wasn't able to get the input groups addons to display correctly, as it wraps the input with a <div>.
Docs: https://v4-alpha.getbootstrap.com/components/forms/#validation
Honestly some of these classes are not used because Rails doesn't have an obvious way to set classes on error fields.
For the error list, I just used this simple class
#error_explanation {
color: red;
}
Maybe a simpler one is search for ids and classes on the form itself. Works for any combo.
By default, this are the lines included in scaffold to arrange the error messages. You can do with them whatever you want. Just have to extend them in your css.scss file:
.field_with_errors {
padding: 2px;
background-color: red;
display: table;
}
#error_explanation {
width: 450px;
border: 2px solid red;
padding: 7px 7px 0;
margin-bottom: 20px;
background-color: #f0f0f0;
}
#error_explanation h2 {
text-align: left;
font-weight: bold;
padding: 5px 5px 5px 15px;
font-size: 12px;
margin: -7px -7px 0;
background-color: #c00;
color: #fff;
}
#error_explanation ul li {
font-size: 12px;
list-style: square;
}
In case something is not working, check the navigator in developer mode. There you should be able to find all the html and css rails is creating...
Another variation with SCSS only
#error_explanation{
background: #f23551;
color: #fff;
border-radius: 4px;
margin-bottom: 20px;
h2{
padding: 20px;
margin: 0;
font-size: 20px;
}
ul{
background: #fff;
color: #e5324a;
border: 1px solid #F23551;
margin: 0;
list-style: none;
padding: 14px 0;
li{
padding: 4px 20px;
&:before {
content: '×';
font-weight: bold;
font-size: 20px;
margin-right: 10px;
}
}
}
}
I've create a custom initializer to have each field having its own errors below it
# app/config/initializers/bootstrap_form_errors_customizer.rb
ActionView::Base.field_error_proc = proc do |html_tag, instance|
is_label_tag = html_tag =~ /^<label/
class_attr_index = html_tag.index 'class="'
def format_error_message_to_html_list(error_msg)
html_list_errors = "<ul></ul>"
if error_msg.is_a?(Array)
error_msg.each do |msg|
html_list_errors.insert(-6,"<li>#{msg}</li>")
end
else
html_list_errors.insert(-6,"<li>#{msg}</li>")
end
html_list_errors
end
invalid_div =
"<div class='invalid-feedback'>#{format_error_message_to_html_list(instance.error_message)}</div>"
if class_attr_index && !is_label_tag
html_tag.insert(class_attr_index + 7, 'is-invalid ')
html_tag + invalid_div.html_safe
elsif !class_attr_index && !is_label_tag
html_tag.insert(html_tag.index('>'), ' class="is-invalid"')
html_tag + invalid_div.html_safe
else
html_tag.html_safe
end
end

RenderAction Partial View is Caching on Back Button Asp.Net MVC

I have a div with a Partial View on it which i render using RenderAction().
I am using Asp.Net MVC 4.0.
My problem is and it happens only on IE(version 9) , when i go to some other page and click the back button on IE, the partial view is not rendered. The partial View section is blank. Even on Firefox, the Action is not called, but at least the Partial View is rendered (its not blank)
Is there any solution to this ?
UPDATE
#foreach (var item in Model)
{
<article style="margin-top: 10px;">
<h5>
#item.Title
</h5>
<span >
<time>
#item.FromDateMonth
</time>-
<time>
#item.ToDateMonth
</time>
</span>
<div style="margin-top:10px;">
#Html.Label("Notes:", new { #style = "color: #000000; font-size: 13px; font-weight: bold; line-height: 16px;" })
<span style="color: #000000; font-size: 13px; font-weight: normal; line-height: 16px;">
#item.Notes
</span>
</div>
</article>

Inserting styles into an html table

I am storing old html markup in my database, tracking changes, and then trying to render the diff using Differ and the :html format option.
The following code is successfully generated:
<table>
...
<tr>
<th style="width:60px; text-align:left;">
Owner:
</th>
<del class="differ">
<td>
<span id="someID">Previous Owner Name</span>
</td>
</del>
<ins class="differ">
<td>
<span id="someID">Current Owner Name</span>
</td>
</ins>
</tr>
...
</table>
Notice the <del> and <ins> tagged elements.
If I view the source, it looks fine.
But because apparently this would disrupt the table layout, all browsers seem to move these new elements to before the table. When I inspect the element, I get the following:
<del class="differ"> </del>
<ins class="differ"> </ins>
<table>
...
<tr>
<th style="width:60px; text-align:left;">
Owner:
</th>
<td>
<span id="someID">Previous Owner Name</span>
</td>
<td>
<span id="someID">Current Owner Name</span>
</td>
</tr>
...
</table>
I tried writing a custom Rails view helper to replace each <ins> and <del> with a <span>, but the same thing happens.
Is there a way to style the table using elements like I am trying to do, or am I going to have to walk the dom and apply styles to each appropriate <td> using javascript? I cannot replace the tables in the beginning because I don't control the source.
Thanks to David & Steve for confirming the issue, I was able to resolve this specific case by translating the <ins> and <del> tags into classes, and applying them to each child element using Nokogiri prior to rendering the view.
I created a table_safe helper as follows:
def table_safe(markup)
parsed = Nokogiri.parse(markup)
parsed.css('ins').children().each do |el|
if el['class']
el['class'] = el['class'] << ' ins'
else
el['class'] = 'ins'
end
end
parsed.css('del').children().each do |el|
if el['class']
el['class'] = el['class'] << ' del'
else
el['class'] = 'del'
end
end
parsed.to_s
end
This can obviously be refactored, but it solves the problem. Ideally I could modify the :html formatting option in the Differ gem so that it inserts the tags inside of the first nested element if that element itself has not changed. I'm not sure why this isn't the default functionality, but it is outside the scope of my capabilities.
Why not add a CSS stylesheet to copy the style class differ to all TD elements?
<link rel="stylesheet" type="text/css" href="some.css" />
And then a definition like this in the stylesheet:
td {
padding: 15px;
background-color: gold;
text: black;
font-family: Courier, "Courier New", Tahoma, Arial, "Times New Roman";
border: 1px solid black;
/* Some other properties here...... */
}
And a sample HTML:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Anything</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<link rel="stylesheet" type="text/css" href="ja.css" />
</head>
<body bgcolor="white" text="black">
<table>
<tr>
<td>A</td>
<td>B</td>
</tr>
<tr>
<td>C</td>
<td>D</td>
</tr>
</table>
</body>
</html>
Working example:
http://pastehtml.com/view/ckdf6rxo3.html
Maybe this W3Schools link will be useful:
CSS Styling Tables

Rails CSS loads, but style isn't applied

I'm following the book http://pragprog.com/book/rails4/agile-web-development-with-rails and my scss files aren't working.
The css file is this one:
.store {
h1 {
margin: 0;
padding-bottom: 0.5em;
font: 150% sans-serif;
color: #226;
border-bottom: 3px dotted #77d;
}
/* An entry in the store catalog */
.entry {
overflow: auto;
margin-top: 1em;
border-bottom: 1px dotted #77d;
min-height: 100px;
img {
width: 80px;
margin-right: 5px;
margin-bottom: 5px;
position: absolute;
}
h3 {
font-size: 120%;
font-family: sans-serif;
margin-left: 100px;
margin-top: 0;
margin-bottom: 2px;
color: #227;
}
p, div.price_line {
margin-left: 100px;
margin-top: 0.5em;
margin-bottom: 0.8em;
}
.price {
color: #44a;
font-weight: bold;
margin-right: 3em;
}
}
}
and the html file the following:
<% if notice %>
<p id="notice"><%= notice %></p>
<% end %>
<h1>Your Pragmatic Catalog</h1>
<% #products.each do |product| %>
<div class="entry">
<%= image_tag(product.image_url) %>
<h3><%= product.title %></h3>
<p><%= sanitize(product.description) %></p>
<div class="price_line">
<span class="price"><%= product.price %></span>
</div>
</div>
<% end %>
The CSS is loading properly, but not being applied. However if add a surrounding div with the class "store" it works. The book doesn't refer this situation, and I believe it should "automatically" apply the style, right?
Thanks.
**EDIT********
I found the problem. For those who may encounter the same issue, check the file:
app/assets/views/layouts/application.html.erb
body tag should have the following code:
<body class="<%= controller.controller_name %>">
Great that you found out the solution. But im trying to explain what happened behind the scene.
The way you are using the css is not a general convention. This facility comes with some additional gem. Check this link https://stackoverflow.com/a/4564922/1160106. With these gems you are able to design your css more DRY way.
General Convention
if you want to apply style to the following h1 element
# Here "store" class is the parent element of "h1"
<div class="store">
<h1> some text </h1>
</div>
Will require following way of css
#Here also "store" is written before "h1"
.store h1
{
#some designs
}
Whats happening in your case?
Probably you are maintaining controller wise css files. And presuming that you have a stores_controller. Thats why the classes for your stores_controller is encapsulated in .store {} block. Like
.store {
h3 {font-size: 120%;}
}
So it is clear that your h3 elements require a parent element having store class. And you are doing so by adding class="<%= controller.controller_name %>" with your body tag. Undoubtedly the <body> tag is parent of all following nodes. Now when you are hitting stores_controller it sets class="store" and your styles are working.
The approach is really DRY and recommendable.
As per your code all the styling is between the .store { } block, so it will not reflect as long as you surrounding div with the class "store"
For example
.store {
h3 {
font-size: 120%;
font-family: sans-serif;
margin-left: 100px;
}
}
is same as
.store h3 {
font-size: 120%;
font-family: sans-serif;
margin-left: 100px;
margin-top: 0;
margin-bottom: 2px;
color: #227;
}