Acquire Asset Path from JavaScript - ruby-on-rails

I need to display images on an HTML5 canvas that are in the Rails asset pipeline, but I need to know the path for the asset from JavaScript. I'm using js-routes for other parts of the application, but it doesn't appear to provide a way to get the path to something in the asset pipeline.
What's the correct way to obtain the path to a Rails asset (e.g., an image) from JavaScript?

In the Rails Asset Pipeline guide, they give an example of coding assets in your stylesheets by preprocessing the stylesheets with ERB. You can use the same technique with JavaScript, assuming you tack an .erb to the end of the filename:
var someAssetPath = "<%= asset_path('some_image.png') %>";

Checkout the js_assets(Javascript helper in rails projects) gem.
I think it is precisely what you need.
From the documentation:
Get the path to the template app/assets/javascripts/rubrics/views/index.html in javascript:
var path = asset_path('rubrics/views/index.html')

Why not add a data attribute for the path inside an element in your .erb file and then retrieve that with JQuery?
inside some_template.html.erb
<%= content_tag(:div, "", id: 'some-id', data:{path_to_asset: asset_path("some_image.png")}) %>
then in some_javascript.js
var assetPath = $("#some-id").data("pathToAsset");

For those using HAML you can do:
:javascript
var assetPath = "#{asset_path('some_image.jpg')}";

I came across the same issue in Rails 4.1 and used referencing rails assets in coffeescript for images. No additional libraries needed.

In my case, I wanted to get the stylesheet path and the hash that rails generates for cache busting made it impossible to hardcode.
What ended up working quite well for me is to assign an ID to the main stylesheet link element in the html (layout) and then use javascript to extract the href. If you want the base asset path, perhaps create a generic element with the data you need as an attribute.
Rendered HTML
<link rel="stylesheet" href="mypath/main.css" type="text/css" id="main-css">
JS
$("#main-css").attr("href"); // "mypath/main.css"

Related

Rails image asset tag helper

In rails you can just a regular html img tag in your templates, what is the purpose of using an asset tag helper?
<%= image_tag "header.png" %>
vs.
<img src="header.png">
I think the image_tag also uses the asset path helpers. So it will automatically use '/assets/header.png'. Also if you have asset digest turned on I think it will automatically use '/assets/header-asdfasd.png' on production.
Actually, any image_tag would be transformed into HTML img tag.
I think Rails just provides some way to create HTML in Ruby/Rails way in case you are not a HTML guy, of course you can just use HTML img tag if you like.
Not only Rails, some other render utils, like Razor in C# , provide the similar feature.

CKEditor/vendor library: can it work when in vendor folder instead of public folder?

I have a working edit view to which I'm trying to add CKEditor. I've downloaded the CKEditor folder/files and placed them in my_app/vendor/assets/ckeditor/. I'm using Rails 4 and this folder is included in the asset pipeline. To application.js I've added //= require ckeditor.js and to application.css #import "contents";.
In my edit view I have (I'd like to use the inline option):
<%= f.text_area :page, contenteditable: 'true' %>
<script>
CKEDITOR.disableAutoInline = true;
CKEDITOR.inline( 'image_page' );
</script>
Problem: Now when loading the edit view, the text field is not displayed as an editable field but just as plain text. There's no way to edit this text and no sign of CKEditor. Any idea what I'm doing wrong?
The page's source code that is being generated, includes:
<textarea contenteditable="true" name="image[page]" id="image_page">
Arbor cubo vel.
</textarea>
<script>
CKEDITOR.disableAutoInline = true;
CKEDITOR.inline( 'image_page' );
</script>
Update: I got it working by moving the CKEditor files from the vendor folder to the public folder. Could someone perhaps confirm whether or not CKEditor is compatible with the asset pipeline?
I would prefer to place it in the vendor folder if anyway possible. This old post as well as this one refer to something similar (if I place <% var CKEDITOR_BASEPATH = '/ckeditor/'; %> as a header line in application.html.erb my app crashes with the error dynamic constant assignment '.freeze). Could someone with more experience with CKEditor provide a more definitive answer than these old posts?
Try adding the ckeditor assets under either vendor/assets/javascripts for the JavaScript files and vendor/assets/stylesheets for the CSS files (separate the ckeditor assets among those folders)
The whenever an asset is referring to another asset use the asset-url helper instead of url so that this asset is served through the asset pipeline
You also need to include all the assets that you'll put in vendor.... folders in the asset pipeline by //require or import
On a side not you can use the ckeditor gem https://github.com/galetahub/ckeditor it will save you a lot of time also it handles some features out of the box like images upload and gallery of ckeditor
May be the script is executing before the textarea is fully loaded on the DOM. Try to use a post load wrapper to your script like the jquery's:
$(function(){
// ... your code
})

Best way to display images from Rails Asset Pipeline using AngularJS?

I'm working on a Rails app with an Angular-driven frontend. I want to include images from my Rails asset folders into a view that is shown only shown in certain contexts using an ng-switch directive. I tried a couple of solutions, like typing the file path of all other (Rails-served) images into the src of the <img> tag. I also tried adding an erb suffix to the coffeescript file holding the angular controller and then doing this:
$scope.logoSrc = '<%= asset_path("images/logo_grey.png") %>'
and using an ng-src directive in the image tag, but that yielded a 404.
Happy to post more of my code if it's helpful. Thanks in advance for any help!
Try the following:
$scope.logoSrc = '<%= asset_path("logo_grey.png") %>'
According to the section 2.3.3 of the Rails Guides:
If you add an erb extension to a JavaScript asset, making it something such as application.js.erb, then you can use the asset_path helper in your JavaScript code:
$('#logo').attr({
src: "<%= asset_path('logo.png') %>"
});

Avoid *.js.erb files by building all the asset_path values

So I want to avoid processing JavaScript files with ERB just so I can get a proper asset path to, say, an image.
Currently, this seems like the popular approach:
var myImage = "<%= asset_path('my_image') %>";
Which, of course, requires the filename be changed to "*.erb" so that it'll be processed.
I'd much rather isolate the ERB ugliness to one point in my project making a single manifest file (say, "assets.js.erb") that computes and makes available all the asset paths my JavaScript needs.
I can certainly do it WETly by tackling it case-by-case:
ASSETS =
"my_image": "<%= asset_path('my_image') %>"
window.assetPath = (path) -> ASSETS[path]
But, I'd really rather just write some ERB to recurse through all of my asset_paths.asset_environment.paths and build a big object literal manifest for me, so that my real application JavaScript can confidently call:
var myImage = assetPath('my_image');
Any ideas on (1) if there's an easier way to do this that I missed, or (2) how I'd accomplish a search of all the potential valid arguments to asset_path?.
An easier way :
Get the assets prefix in your .js.erb : <%= Rails.configuration.assets.prefix %>. If an absolute path is needed, you can also get the application URL (it's more complicated to get it from rails, so you can just hardcode it in your .js.erb ?)
If you are working with precompiled assets, get the fingerprint of your file which is stored in manifest.yml (at <%= Rails.configuration.assets.manifest %>). The manifest contains a list with all your assets and their respective fingerprints (documentation)
Make assetPath just prepending the application URL + prefix to your image name or fingerprint
An inconvenient is that you have to specify the full image name (included the extension).
Old question, but there is nice way to accomplish this. Just to explain the context of my solution: I need to display markers in a map, which have different possible icons based on the JS dynamic variables. Strangely, using the <%= asset_path('" + somefunction(raw_value) + "') %> was not working. Then, I've looked for the solution bellow.
Concretely, the solution I am using has only one js.erb file which stores the values of the images, and their fingerprinted names, which can be get by a function, image_path. After that, all my other JS files can be free of the asset_path and, consequently, of the .erb
Create a file images.js.erb in your_application/app/assets/javascripts with the following content:
<%
imgs = {}
Dir.chdir("#{Rails.root}/app/assets/images/") do
imgs = Dir["**"].inject({}) {|h,f| h.merge! f => image_path(f)}
end
%>
window.image_path = function(name) {
return <%= imgs.to_json %>[name];
};
Require this file in your application.js, which is normally in the same directory as above:
//= require ...
//= require ...
//= require images
//= require_tree .
Then, inside the JS that you've been using <%= asset_path('image.png') %>, you will use instead image_path('image.png');
Credits to this blog post for posting a Coffee script version from which I've based mine.
It depends on the context of where this image is used.
Use Case 1: The image is decorative and needs to be dynamically swapped.
Example: Spinner, while data is loading.
In this case, I refer to is in my sass and java script.
.spinner
background-image: url(image_path("spinner.png"))
Then I would operate with classes in java script and not images.
$.addClass('spinner')
Use Case 2: Image is part of an object.
There are many situations, when an image actually belongs to a object. In this case, I create a json file, which stores the data and the image reference like this. Then I use erb to unwrap the image reference - my_object.json.erb:
{
"icon" : "<%=image_path("icons/my_icon.png")%>",
"label":"My label",
"description":"My description"
}
Use case 2 requires more work on javascript side to load the json files, but it opens very powerful extensibility options.
Asset pipeline handles both cases famously.

Rails with backbone-rails: asset helpers (image_path) in EJS files

I have a Rails 3.1 app that uses the codebrew/backbone-rails. In a .jst.ejs template, I would like to include an image, like so:
<img src="<%= image_path("foo.png") %>"/>
But of course the asset helpers are not available in JavaScript.
Chaining ERB (.jst.ejs.erb) does not work, because the EJS syntax conflicts with ERB.
Here is what I know:
The asset helpers are not available in the browser, so I need to run them on the server side.
I can work around the problem by making the server dump various asset paths into the HTML (through data attributes or <script> and JSON) and reading them back in JS, but this seems rather kludgy.
Is there a way to somehow use the asset helpers in EJS files?
There is a way, actually, to chain a .jst.ejs.erb file, although it's fairly undocumented, and I only found it through looking at the EJS test cases. You can tell EJS to use {{ }} (or [% %] or whatever else you want) instead of <% %>, and then ERB won't try to evaluate your EJS calls.
Make sure to require EJS somewhere in your code (I just included gem 'ejs' in my Gemfile), and then create an initializer (I called it ejs.rb) that includes the following:
EJS.evaluation_pattern = /\{\{([\s\S]+?)\}\}/
EJS.interpolation_pattern = /\{\{=([\s\S]+?)\}\}/
Then just make sure to rename your templates to .jst.ejs.erb, and replace your existing <% %> EJS-interpreted code with {{ }}. If you want to use something other than {{ }}, change the regular expressions in the initializer.
I wish there were an option in Sprockets to handle this through the config rather than having to explicitly include EJS, but as of the moment, there's no way to do that that I know of.
I can see two ways. Neither are great.
When you say <%%= variable %> then this is rendered by ERB as <%= variable %>, so you could double percent escape everything but the asset_tags and that would survive the trip through one ERB pass on the way to EJS.
If you find that too gross...
How about making a different javascript file, with an ERB extension, that defines your asset paths? And then use the asset pipeline to require that.
So say assets.js.erb defines something like:
MyAssets = {
'foo': <%= image_path("foo.png") %>,
...
}
And then require this somewhere near the top of your manifest. And then reference the globals however that works in EJS.
For those willing to try HAML instead of EJS: Using haml-coffee through haml_coffee_assets has worked well for me as well.
You can have the following in a .hamlc.erb file:
%img(src="<%= image_path('foo.png') %>")
(It still doesn't give you routing helpers though, only asset helpers.)
Ryan Fitzgerald was kind enough to post a gist of his JavaScript asset helpers (which get precompiled with ERB): https://gist.github.com/1406349
You can use corresponding Javascript helper via the following gem:
https://github.com/kavkaz/js_assets
Finally (after installing and configuring) you will be able to use it like this:
<img src="<%= asset_path("foo.png") %>"/>

Resources