Rails asset pipeline and serving static files from nginx - ruby-on-rails

I'm trying to access a file logo.png from my rails app. During the deploy process everything in /app/assets gets compiled and placed into /public/assets. For example my file which had been named logo.png looks like this:
/public/assets/logo-e66eddecdb08ac2b7fe349da2a065d87.png
When I try to access that full filename nginx successfully serves it up directly because of these lines in my /etc/sites-enabled/myapp:
try_files $uri/index.html $uri #unicorn;
root /home/deployer/apps/myapp/current/public
So I can browse to myserverhost.com/assets/logo-e66eddecdb08ac2b7fe349da2a065d87.png and it loads fine. However of course in my app I have that file referenced simply as "logo.png" and when I load my home page I'm getting a 404 not found on the logo.png.
How is nginx supposed to know that the filename has been mashed up with a hash at the end?
EDIT: I reference the logo file like this in my scss file:
#sidebar .logo-div {
border-bottom: 2px solid#ddd;
width:100%;
height:80px;
text-align:center;
background-image:url('logo.png');
background-position:center;
background-repeat:no-repeat;
margin-bottom:20px;
}

You'll have to use an url helper.
background-image: url(image-path("logo.png"));
or
asset-url("logo.png", image)
Rails automatically adds the hash in production.

If your file is a css file:
background-image: url(/assets/logo.png);
If your file is a sass file can use the helper:
background-image: image-url("logo.png");

Related

Image Asset Not Loading In Production

I'm running Rails 5.2.2. I recently separated some admin code from my frontend and in the process moved my controllers, views, css & JS to folders in either frontend or admin respectively.
In development, everything works fine. In production, I am unable to load image assets from my css.scss files using the following line background: url(arrow.png) no-repeat left center; (located in app/assets/stylesheets/frontend/application.css.scss).
My assets has the following file structure:
assets/
config/
images/
admin/
frontend/
products/
another_folder/
javascripts/
admin/
frontend/
stylesheets/
admin/
frontend/
I did not have to change any of my image tags in my views once I made these changes for my images in assets/images/products so I figured that I wouldn't have to do that anywhere else either; things just seemed to work. However, in production the arrow.png returns a 404. When I inspect the image request, the link to the image is /assets/frontend/arrow.png. I use the RAILS_ENV=production flag when compiling assets. I have also run rake assets:clobber with the production flag then tried compiling the assets again. I've deleted all browsing data.
Here are my server logs where the image is requested:
I, [2019-08-01T05:06:22.496953 #6733] INFO -- : [8a0b82c0-c4a3-419f-92fd-8f4a89bbe643] Started GET "/assets/frontend/arrow.png" for 35.188.197.210 at 2019-08-01 05:06:22 +0000
F, [2019-08-01T05:06:22.501395 #6733] FATAL -- : [8a0b82c0-c4a3-419f-92fd-8f4a89bbe643]
F, [2019-08-01T05:06:22.503739 #6733] FATAL -- : [8a0b82c0-c4a3-419f-92fd-8f4a89bbe643] ActionController::RoutingError (No route matches [GET] "/assets/frontend/arrow.png"):
UPDATE:
Adding this to a view works fine in production so I can confirm the asset does indeed compile properly.
<%= image_tag("frontend/arrow.png") %>
For Rails 5, please try to change following configuration:
config.public_file_server.enabled = ENV['RAILS_SERVE_STATIC_FILES'].present?
to
config.public_file_server.enabled = true
OR
you can set RAILS_SERVE_STATIC_FILES true in your passenger_env_var. That will also work.
Helo is this code works for you?
background: image-url(arrow.png) no-repeat left center;

Font awesome Rails won't work after deploying. It looks like bad Unicode characters. Why?

In my local machine fontawesome is working perfectly (Im using 4.1 gem). But when uploaded to Heroku it stops working. I looks like bad unicode characters. I have included the following line in config and precompiled assets but it didn't work :
config.assets.paths << Rails.root.join(‘app’, ‘assets’, ‘fonts’)
config.assets.precompile += %w( .svg .eot .woff .ttf )
Please look at this image :
On the left is the problem. On the right is the correct version. What might be the problem? Here's the link to the Heroku app : http://fast-garden-6871.herokuapp.com/
Update It looks like /assets/fontawesome-webfont.eot is missing in the production machine!
In your css file, change url to asset-url under #font-face.
Also did you precompile assets after deployment?
RAILS_ENV=production rake assets:precompile
Finally fixed it! In custom.css I added the following lines:
#font-face {
font-family: 'FontAwesome';
src: asset-url('fontawesome-webfont.eot');
src: asset-url('fontawesome-webfont.eot?#iefix') format('embedded-opentype'), asset-url('fontawesome-webfont.woff') format('woff'), asset-url('fontawesome-webfont.ttf') format('truetype'), asset-url('fontawesome-webfont.svg#fontawesomeregular') format('svg');
font-weight: normal;
font-style: normal;
}
The problem was, rails will generate the font file with a hash like it generate css files. But the css is not updated with this new generated file. So the system can't find the font. With the above code, the system will assign the right url!

Heroku font assets not working

Placed fonts in app/assets/fonts
Added
Add the fonts path
config.assets.paths << Rails.root.join('app', 'assets', 'fonts')
Precompile additional assets
config.assets.precompile += %w( .svg .eot .woff .ttf )
in production.rb and development.rb
Fonts linked in css like:
#font-face {
font-family: 'Icomoon';
src:url('/assets/icomoon.eot');
src:url('/assets/icomoon.eot?#iefix') format('embedded-opentype'),
url('/assets/icomoon.svg#icomoon') format('svg'),
url('/assets/icomoon.woff') format('woff'),
url('/assets/icomoon.ttf') format('truetype');
font-weight: normal;
font-style: normal;
}
Seems to work in development. But in HEROKU is does not seem to work. It cannot find /assets/icomoon.eot .
The solution in this link does not seem to work
Using fonts with Rails asset pipeline
Assets like fonts will work on development but not production if you are using regular old css to locate your assets rather than the asset pipeline helpers. Rails 4 added breaking changes to the asset pipeline to encourage people to use it properly, and not use the old css method of referencing assets.
To resolve this, you need to use the new asset pipeline helpers to point to the fingerprinted, cached versions of your fonts. Rather than url (which does not use the asset pipeline), you need to use font-url (which does use it). To do this, you may have to use Sass or embed ERB in your stylesheet.
Example (using SCSS):
#font-face {
font-family: 'Icomoon';
src: font-url("/assets/icomoon.eot");
src: font-url("/assets/icomoon.eot?#iefix") format("embedded-opentype"), font-url("/assets/icomoon.svg#icomoon") format("svg"), font-url("/assets/icomoon.woff") format("woff"), font-url("/assets/icomoon.ttf") format("truetype");
font-weight: normal;
font-style: normal;
}
See here: http://guides.rubyonrails.org/asset_pipeline.html#coding-links-to-assets
In light of the comments received on this answer (and the unnecessary downvotes) I've amended my answer as follows:
It seems Rails has now created a way to handle fonts in the assets folder. It's called font-path and works like this:
If you add a custom font to your /assets/fonts folder, you can use the
font-path helper to access the files within. This can then be used
in your stylesheets & other assets using the font-path helper:
|-app/
|---assets/
|-----fonts/
|-----images/
|-----javascripts/
|-----stylesheets/
#font-face {
font-family:'icofonts';
src:font-url('icofonts.eot');
src:font-url('icofonts.eot?#iefix') format('embedded-opentype'),
...
}
This works for precompiled assets (which Heroku does anyway), and static assets. If you want the pre-Rails 4 way of achieving this, please refer to my answer below:
We've got fonts working on Heroku here: http://firststop.herokuapp.com (it's in demo still)
Here is our CSS for it:
#assets/application.css
/*-- Akagi Font --*/
#font-face {
font-family: 'akagi';
src: url('fonts/akagi-th-webfont.eot'),
src: url('fonts/akagi-th-webfont.eot?#iefix') format('embedded-opentype'),
url('fonts/akagi-th-webfont.woff') format('woff'),
url('fonts/akagi-th-webfont.ttf') format('truetype'),
url('fonts/akagi-th-webfont.svg#akagithin') format('svg');
font-weight: 300;
font-style: normal;
}
#font-face {
font-family: 'akagi';
src: url('fonts/akagi-bk-webfont.eot');
src: url('fonts/akagi-bk-webfont.eot?#iefix') format('embedded-opentype'),
url('fonts/akagi-bk-webfont.woff') format('woff'),
url('fonts/akagi-bk-webfont.ttf') format('truetype'),
url('fonts/akagi-bk-webfont.svg#akagibook') format('svg');
font-weight: 400;
font-style: normal;
}
#font-face {
font-family: 'akagi';
src: url('fonts/akagi-sb-webfont.eot');
src: url('fonts/akagi-sb-webfont.eot?#iefix') format('embedded-opentype'),
url('fonts/akagi-sb-webfont.woff') format('woff'),
url('fonts/akagi-sb-webfont.ttf') format('truetype'),
url('fonts/akagi-sb-webfont.svg#akagisemibold') format('svg');
font-weight: 500;
font-style: normal;
}
We put our fonts into the /stylesheets/fonts folder
We just do the standard precompile fonts stuff to get all CSS working on Heroku, and it works. I suspect your paths are not correct. Maybe try moving your fonts directory into your /assets/stylesheets folder :)
Actually, I just tried the solution proposed in this comment, and it worked perfectly. Seems you only have to change the regex for the precompile instruction in order for Heroku to correctly find the asset.
i.e. change config.assets.precompile += %w( .svg .eot .woff .ttf ) to config.assets.precompile << /\.(?:svg|eot|woff|ttf)$/.
Edit: It might also be necessary to add RAILS_ENV=production when you run the assets:precompile rake task, as per Heroku's docs.
Rails 4
# config/application.rb
config.assets.paths << Rails.root.join("app", "assets", "fonts")
config.assets.precompile += %w(.svg .eot .woff .ttf)
# app/assets/stylesheets/foundation-icons.css.scss
#font-face {
font-family: "foundation-icons";
src: asset-url("foundation-icons.eot");
src: asset-url("foundation-icons.eot?#iefix") format("embedded-opentype"),
asset-url("foundation-icons.woff") format("woff"),
asset-url("foundation-icons.ttf") format("truetype"),
asset-url("foundation-icons.svg#fontcustom") format("svg");
font-weight: normal;
font-style: normal;
}
Try removing /assets/ from all of your font paths.
#font-face {
font-family: 'Icomoon';
src:url('icomoon.eot');
src:url('icomoon.eot?#iefix') format('embedded-opentype'),
url('icomoon.svg#icomoon') format('svg'),
url('icomoon.woff') format('woff'),
url('icomoon.ttf') format('truetype');
font-weight: normal;
font-style: normal;
}
Also try removing scaffolds.css if it's in assets/stylesheets.
I solved the problem by using a combination of all the answers and comments. My example uses the Foundation Icon Fonts.
In your application.rb file add the following:
config.assets.precompile << /\.(?:svg|eot|woff|ttf)$/
Rename your application.css file to application.css.scss and use the font-url and asset-path directives:
#font-face {
font-family: "foundation-icons";
src: font-url( asset-path("foundation-icons.eot") );
src: font-url( asset-path("foundation-icons.eot?#iefix") ) format("embedded-opentype"),
font-url( asset-path("foundation-icons.woff") ) format("woff"),
font-url( asset-path("foundation-icons.ttf") ) format("truetype"),
font-url( asset-path("foundation-icons.svg#fontcustom") ) format("svg");
font-weight: normal;
font-style: normal;
}
You don't actually have to change the precompile regex or asset path.
Try to run rake assets:precompile in production mode before committing to Heroku.
rake assets:precompile RAILS_ENV=production
and make sure to reference your assets in css files using asset_path helper method.
like:
src: font-url('<%= asset_path("foundation-icons.eot")%>');
You don't need to include the /assets/fonts/ directory in config.assets.paths. According to documentation all directories included in app/assets, lib/assets or vendor/assets are automatically loaded.
http://guides.rubyonrails.org/asset_pipeline.html#asset-organization
Pipeline assets can be placed inside an application in one of three locations: app/assets, lib/assets or vendor/assets.
[...]
Besides the standard assets/* paths, additional (fully qualified) paths can be added to the pipeline in config/application.rb.
config.assets.paths << Rails.root.join("lib", "videoplayer", "flash")
Try to run Rails.application.class.config.assets.paths in console and you'll see an array of all directories inside /assets. if you add another directory and restart the console it will be automatically included inside the array and the content will be served as assets.
You don't even need config.assets.precompile += %w( .svg .eot .woff .ttf ) because all non-js-css files are already included through the default matcher Proc.
http://guides.rubyonrails.org/asset_pipeline.html#precompiling-assets
The default matcher for compiling files includes application.js, application.css and all non-JS/CSS files (this will include all image assets automatically):
[ Proc.new { |path| !%w(.js .css).include?(File.extname(path)) }, /application.(css|js)$/ ]
Try to only add the fonts directory in app/assets/ leaving all config as default and deploy your app on heroku.
Rename your .css file to .css.erb
Replace all the url('/assets/icomoon.eot') with url(<%= asset_path 'icomoon.eot' %>), etc.
You can achieve the same result by converting your css file to SASS/SCSS and using font-url() helper instead of url().
I've tried that with Rails 4 and it works even without the bits you've added to production.rb/application.rb.
After trying all the methods above, none worked for me but this is how I fixed my font problem. If the fonts work in development mode then simply do
config.assets.compile = true
in
config\environments\production.rb
There are two ways to solve this issue.
You can directly put your font files in public directory and add the path e.g /fonts/font-name in the CSS file
Add the line Rails.application.config.assets.compile = true in config/initializers/assets.rb file

Font-Face not Working with Rails 3.1

I just upgraded to Rails 3.1 and the Asset Pipeline and I can't figure out why my font-face is not being read in anymore. I've tried the answers in this post (with no luck):
Using #font-face with Rails 3.1 app?
Currently, I'm trying the selected solution. I have a fonts folder under app/assets. The file name is correct and exists in the fonts directory.
In my Application.rb
config.assets.paths << "#{Rails.root}/app/assets/fonts"
I've also tried, from the Rails Guide (http://guides.rubyonrails.org/asset_pipeline.html):
config.assets.paths << Rails.root.join("app", "assets", "fonts")
With this code, the path maps to this when the code is run
src: url('/assets/League_Gothic-webfont.eot
In my CSS:
#font-face {
font-family: "League_Gothic";
src: url('<%= asset_path('League_Gothic-webfont.eot') %>');
font-weight: normal;
font-style: normal;
}
When I try the other solution, essentially hard coding the path:
src: url(/assets/fonts/League_Gothic-webfont.eot);
I get this error when I click on the link in the source code of the page:
No route matches [GET] "/assets/fonts/League_Gothic-webfont.eot"
Add this to application.rb
# Enable the asset pipeline
config.assets.enabled = true
config.assets.paths << "#{Rails.root}/vendor/assets/fonts"
# Precompile additional assets
config.assets.precompile += %w( .svg .eot .woff .ttf )
Then add this to css or scss before the font is used
#font-face {
font-family: 'Museo300Regular';
src: font-url('Museo300-Regular-webfont.eot');
src: local('Museo300Regular'),
font-url('Museo300-Regular-webfont.eot?#iefix') format("embedded-opentype"),
font-url('Museo300-Regular-webfont.woff') format("woff"),
font-url('Museo300-Regular-webfont.ttf') format("truetype"),
font-url('Museo300-Regular-webfont.svg#Museo300Regular') format("svg") ;
font-weight: normal;
font-style: normal;
}
You shouldn't have to make those changes in application.rb.
But what's probably your problem is that you're doing "assets/fonts/myfont.eof" when you should be doing "assets/myfont.eof". Don't address fonts, images, etc. directory names if they're assets, just call them from assets/
You may have to get rid of that stuff that you changed in application.rb in order for this to work. I dunno, try it with and without.
Also, from my CSS file on a project I'm working on:
#font-face
{
font-family: ubuntu;
src: url("/assets/Ubuntu-R.ttf");
}
This might help.

Heroku and #font-face - embedded fonts wont display on Heroku

I have a few licensed fonts that I have embedded into my Rails app using the CSS #font-face tag. These fonts are located in the "../Public/Fonts/" path in my Rails 3 app and render perfectly on any local machine that I pull down the repo and run on.
However when I push my app to Heroku it can't seem to find the fonts. You can tell that it's looking in the font directory but can never access them. It doesn't seem to matter where I place the fonts or how I type the font path in the #font-face declaration.
My fonts are located at #{RAILS.root}/public/fonts/ChunkFive
Here is my #font-face declaration:
#font-face {
font-family: "ChunkFive";
src: url("../fonts/ChunkFive/ChunkFive-webfont.eot");
src: local("?"),
url("../fonts/ChunkFive/ChunkFive-webfont.woff") format("woff"),
url("../fonts/ChunkFive/ChunkFive-webfont.ttf") format("truetype"),
url("../fonts/ChunkFive/ChunkFive-webfont.svg") format("svg");
}
Here is the 404 resource not found message I get for each font:
Request URL:http://thedanbarrett.heroku.com/fonts/ChunkFive/ChunkFive-webfont.woff
Request Method:GET
Status Code:404 Not Found
Request Headers
Referer:http://thedanbarrett.heroku.com/home
User-Agent:Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US) AppleWebKit/534.10
(KHTML,like Gecko) Chrome/8.0.552.224 Safari/534.10
Response Headers
Age:0
Connection:keep-alive
Content-Length:727
Content-Type:text/html
Date:Wed, 05 Jan 2011 15:25:21 GMT
Server:nginx/0.7.67
Via:1.1 varnish
X-Runtime:0.001344
X-Varnish:764492621
The strange thing is that it finds and loads stylesheets, icons, and images in the same root folder. Just to reiterate the fonts embed and work perfectly run from a local server, even on hosts that don't have the font installed.
I did find one reference online to someone that was having a similar issue who changed their config.ru and environment.rb files to make it friendly with Heroku, but I can't seem to find it.
Thanks in advance SO minions for all your help!
~Dan
So it turned out the root for resources was set to Public/Stylesheets so my path declaration in the font-face section was nonsensicalness. I took the easy out and moved the fonts under the stylesheets directory and everything works perfectly now!
Here's an example that is working on Heroku: http://www.arailsdemo.com/posts/12
Here is the corresponding stylesheet http://www.arailsdemo.com/stylesheets/application.css
I don't remember needing any configuration changes. Hopefully, it helps.
Fonts directory: app/assets/fonts/
Add the line below to production.rb
config.serve_static_assets = true
In your styles.css.scss
#font-face {
font-family: "mycustomfont";
src:url(asset_path("mycustomfont.eot"));
src:url(asset_path("mycustomfont.eot?#iefix")) format("embedded-opentype"),
url(asset_path("mycustomfont.ttf")) format("truetype"),
url(asset_path("mycustomfont.svg#mycustomfont")) format("svg"),
url(asset_path("mycustomfont.woff")) format("woff");
font-weight: normal;
font-style: normal;
}
Environment: Rails 4.0.1 Ruby 2.0.0-p247
It should work on heroku :)

Resources