Access asset_host inside javascript for Rails? - ruby-on-rails

I have the following javascript (shortened for clarity):
$modal = $('<img src="/assets/loading.gif">');
$('body').append($modal);
But I am not sure how to access the asset_host within that javascript? Any suggestions? (I am trying to not use coffee script)

There are several options:
asset_path
If you're not accessing the file inside the asset pipeline (and consequently can use ERB code), you could use this:
$img = '<%=j image_tag asset_path("loading.gif)" %>'
$('body').append($img);
Gon
If you are accessing inside the asset pipeline (where you can only use pure JS), you'll have to pass the asset host variable to JS through HTML. Gon is a great way to do this:
#config/initializers/gon.rb
gon.push({asset_host: ActionController::Base.asset_host})
#app/views/layouts/application.html.erb
<%= include_gon %>
#app/assets/javascripts/application.js
$modal = $('<img src="' + gon.asset_host + '/assets/loading.gif">');
$('body').append($modal);
Got the asset_host reference from here

Related

Why my image doesn't load when using wicked_pdf_image_tag?

I'm creating a service to add a watermark to the top of a client pdf file. When I add it to the pdf source, the html text loads fine but not the image (a small square is shown instead).
Here some piece of my code:
add_online_signature_to_partner_quote_pdf_service.rb:
class AddOnlineSignatureToPartnerQuotePdfService
def initialize(quote)
#quote = quote
end
def call
pdf = CombinePDF.new
source = CombinePDF.parse(#quote.document.download, { allow_optional_content: true })
signature = CombinePDF.parse(generate_signature(#quote))
pdf << source
pdf << signature
update_quote_with_signature(#quote, pdf)
end
private
def generate_signature(quote)
project = quote.project
ac = ApplicationController.new
pdf = WickedPdf.new.pdf_from_string(
ac.render_to_string(
template: "advanced_admin/quotes/form/_partner_quote_signature.pdf.erb",
layout: "pdf.html",
locals: { quote: quote, project: project, pdf: true }
)
)
end
def update_quote_with_signature(quote, pdf)
quote.document.attach(
io: StringIO.new(pdf.to_pdf),
filename: "quote_complete.pdf",
content_type: "application/pdf"
)
end
end
_partner_quote_signature.pdf.erb:
<div>
<h1>my title</h1>
<%= wicked_pdf_image_tag "logo-blue.png" %>
<p>my paragraph</p>
</div>
The image I want to generate within my PDF is classically located in my asset pipeline app/assets/images/logo-blue.png
I tried a lot of different syntaxes I saw on other topics but nothing seems to work... The 'wkhtmltopdf-binary' gem version is 0.12.6.5
Do you have an idea how I could make my code working? Thanks a lot!
As they said in the documentation :
The wkhtmltopdf binary is run outside of your Rails application; therefore, your normal layouts will not work. If you plan to use any CSS, JavaScript, or image files, you must modify your layout so that you provide an absolute reference to these files. The best option for Rails without the asset pipeline is to use the wicked_pdf_stylesheet_link_tag, wicked_pdf_image_tag, and wicked_pdf_javascript_include_tag helpers or to go straight to a CDN (Content Delivery Network) for popular libraries such as jQuery.
Using wicked_pdf_helpers with asset pipeline raises Asset names passed to helpers should not include the "/assets/" prefix. error. To work around this, you can use wicked_pdf_asset_base64 with the normal Rails helpers, but be aware that this will base64 encode your content and inline it in the page. This is very quick for small assets, but large ones can take a long time.
So you can do it like this :
<%= image_tag wicked_pdf_asset_base64("logo-blue.png"), height: 300 %>

Rails path-helpers doesn't work in js.coffee.erb

In my Rails 3.2 app (Ruby 1.9) I get following error when using path helpers in Coffeescript.
undefined local variable or method `new_user_session_path'
In my partial _usermenu.html.haml that works fine:
= link_to t('user.login'), new_user_session_path
In my app/assets/javascripts/metamenu.js.coffee.erb that throws above error:
$.get("<%= new_user_session_path %>")
Isn't it possible to use x_path and x_url helpers in coffeescript erb's?
This is because you are not within the view context inside of your assets. Adding an erb extension to the file doesn't change this, it simply allows you to evaluate embedded ruby.
If this is a one-off scenario, your best bet is to simply use the string itself.
$.get("/sign_in")
If you really wanted to you could create a partial that output a script tag that output your helper methods into js variables and access them that way.
# in your layout
<%= render 'url_helpers' %>
# in app/views/layouts/_url_helpers.html.erb
<script>
window.new_user_session_path = "<%= new_user_session_path %>";
# add more if necessary
</script>
# in your coffeescript
$.get(#new_user_session_path)
Also worth keeping in mind that this will obviously never work for member routes where your passing an instance of a model to the url helper as that is definitely not available to coffeescript. Remember, in production assets are precompiled so you can't use anything dynamic. For that you can only really rely on setting up actions in your controller to respond to JS calls.
Old post, but still accessible from Google.
In rails 4 (and certainly at least 3 too) you can use the route helpers to insert your js files easily:
assets/javascript/my_file.js.coffee.erb
<% self.class.include Rails.application.routes.url_helpers %>
window.index_route = '<%= index_path %>'

How does one minify a javascript partial within a rails erb file?

The application is not using the standard asset pipeline due to having some of the javascript being rendered dynamically by controller variables.
I'd like to minify the js before appending/inline-ing it into the html file that it would be served out from.
I've tried <render :partial => 'javascript.js'> which is the standard way to render a partial in an erb.
Ideally i'd just be able to do <render :partial => Minify.new.minify('javascript.js')> to render out a minified version of the js
You can try the uglifier gem (http://rubygems.org/gems/uglifier), I don't know about the performance, but you can do something like:
<script type="text/javascript">
<%= raw Uglifier.new.compile(render "your_js_in_a_partial.js") %>
<script>

Rails 3.1: Trouble on displaying images in mailer view files

I am using Ruby on Rails 3.1 and I would like to add my web site logo (that is, an image handled through the new Asset Pipeline) to an e-mail.
If in my mailer view file I state the following:
<% # Note: '#root_url' is my application hostname (eg: http://www.mysite.com) %>
<%= link_to image_tag( "#{#root_url.to_s}/images/logo.png"), #root_url.to_s %>
it doesn't work in production mode (that is, I cannot display the logo image) because I think the Asset Pipeline uses the Fingerprinting technique and in the received e-mail it doesn't. Inspecting the HTML logo element in the e-mail I get something like this:
<img src="http://www.mysitecom/images/logo.png"> # without Fingerprinting
How can I solve the problem?
In my production.rb file I have the following commented out code:
# Enable serving of images, stylesheets, and javascripts from an asset server
# config.action_controller.asset_host = "http://assets.example.com"
in config/environments/production.rb (and other enviroment files needed) add:
config.action_mailer.asset_host = 'http://mysite.com'
after that rails will automatically add hostname in front of paths generated by image_tag
# haml
= image_tag 'foo.jpg'
will become
#html
<img alt="" src="http://mysite.com/assets/foo.jpg" >
...same apply for image_path
#haml
%table#backgroundTable{background: image_path('email-background.jpg'), width: '100%', :border => "0", :cellpadding => "0", :cellspacing => "0"}
will become
<table background="http://mysite.com/assets/email-background.jpg" border="0" cellpadding="0" cellspacing="0" id="backgroundTable" width="100%">
watch out!!!
# this will make your emails display images
config.action_mailer.asset_host = 'http://mysite.com'
is different than
# this wont make your email images work
config.action_controller.asset_host = "http://mysite.com"
All of these answers are assuming you're using the asset pipeline, but from your example, you're specifying an image in /public/images - this is not part of the asset pipeline, so all the asset_path based answers won't work, and further your initial fingerprinting supposition is incorrect.
If you put an image in /public/images, you want your image tag to have a src of http://yoursite.com/images/the-image.jpeg, no fingerprint, no asset path, nothing - just hard-code it into your view:
<img src="<%=#root_url%>/images/logo.png">
But, you have to actually have the file in that location! If you have your image in /app/assets/images, then you'll need to use image_tag and the asset pipeline as others have answered.
An alternative is to include the image logo in the mail. The mail could also be viewed offline. You can add the logo in you Mailer class, with the following code..
attachments["your_logo.png"] = File.read("#{Rails.root}/assets/images/your_logo.png")
This code will include your image to the mail. I believe when you want to show your attachment in the mail you need to do the following:
Class YourMailer < ActionMailer::Base
def sendmail
.....
attachments.inline['your_logo.png'] = File.read("#{Rails.root}/assets/images/your_logo.png")
end
And in your sendmail.html.erb view you can use the image_tag method:
<%= image_tag attachments['your_logo.png'].url %>
note: if the mail does not get shown correctly you can alternatively try the solution at:
Rails attachments inline are not shown correctly in gmail
Your mail can then also be viewed offline correctly.
Have you tried adding something like this
config.action_mailer.default_url_options = { :host => 'www.example.com' }
to your config/enviroments/production.rb file
Try:
<%= link_to image_tag( "#{#root_url.to_s}/assets/logo.png"), #root_url.to_s %>
You're giving image_tag an absolute url so it thinks it doesn't need to do any fingerprinting or anything else other than regurgitate the string you gave it. I would try
link_to( image_tag('logo.png'), #root_url)
You'll also need to set actioncontroller's asset host to get rails to generate a full url for the image rather than just a path
One caveat to note: if you change the image then the fingerprint will obviously change and so the inage URL in all of your previously sent emails will become invalid. You may wish to consider inline images, although obviously these increase the email size
Try out this one
<%= link_to image_tag( asset_path, 'logo.png'), #root_url.to_s %>
Adding mode:'rb' worked for me:
attachments.inline['Logo.jpg'] = File.read(File.join(Rails.root,'app','assets','images','Logo.jpg'), mode: 'rb')
If you compile your assets:
RAILS_ENV=production bundle exec rake assets:precompile
and use asset_path in your view:
<%= link_to image_tag( asset_path('logo.png') ), #root_url.to_s %>
--it should work in both development and production. This is the way I do it my views, and .css.scss.erb stylesheets. I assume that it doesn't make a difference that it is a view for a mailer.
make sure your html page have follwing header
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd">
and render image as:
<%= image_tag('http://'+#url+'/images/header.jpg')%>
or
if you want link to image then
<%= link_to image_tag('http://'+#url+'/images/header.jpg'),root_path %>
#url = 'your website address'

Embedding an ejs template inside of an erb template

I'm building a javascript-heavy rails 3 app. It uses underscore.js, which has a very elegant templating mechanism built on top of ejs ( http://embeddedjs.com/).
The problem: embeddedjs borrows heavily from the erb syntax, so including ejs templates in an erb template causes rendering problems with the view.
Is there a way to include "non-erb" sections in an erb file? This would let me define ejs templates inside erb files. Right now I'm using a hack where I have a helper that reads the raw contents of a file containing ejs templates, and outputting that as a raw string in the erb template.
I use this trick to solve the problem:
// Using custom tags to be able to use regular for templates in templates
var ejs = require('ejs');
ejs.open = '{{';
ejs.close = '}}';
// Using html extension for custom ejs tags
app.register('.html', ejs);
app.set('views', __dirname + '/views');
app.set('view engine', 'html');
This changes <% %> to {{ }}, and let me use <% %> for templates which are used by JS. This works for me as I don't have classic style templates (<% %>).
If you have a lot of those you may want to do the same trick but for underscore.js templates.
You could save ejs as a seperate file and than render it as a text (which won't be evaluated as erb) inside script tag.
Inside your erb partial:
<script id="my_awesome_template" type="text/x-ejs">
<%= render :text => File.open("app/views/controller_name/_my_awesome_template.html.ejs").read %>
</script>`
In your JavaScript file:
new EJS({element: document.getElementById('my_awesome_template')}).render(data)
Escape your Underscore variables: (The ones you do not want erb to interpolate)
<%= foo %> becomes:
<%%= foo %>

Resources