Rails 4 + Sass - No background image in production - ruby-on-rails

I know there are alot of similar questions/answers on SO about this, and I have tried at least 7 of the proposed methods. I can display my app's background image locally in a variety of ways. After trying for nearly 40 hours, there seems to be no way to render it in production. It runs on the following:
Ruby 2.1.5
Rails 4.1.8
Puma 2.1 via Amazon Elastic Beanstalk (single instance - no load balancer)
I've tried every combination of config.serve_static_assets=[true|false] and setting RAILS_SKIP_ASSET_COMPILATION to true and false.
Ran rake assets:precompile RAILS_ENV=production
Tried every path I can think of, but it's not finding the background image. One thing I noticed was that precompilation changes the name of the image when it copies to the public/assets directory. (example: "foo.jpg" becomes "foo-ilfajwe8hjsa8erfjsdf.jpg") So I tried copying the original image files to the new public/assets directory, hoping the app would find them there. That didn't work.
I'm thinking it might be how I'm referencing it in my css, because oddly the favicon file displays as does the fonts from my app's "fonts" folder. And both have their names appended to just like the background image.
Here is my application.html.erb..
<!DOCTYPE html>
<html>
<head>
<title>Capstone v1.4.5</title>
<%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track' => true %>
<%= javascript_include_tag 'application', 'data-turbolinks-track' => true %>
<%= csrf_meta_tags %>
<%= favicon_link_tag 'capstone_icon.png' %>
</head>
<body>
<% if notice %>
<p class="alert alert-success"><%= notice %></p>
<% end %>
<% if alert %>
<p class="alert alert-danger"><%= alert %></p>
<% end %>
<%= render 'navigation' %>
<main>
<%= yield %>
</main>
</body>
</html>
Here is the application.css.sass..
/*
*= require bootstrap.min
*/
#import "bootstrap-sprockets"
#import "bootstrap"
#font-face
font-family: 'Cinzel-Regular'
src: font-url('Cinzel-Regular.ttf')
#font-face
font-family: 'Oxygen'
src: font-url('Oxygen.otf')
html
position: relative
min-height: 100%
body
background-image: image-url("snowy_prairie_bg.jpg")
background-repeat: no-repeat
background-position: center top
font-family: 'Oxygen'
margin: 0 0 95px
The contents of my public directory (after precompilation)
application-6cca23f2f72df0ad7d26279535719396.css
application-6cca23f2f72df0ad7d26279535719396.css.gz
application-fddd9c84ba451526dbd2ef5bf46e494c.js
application-fddd9c84ba451526dbd2ef5bf46e494c.js.gz
bootstrap
capstone_icon-ed6ffe0ae4bbbb56a8b74a4d7ff230cf.png
capstone_icon.png
Cinzel-Regular-59dcda430d3afc3ace221f1835d7fb08.ttf
images
manifest-73d04c0fd1290b15fb280becfcf62b7b.json
Oxygen-1c736bd9242de63cf87c07f0a48c9b5c.otf
Oxygen-Bold-01bc72645c864aa090d57754565ef634.otf
Oxygen-BoldItalic-cfe32a5aedef7b25f8b1efdfcbdbd72a.otf
Oxygen-Italic-2a51c29c8f2bd242ac27e6fb7860f6a1.otf
snowy_prairie_bg-d246fbbe1178a09d38df31be96aee79a.jpg
snowy_prairie_bg.jpg
Am I referencing the image wrong in my css? Again, it renders great locally. Should I be using Passenger instead of Puma? This is not a very small app and I've got alot invested in the database, also hosted on Amazon. But like I said, I'm approaching 40 hours just trying to get this background rendered.
If you have any ideas, please help. I am willing to try anything!
Thank you
FYI - the above bootstraps, fonts, other images and sass styles render perfectly. It's just the background image. Thanks
EDIT: When I go to the page, capstonesavings.com, the following error is shown in the dev. console: Failed to load resource: the server responded with a status of 403 (Forbidden). Do I need to change permissions on something?

OK, SO I THINK I FIXED IT!
Most of the above code is correct, but I changed the following from the above application.css.sass..
Changed
background-image: image-url("snowy_prairie_bg.jpg")
To
background-image: asset-url("snowy_prairie_bg.jpg")
Then, I SSH'ed into the instance (eb ssh) and did the following:
cd /var/app/current
followed by
sudo chmod 755 public/assets/snowy_prairie_bg-d246fbbe1178a09d38df31be96aee79a.jpg
I had tried the above change to the SaSS before, but it didn't work without changing permissions. Thanks to Chrome developer tools, I noticed a (tiny) error flag when the page was rendered. I clicked it and it showed the 403 error that I added in the above edit. This is some stuff that Amazon uses to make things secure, since I guess you can route your log files, etc. to the associated S3 bucket. So that's why I explicitly targeted the image in question when changing the perms. This site isn't going to have a ton of images, but if it did I'd probably take the time to elaborate on the storage within the bucket and set broader perms accordingly.
This saved the day for me. Hope it helps someone else.

Related

stylesheet_link_tag together with Bootstrap

I'd like to set Bootstrap on Rails 5.1.5, following the tutorial https://www.railstutorial.org/book/filling_in_the_layout but the procedure with the Gemfile won't work.
After some readings, in particular here: Installing Bootstrap 3 on Rails App I ended up downloading the css files and copying them directly in app/assets/stylesheets.
Now I get this error:
Invalid CSS after "...quire bootstrap": expected "{", was ""
linked to this line in application.html.erb
<%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %>
As I understand, this line is processed with the application.scss file that I have created in app/assets/stylesheets (where there was a file application.css). This file has only one line:
*= require bootstrap
After looking further in the docs, I have made a test with:
<%= stylesheet_link_tag "bootstrap" %>
and from there I get another error:
TypeError: Cet objet ne gère pas cette propriété ou cette méthode
which means 'this object doesn't deal with this method'.
Just another misconfiguration of my Rails installation or what ?
Is it possible that a nodeJS installation solve the problem ? I've found a reply here Ruby on rails: Stylesheets not working ExecJS::ProgramError which seems to have made it.
Actually installing NodeJS can help a lot: this should be the very first thing to do for window users!

LoadError in ProductsController#index

This is the follwing happened while running the application
I am also not able to install therubyracer gem to ruby
cannot load such file -- v8 (in C:/railsapps/myapp/app/assets/stylesheets/bootstrap_and_overrides.css.less)
Extracted source (around line #10):
8 <script src="http://html5shim.googlecode.com/svn/trunk/html5.js" type="text/javascript"></script>
9 <![endif]-->
10 <%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track' => true %>
11
12
13 <%= javascript_include_tag "application" %>
SASS
This issue will likely be caused by importing (requiring) that particular file in your CSS
If you use one of the SASS #import functions like this:
#app/assets/stylesheets/application.css.sass
#import "name"
The problem here is that, like in other programming interfaces, if you call a file which doesn't exist, it will throw an error. If this happens, you'll typically receive an error like the one you're seeing (I.E "could not find" etc etc)
--
Fix
Without seeing your application.css.less, I can only speculate on what the answer might be. I would recommend:
Make sure you have the following file present (even if empty): app/assets/stylehsheets/bootstrap_and_override.css.less
With the file present, you should then be able to load it. If not, you need to find the reference to #import in your
application.css.less file

JW-Player and Rails 3.2

I'm trying to use JW-Player in my application. Researching the issue a bit, there seems to be several abandoned efforts to produce a gem, and the latest is undocumented. So, here's how I'm going about it:
I downloaded the JW-Player version 6, unzipped and copied the files in my /app/assets/javascripts directory as follows:
app/assets/javascripts/jwplayer/jwplayer.js
app/assets/javascripts/jwplayer.html5.js
app/assets/javascripts/jwplayer.flash.swf
In my app/views/layouts/application.html.erb, I have the following:
<head>
<%= javascript_include_tag "/assets/javascripts/jwplayer/" %>
</head>
and in app/views/pages/about.html.erb, I have the following:
<%= jw_player("http://xxxxx/video.mp4",
:width => 200, :height => 110) %>
Here's what happens when I click on the About page link:
Showing xxxxxxxx/app/views/pages/about.html.erb where line #10 raised:
undefined method `jw_player' for #<#<Class:0x007fe77e37c018>:0x007fe780c1f678>
First time user of JW-Player.
When implementing JWPlayer 6.6, we stood before the choice of putting the jwplayer.flash.swf file into the public folder, to make the flash mode work, but it seemed very messy to have the files separated like that. What I did in the end to make it work both on development and production was:
Put all 3 files to vendor/assets/javascripts/jwplayer
Rename jwplayer.js to jwplayer.js.erb
Inside jwplayer.js.erb, update the flash file path config like this (the 1st line with the html5 file path config is just for reference)
j={type:"html5",src:e.base+"jwplayer.html5.js"},
b={type:"flash",src:"<%= asset_path('jwplayer/jwplayer.flash.swf') %>"};
(note that the "e.base+" before the path was removed for the flash file path - that's the trick that allowed working relative paths in the development environemtn)
In my understanding, the JWPlayer license allows modifications like this:
"Adaptations
Publisher shall be permitted to make Adaptations reasonably necessary for the purpose of exercising its rights under these Terms of Service, such as Adaptations to integrate the Products into Publisher’s websites or other properties. All Adaptations created by Publisher are strictly for its own Use and Publisher is prohibited from Distributing any Adaptation it creates. The Company reserves the right to prohibit the Use of any Adaptation in its sole discretion."
I have just finished working on a gem started by choix and improved by mattherick called jwplayer-rails that probably worked in older version of rails. It wasn't working with the assets pipeline but mattherick did a great job at fixing that up and I went on to update JWPlayer to the newest version.
You can see the repository here.
The following instructions are right out of the repo above.
To add this gem to your rails app just add this line to your application's Gemfile:
gem 'jwplayer-rails', :git => 'git://github.com/dutgriff/jwplayer-rails.git'
To use it first include assets on the page
<%= jwplayer_assets %>
Then place a div with JW Player
<%= jwplayer %>
You can pass options to jwplayer helper to customize it:
<%= jwplayer({width: 500, height: 200}) %>
More information for customization could be found here.
It works great for me so far but if you find an issue let me know on here or github.
I've found a solution to this.
The main issue you need to work-around is that jwplayer.js wants to fetch jwplayer.flash.swf and jwplayer.html5.js based on the path of jwplayer.js.
You can see that in Chrome Developer Toolbar for jwplayer.js (with pretty print):
(h.embed.config = function(b) {
var e = {fallback: !0,height: 270,primary: "html5",width: 480,base: b.base ? b.base : j.getScriptPath("jwplayer.js"),aspectratio: ""};
b = j.extend(e, h.defaults, b);
var e = {type: "html5",src: b.base + "jwplayer.html5.js"},
g = {type: "flash",src: b.base + "jwplayer.flash.swf"};
You can use that base property as an undocumented api to tell jwplayer where the jwplayer.flash.swf and jwplayer.html5.js can be found.
Example:
jwplayer("player-id").setup({
width: 640,
height: 480,
file: "www.w3schools.com/html/movie.mp4",
base: "http://cloudfront.net/assets/vendor/jwplayer/"
};
Then it will look for http://cloudfront.net/assets/vendor/jwplayer/jwplayer.flash.swf. Note: jwplayer has no notion of the asset pipeline fingerprint filenames, so make sure you sync both the file with md5 and without.
This worked for me:
Place jwplayer folder in public (Downloaded from longtail video)
Include it like an external script, without using asset pipeline (HAML).
%script{:src => '/jwplayer/jwplayer.js'}
In your video partial (ERB)
<script type="text/javascript">
jwplayer.key="Your key here";
$(document).ready(function(){
jwplayer("video").setup({
height: 360,
width: 640,
playlist: [
<% videos.each do |v| %>
{
image: "<%= v.poster %>",
sources: [
{ file: "<%= v.url %>" },
]
},
<% end %>
]
});
})
</script>
<video id="video">Video Loading... Ensure JavaScript is enabled...</video>
Did you restart the server after downloading the player and including it in your layouts. This could be one reason of failure.
Download jwplayer from http://www.longtailvideo.com/jw-player/download/
Put these files to the particular directory:-
app/assets/jwplayer/jwplayer.flash.swf
vendor/assets/javascripts/jwplayer.js
vendor/assets/javascripts/jwplayer.html5.js
Then add these line in application.js
//= require jwplayer
//= require jwplayer.html5
On the page where you are playing video, add these lines
<script type="text/javascript">jwplayer.key="YOUR_JWPLAYER_KEY";</script>
<div id="video">Loading the player ...</div>
<script type="text/javascript">
jwplayer("video").setup({
flashplayer: "<%=asset_path('jwplayer.flash.swf')%>",
file: "<%= file_path %>",
height: 360,
width: 640,
analytics: {
enabled: false,
cookies: false
}
});
http://account.longtailvideo.com/#/home from where you can get your free self hosted key in signing up from Get Your License Key portion.
I also chose JWplayer.
Here are my steps.
I'm using https://github.com/choix/jwplayer-rails gem.
Added
gem 'jwplayer-rails', '1.0.1'
to my Gemfile.
Did all things from above page; in a show.html.slim view file included these lines:
= jwplayer_assets
br
br
= jwplayer({file:#lesson.media_file})
lesson.media_file attribute contains file location. For a video file project/public/videos/videoclip.webm, media_file contains string "/videos/videoclip.webm".
Hope this will be useful.

Generating a PDF in Rails with MathJax and wkhtmltopdf

I'm writing a website using Rails 3.2.6 and it needs to be able to display maths formatting on the website. To do this job I am using the mathjax-rails gem which works perfectly rendering the maths on, for example, questions/1. However, I would like the user to be able to download the question containing the maths content as a PDF. I have done a lot of searching and fiddling with my app and the closest I have come to a solution is wkhtmltopdf and the wicked_pdf gem. This works, in that a PDF is created which is saved to the user's computer. However, the maths is not rendered properly because, I presume, mathjax is not actually processing it.
Having done a bit of reading, I thought I found the answer elsewhere where it said to add a delay to the controller to give mathjax a chance to do its magic:
format.pdf do
render :pdf => 'filename',
:javascript_delay=>5000
end
However this doesn't work either and I end up with a PDF covered in things like:
[itex]3H_{2~(g)} + 2N_{2~(g)} ⇌ NH_{3~(g)}[/itex]
Rather than formatted maths. Has anyone got any clues on how I can get this to work?
Thanks in advance.
This is even a bit silly, but have you tried a longer delay?
With wkhtmltopdf this works:
wkhtmltopdf.exe --javascript-delay 15000 http://www.mathjax.org/demos/mathml-samples/ MML.pdf && MML.pdf
This does not work
wkhtmltopdf.exe --javascript-delay 5000 http://www.mathjax.org/demos/mathml-samples/ MML.pdf && MML.pdf
It's the same for the TeX samples as well
I finally solved it like this, the only thing is that I used the cdn instead of the gem:
This is my show action in the controller:
def show
#example = Exam.find(params[:id])
respond_to do |format|
format.html
format.pdf do
render pdf: #exam.name,
template: "exams/show.pdf.erb", // The template that you want to convert to pdf
:javascript_delay=>5000,
locals: {:exam => #exam},
layout: "application-pdf.html.erb"
end
end
end
And inside app/views/layouts/application-pdf.html.erb:
<!DOCTYPE html>
<html>
<head>
<title>MathTest</title>
<meta charset='utf-8' />
<%= stylesheet_link_tag "https://fonts.googleapis.com/icon?family=Material+Icons" %>
<script type="text/x-mathjax-config">
MathJax.Hub.Config({
extensions: ["tex2jax.js"],
jax: ["input/TeX", "output/HTML-CSS"],
tex2jax: {
inlineMath: [ ['$','$'], ["\\(","\\)"] ],
displayMath: [ ['$$','$$'], ["\\[","\\]"] ],
processEscapes: true
},
"HTML-CSS": { availableFonts: ["TeX"] }
});
</script>
<script type="text/javascript" async
src="https://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-MML-AM_CHTML">
</script>
</head>
<body>
<%= yield %>
</body>
</html>
The key is to wrap your pdf template, in my case "exams/show.pdf.erb" in an application layout designed for your pdf, the cdn is loaded in the layout and you just have to give wickedpdf the option to delay the javascript processing so mathjax has enough time to process the page.
Hope it helps.
UPDATE
As Peter Krautzberger mentioned, cdn.mathjax.org is shutting down due to budget issues. The solution would stay the same, you just have to load the mathjax from your project internally or use another cdn. You can fiend some cdn alternatives here: https://www.mathjax.org/cdn-shutting-down/

Rails: WickedPDF: Page Breaks

In my Ruby (1.9.2) Rails (3.0.x) I would like to render a web page as PDF using wicked_pdf, and I would like to control where the page breaks are. My CSS code to control page breaks is as follows:
<style>
#media print
{
h1 {page-break-before:always}
}
</style>
However, when I render the page with wicked_pdf, it does not separate the document into two pages. Is there something else that I must do to get page breaks with wicked_pdf?
For some reason, the "#media print" didn't quite do it. I just went with
.page-break { display:block; clear:both; page-break-after:always; }
for the CSS rule, and then I stuck the following in my page for a page break:
<div class="page-break"></div>
That just worked.
Tried Jay's solution but could not get it to work (maybe a conflict with other css)
I got it to work with this:
<p style='page-break-after:always;'></p>
I had the same problem and I discovered something that might help. This was my page break CSS code:
.page-break {
display: block;
clear: both;
page-break-after: always;
}
This didn't work because of TWO reasons:
I. In one of the SASS imported file I had this line of code:
html, body
overflow-x: hidden !important
II. The other problem was bootstrap
#import "bootstrap"
It looks like because of the float: left in:
.col-xs-1, .col-xs-2, .col-xs-3, .col-xs-4, .col-xs-5, .col-xs-6, .col-xs-7, .col-xs-8, .col-xs-9, .col-xs-10, .col-xs-11, .col-xs-12 {
float: left;
}
the page break is no longer working. So, just add this after you import bootstrap.
.col-xs-1, .col-xs-2, .col-xs-3, .col-xs-4, .col-xs-5, .col-xs-6, .col-xs-7, .col-xs-8, .col-xs-9, .col-xs-10, .col-xs-11, .col-xs-12 {
float: initial !important;
}
None of these solutions worked for me. I did find a solution that worked for many people in the gem issues here - https://github.com/wkhtmltopdf/wkhtmltopdf/issues/1524
you want to add CSS on the element that needs the page break. In my case, it was table rows, so I added:
tr {
page-break-inside: avoid;
}
Make sure that the stylesheet link tag includes media='print" or media='all' if you are using an external stylesheet:
<%= stylesheet_link_tag 'retailers_pdf',media: 'all' %>
or
<%= stylesheet_link_tag 'retailers_pdf',media: 'print' %>
otherwise wicked_pdf will not pick it up.
Also note that if you are in the middle of a table or div with a border, that the page-break attributes will not work. In this case, it's time to break out jQuery and start splitting things up. This answer: https://stackoverflow.com/a/13394466/2016616 has a good snippet for position measurement. I am working on clean and repeatable table-splitting code and will post it when I have finished it.
i had the same issue and what ended up working for me was to make sure that my element with
page-break: always;
was on the root of the document, seems when its nested inside of other elements, especially ones with height assigned, the declaration gets ignored.
hope this helps someone.

Resources