28

I would like to use some erb in my .coffee files, like the following example

myLatlng: new google.maps.LatLng(<%=@location.latitude %>, <%=@location.longitude %>)

I renamed my locations.js.coffee to locations.erb.coffee

but I still get the following error

Error compiling asset application.js:
ExecJS::ProgramError: Error: Parse error on line 4: Unexpected 'COMPARE'
  (in /Users/denisjacquemin/Documents/code/projects/geolog/app/assets/javascripts/locations.erb.coffee)
Served asset /application.js - 500 Internal Server Error
denisjacquemin
  • 7,414
  • 10
  • 55
  • 72

5 Answers5

76

If you want erb in the .coffee files IN YOUR VIEW folder, leave your file named as yourfilename.js.coffee, and Rails will still process the ERB, oddly enough.

To make it work in Heroku, move coffee-rails out of the assets group in your Gemfile.

Arcolye
  • 6,968
  • 4
  • 34
  • 28
  • Very interesting. Would not have expected that result at all. – John Mar 04 '12 at 07:49
  • 1
    It would be nice to find this feature documented somewhere to prevent all us from finding at some point that it was actually a bug... – opsidao Jun 29 '12 at 12:33
  • 4
    Just tried it in Rails 3.2.6 and it didn't work. Had to rename `locations.js.coffee` to `locations.js.coffee.erb` – Brian Armstrong Jul 04 '12 at 21:19
  • weird adding .erb to location.js.coffee.erb in my view file doesn't work but getting rid of the .erb does. – shicholas Jan 09 '13 at 21:59
  • 5
    I'm on 3.2.12 and .js.coffee.erb files don't work. I have to rename them .js.coffee and they work -- even though they have erb. Go figure. – Tom Rossi Mar 01 '13 at 16:40
  • I'm on Rails 4.2.0 and it works. Seems Rails can only use one handler for template instead of a pipeline of handlers. If someone still have `ActionView::Template::Error` I suggest to check if your indentation is correct. – darkbaby123 Jan 12 '15 at 07:35
13

You may have to rename your file to locations.coffee.erb so erb is processed before coffee :)

Clément
  • 1,399
  • 13
  • 19
  • In your error, coffee script tries to execute the erb tag "<% ..." – Clément Jun 28 '11 at 10:12
  • 1
    full explanation could be found here http://ryanbigg.com/guides/asset_pipeline.html#preprocessing – denisjacquemin Jun 28 '11 at 12:49
  • I tried to do this in my `file.coffee.js.erb`, but it didn't work and leads to compilation error `emailRegex = <%= Devise.email_regexp %>` – Vipin Verma Mar 18 '16 at 07:58
  • The provided link in the comment made by @denisjacquemin seems to be returning a 404. However, I found the rails documentation on the preprocessing of the asset pipeline to be a good explanation as to how rails preprocesses file extensions and in what order: https://guides.rubyonrails.org/asset_pipeline.html#preprocessing. `Additional layers of preprocessing can be requested by adding other extensions, where each extension is processed in a right-to-left manner. These should be used in the order the processing should be applied.` - – Nappstir Apr 05 '19 at 20:10
5

Stick to the asset pipeline when possible in Rails 4, instead of using a js.erb view.

Pass variables to the Js using gon or some other technique discussed at: Ruby on Rails - Send JavaScript variable from controller to external Javascript asset file

With gon:

app/views/layouts/application.html.erb:

<head>
  <meta charset="utf-8"/>
  <%= include_gon %>

app/controllers/application_controller.rb:

before_filter do
  gon.latitude = 0.1
  gon.longitude = 0.2
end

app/assets/javascripts/locations.js.coffee:

myLatlng: new google.maps.LatLng(gon.latitude, gon.longitude)

This method is faster because file is precompiled only once at startup, gets served by the server instead of through Rails, and on the same HTTP request as the rest of the Js.

Community
  • 1
  • 1
Ciro Santilli OurBigBook.com
  • 347,512
  • 102
  • 1,199
  • 985
3

In Rails 3.2.8, I didn't have to move my .coffee file to /app/views. I just added .erb to the filename and left it in /app/assets/javascripts. Ie. I changed

/app/assets/javascripts/user_answers.coffee.js to 
/app/assets/javascripts/user_answers.coffee.js.erb

and then this worked:

# Note the level of indentation.
var x = 2;

<% Question.first(2).each do |eq| %>
alert('eq: ' + <%= eq.id %>)
<% end %>

(The indentation level has to match in CoffeeScript, not Ruby.) Enjoy your coffee embedded in rubies.

David Beckwith
  • 2,679
  • 1
  • 17
  • 11
  • yet that didn't work anymore for me once I deployed onto heroku. But it did work fine on my machine. Any further ideas? – zabumba May 08 '13 at 00:32
  • I tried to do this in my `file.coffee.js.erb`, but it didn't work and leads to compilation error `emailRegex = <%= Devise.email_regexp %>` – Vipin Verma Mar 18 '16 at 07:58
1

I agree with Ciro Centelli to leave the asset pipeline alone, especially if you are using Heroku. No doubt gon is useful if you need to many assignments, but you can also do this without a gem. In your html include

<%= javascript_tag do %>
    window.latitude = <%=@location.latitude %>
    window.longitdue = <%= @location.longitude %>
<% end %>

and in your coffee file

myLatlng: new google.maps.LatLng(window.latitude, window.longitude)

You can often work around other needs in a similar fashion. For instance if you do not want the coffee script to trigger on an element with particular id, then in the html use erb to only add that id when you want it triggered.

Obromios
  • 15,408
  • 15
  • 72
  • 127