Ruby on Rails - Send JavaScript variable from controller to external Javascript asset file

Yes, you can!

Rewrite your JS code into function with one argument (timelimit) and put it into some external file. Then you can call the function from view and pass that @timeleft variable as JS function argument.

Short example:

#controller
@time_left = Time.now.to_i - 3.hours.to_i

.

#javascript
function count_down(time_left) {
  $('#countdown').countdown(time_left)
}

.

#view
<%=javascript_tag "count_down(#{@time_left})" -%>

javascript_tag

Example not tested, it is only idea not complete solution. Don't forget to load that JS file. You can use other JS rails helper javascript_include_tag.


retro's technique of using a function parameter is a possibility, but you have to properly escape the variable you are passing with either escape_javascript or to_json + html_safe as explained below.

However, since you want to affect external files, the best techniques will be to use gon. Another good possibility is to use data- attributes.

gon

Gem specialized for the job: https://github.com/gazay/gon

Probably the most robust solution.

Gemfile:

gem 'gon'

Controller:

gon.timeleft = 1

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

<html>
<head>
  <meta charset="utf-8"/>
  <%= include_gon %>
  <%= javascript_include_tag 'application' %>

Asset file:

gon.timeleft === 1

data- attributes

Add values to attributes, retrieve them with JavaScript DOM operations.

Sometimes called "unobtrusive Javascript".

View head:

<%= javascript_include_tag 'application' %>

View body:

<%= content_tag 'div', '', id: 'data', data: {timeleft: '1'} %>

Asset file:

$(function() {
  parseInt($('#data').data('key1')) === 1
})

The following illustrate how escape_javascript and to_json work for you to use on top of retro's answer.

escape_javascript

Alias: j.

Works only on strings.

Escapes characters that can have special meanings in JavaScript strings, like backslash escapes, into a format suitable to put inside JavaScript string literal quotes.

Maintains html_safe status of input, so needs html_safe otherwise special HTML chars like < would get escaped into &lt;.

<% a = "\\n<" %>
<%= javascript_tag do %>
  f('<%= j(a)           %>') // === '\\n&lt;'
  f('<%= j(a).html_safe %>') // === '\\n<'
<% end %>

to_json + html_safe

Works because JSON is almost a subset of Javascript object literal notation.

Works not only on hash objects, but also on strings, arrays and integers which are converted to JSON fragments of the corresponding data type.

<% data = { key1: 'val1', key2: 'val2' } %>
<%= javascript_tag do %>
  var data = <%= data.to_json.html_safe %>
  f(data.key1) \\ === 'val1'
  f(data.key2) \\ === 'val2'
<% end %>