I have a question about using asset_sync and a Heroku CDN. In this article, it says
Make sure you’re using the Rails AssetTagHelper methods (like
image_tag). This will ensure all of your assets will reference the new
asset host.
Does that mean any plain html <img> tags or refs in my app won't work? Or maybe it's just to warn against tags with an absolute URL?
EDIT: I know I can and should use image_tag and image_path in views or css. What I'm asking is, do I HAVE to?
They will work but you will need to point it manually to where you are syncing your assets to, some bucket on Amazon S3. Not really recommended unless your assets will hardly ever change.
You configure your asset path in your production.rb config like so:
config.action_controller.asset_host = "http://assets.domain.com"
Then whenever you reference asset_path it will point to the asset on the host defined in your environment config.
Perhaps a solution (without understanding your exact problem) would be to do something like this:
<img src="<%= asset_path("image.png") %>" />
You should to use
<%= image_path("logo.png") %>
instead of
<img src="<%= asset_path("image.png") %>" />
You can more details about this helper method here. Also As specified by andrew you need to specify asset_host in you config file. Here is a small blogpost for the same
Also:
If you want to pull css background icons/images from amazon s3 then use:
background-image: image_url("icon.png"); // it requires scss extension ie saas and also you must has saas rails gem included.
When I try to use asset_url in my view (Rails 3.2), I get a NoMethodError.
What do have to do to be able to use AssetUrlHelper's methods in my views?
To explain this a bit better and maybe find an alternative solutions: I need to get an "asset link" to file attachments created with carrierwave.
My model has an attachment which points to a file in my assets directory. I need to draw a link to this file.
= link_to model.name, model.attachment(:size)
gives me /myfiles/model/id/attachment/size.png (which is what is persisted by carrierwave)
= image_tag model.attachment(:size)
gives me the wanted http://static_host.com/.../size.png
but I have no need for an image tag, but the plain link to the file at the asset host.
The following works ok for me:
<%= link_to "link to asset", asset_path(article.image.url) %>
I'm using paperclip but I doubt it makes much difference
I think the helper asset_path belongs to asset files (like .css and .js) , not views. In views is proper to be used helpers like image_tag or stylesheet_include_tag. This is the idea behind the asset-pipeline - to ease reference to assets.
Instead of having the page include a style tag with a link where to get the css from, which I could add to my view using rails' stylesheet_link_tag helper method, I want to have the css inline directly inside the page.
This is what I came up with so far:
%style(type="text/css")=File.read(physical_asset_path("email.css"))
But I can't find any rails' helper method which gives me the physical path of an asset - physical_asset_path is just a dummy method invented by me.
Anybody knows how to get the physical path of an asset when using rails 3.2.x?
Is there an easier/ better way to get stylesheets - from css files inside the common rails assets paths - inline?
Use case: most email clients don't access external sources (like css, images) without user confirmation. So to get the emails properly displayed I need to embed the CSS inside the emails' HTML.
Rails.application.assets.find_asset('email').to_s will return the compiled asset as a string.
Use premailer or premailer-rails3
https://github.com/fphilipe/premailer-rails3
or
https://github.com/alexdunae/premailer
Joe's Nerd Party say:
We also used the Premailer gem to automatically inline the linked
stylesheet in the email views. Our email layout looks something like:
%html
%head
= stylesheet_link_tag 'email'
%style{:type => "text/css"}
:sass
#media all and (max-width: 480px)
table#container
width: auto !important
max-width: 600px !important
... and so on for the mobile code
%body
Email body here.
%table
Lots of tables.
We include a stylesheet in the HTML. Premailer downloads it, processes
it, and inserts the css rules inline in the HTML.
The #media rules need to be inline in the email layout, since
Premailer can’t handle those being in a separate css file yet.
We use premailer-rails3 to integrate Premailer into Rails 3.
Unfortunately, we found a bunch of bugs in premailer and
premailer-rails3. Our forks of the projects are at
https://github.com/joevandyk/premailer and
https://github.com/joevandyk/premailer-rails3. The forks fix some
encoding bugs, remove some weird css processing stuff done by
premailer-rails3, allow premailer to not strip out embedded
rules in the email layouts, and some other things.
We also found a bug in sass-rails, where you can’t embed image-urls in
inline sass code. See https://github.com/rails/sass-rails/issues/71
Premailer-rails3 hooks into ActionMailer when the email actually being
delivered, not just generated. When running tests, email is not
actually sent, so the premailer-rails3 hooks don’t get ran during
tests. I haven’t spent the time to see if it’s possible to get the
premailer processing to run during tests, but that would be a nice
thing to do.
Also, our forks on premailer-rails3 assume that you want premailer to
go out and actually download the linked CSS files. It should be
possible to use the Rails 3.1 asset pipeline to get the processed css
without downloading it. A very special thanks goes to Jordan Isip who
did the super annoying job of making sure the emails look great in all
the different clients out there. Writing that CSS/HTML did not look
fun.
Update:
Roadie appears to be a better option. Thanks to Seth Bro for pointing it out.
(Sorry this answer is in html, not HAML… but that shouldn't be a problem for HAML fans)
I found this question when looking for a way to inline Sass compiled as css into html for creating html email templates.
Combining the above advice, I used the following code in the head of my html page:
<style type="text/css">
<%= Rails.application.assets['path/to/sass/file'].to_s.html_safe %>
</style>
This code compiles Sass as CSS and then inserts the css into a <style> tag. The html_safe ensures that any quotes (' and ") or angle brackets (> and <) used in the css are not escaped.
The path/to/sass/file is the same as you would use when creating a stylesheet link tag:
<%= stylesheet_link_tag 'path/to/sass/file', :media => 'all' %>
Rails.application.assets['asset.js'] will work only in local environment, as rails asset compilation is disabled in both production and staging environment.
Rails.application.assets_manifest.find_sources('asset.js').first.to_s.html_safe should be used to inline css when using rails asset pipeline.
Can't add comment to Seth Bro's answer. You better use #[] instead of #find_asset:
Rails.application.assets["email"].to_s.
Re "asset will not be compressed". It's not true. It will be compressed if you have compressors enabled (in rails config):
Rails.application.configure do
# ...
config.assets.css_compressor = :sass
config.assets.js_compressor = :uglify
end
Notice, that by default this is enabled in production environment (config/environments/production.rb).
Had the same problem, solved it using #phlegx's answer to a similar issue in Premailer.
For an environment-safe solution you need to use
(Rails.application.assets || ::Sprockets::Railtie.build_environment(Rails.application)).find_asset('email.css').to_s
I've packaged it into a helper in my app:
# app/helpers/application_helper.rb
# Returns the contents of the compiled asset (CSS, JS, etc) or an empty string
def asset_body(name)
(Rails.application.assets || ::Sprockets::Railtie.build_environment(Rails.application)).find_asset(name).to_s
end
I was trying to inline css for use in google amp compatible pages with rails. I found the following helper from vyachkonovalov which was the only thing for me working in production and locally.
Add the following to the erb template:
<style amp-custom>
<%= asset_to_string('application.css').html_safe %>
</style>
And the helper to ApplicationHelper. It works perfectly locally and in production.
module ApplicationHelper
def asset_to_string(name)
app = Rails.application
if Rails.configuration.assets.compile
app.assets.find_asset(name).to_s
else
controller.view_context.render(file: File.join('public/assets', app.assets_manifest.assets[name]))
end
end
tl;dr (without Roadie):
%style(type="text/css")
= render template: '../assets/stylesheets/email_responsive.css'
For actually applying the CSS as inline styles, I recommend roadie-rails (which is a Rails wrapper for Roadie). It also has other neat features like absolutizing hrefs, srcs etc.
A usage combining both inlined (email.scss) and non-inlined (email_responsive.css) stylesheets, both residing in app/assets/stylesheets:
-# This will be inlined and applied to HTML elements.
-# Note that you need to include this in your asset config, e.g.:
-# Rails.application.config.assets.precompile += %w(... email.css)
-# (You need to list it as `email.css` even if it's actually `email.scss`.)
= stylesheet_link_tag 'email'
-# E.g. for media queries which can't be inlined - yeah, some iOS devices support them.
-# This will not be inlined and will be included as is (thanks to `data-roadie-ignore`).
-# `template:` marks it as a full template rather than a partial and disables `_` prefix.
-# We need to add the extension (`.css`) since it's non-standard for a view.
%style(type="text/css" data-roadie-ignore)
= render template: '../assets/stylesheets/email_responsive.css'
You can use this:
Rails.root.join('public', ActionController::Base.helpers.asset_path("email.css")[1..-1]).read.html_safe
In Rails, when we include an image into the page we use image_tag helper, which generates <img> tag and adds ?nnnnn at the end of its url, so that every time an image is updated the old version would not be stuck in the cache on the client side. Same thing for SASS needed, but I can't find it in the documentation.
You should be using helpers provided by sass-rails gem https://github.com/rails/sass-rails, (scroll to Asset Helpers).
These helpers can be used from inside sass files any time you need to reference an asset (image/audio/video/font)
body{
background: asset_path($relative-asset-path, $asset-class);
}
Note: image_url("...") is not working on Rails 3.1.0.rc4 due to a bug, but you can still use asset_url and asset_path.
Using stylesheet_link_tag will do this for you, just the same as image_tag does. This also applies to JavaScript files linked in with javascript_include_tag.
I set up facebooker to tunnel my Ruby on Rails application.
The issue is that I would like to test locally. That is, I don't want to have to start a tunnel every time I want to see my changes.
Right now, when I start the application using ruby script/server (not calling rake facebooker:tunnel:background_start beforehand), links created by helpers (e.g., stylesheet_link_tag, javascript_include_tag, image_tag) are prepended with my tunnlr address: http://web1.tunnlr.com:myPort/. (For example, a CSS link looks like this in the page source: http://web1.tunnlr.com:myPort//stylesheets/appName.css?1234567890.)
I don't want that functionality; I can't see my CSS or JavaScript changes without having to start the tunnel first. I want the links to be relative, not absolute. So, stylesheet_link_tag should produce /stylesheets/appName.css?1234567890.
Does anyone know why it's doing that in the first place and how to fix it?
Thanks in advance.
The AssetTagHelper uses your asset_host URL. I am not sure whether facebooker is setting it for you (I don't know much about facebooker), but you can reset it in your view no problem:
Before your stylesheet_link_tab just override the host URL:
ActionController::Base.asset_host = "localhost:3000"
# or
ActionController::Base.asset_host = ""
So using ERB it might look like this:
<% ActionController::Base.asset_host = "" %>
<%= stylesheet_link_tag "stylesheet.css" %>
Walabing!