Nick
Nick

Reputation: 169

How do I Inject a JavaScript variable into Ruby code using HAML?

I am trying to inject the filename JavaScript variable into my Ruby code like this:

"#{ajax_download_report_url(" + filename+ ")}"

It's a basic route URL but I need to pass this variable in HAML because I get it from this Ajax request:

:javascript
        var updaterId = setInterval(function() {
          $.ajax({
            url: #{admin_reports_url.to_json},
            dataType: "json",
            type:  "GET",
            data: {job_id: "#{job_id}"},
            success: function(response){
              var filename = response.file;
              switch(status) {
                case 'failed':
                  $('.loader').hide();
                  clearInterval(updaterId);
                  alert(message);
                  break;
                case 'completed':
                  $('.loader').hide();
                  clearInterval(updaterId);
                  location.href = "#{ajax_download_report_admin_reports_url(" + filename+ ")}";
                  break;
              }
            }
          })}, 1000);

Now I have an error:

ActionController::RoutingError - No route matches 
{:controller=>"admin/reports", :action=>"ajax_download_report", :file=>" + filename+ "}

which means that HAML can't properly evalute this code.

Upvotes: 1

Views: 1374

Answers (4)

the Tin Man
the Tin Man

Reputation: 160621

This:

ajax_download_report_admin_reports_url(" + filename+ ")

is going to call a method in Ruby with a parameter of:

" + filename+ "

Which is why you see:

:file=>" + filename+ "

JavaScript is client-side running inside the browser, and can't touch the Ruby code on the server, so the JavaScript variable filename is invisible to Ruby and unreachable unless you send the value of filename back to the server somehow.


What I've done in the past, when I had a similar need, was to generate the URL and store it in a JavaScript variable definition, then use JavaScript string concatenation to insert the URL in the right place. Notice what this does:

File.dirname("http://foo.bar/baz/bor.html")
=> "http://foo.bar/baz"

It removes the resource name and leaves only the base URL. Using that:

:javascript
  var admin_reports_base_url = "#{ File.dirname(ajax_download_report_admin_reports_url('foo')) }/"
  var updaterId = setInterval(function() {
    $.ajax({
      url: #{admin_reports_url.to_json},
      dataType: "json",
      type:  "GET",
      data: {job_id: "#{job_id}"},
      success: function(response){
        var filename = response.file;
        switch(status) {
          case 'failed':
            $('.loader').hide();
            clearInterval(updaterId);
            alert(message);
            break;
          case 'completed':
            $('.loader').hide();
            clearInterval(updaterId);
            location.href = admin_reports_base_url + filename;
            break;
        }
      }
    })}, 1000);

Upvotes: 1

BvuRVKyUVlViVIc7
BvuRVKyUVlViVIc7

Reputation: 11821

"#{ajax_download_report_admin_reports_url('')}" + filename

Upvotes: 0

user946611
user946611

Reputation:

One solution would be to not use ruby code.

eg:

location.href = "admin/reports/ajax_download_report?file=" + filename;

Upvotes: 0

7stud
7stud

Reputation: 48649

def get_url(x)
   return "a url: #{x}"
end

filename = 'abcd'

puts "#{get_url(filename)}"

--output:--
a url: abcd

But you are trying to use a js variable called filename, which does not exist until after the page is sent to the browser and after an ajax call is made some time later, in some ruby code that is executing now. No can do.

Upvotes: 0

Related Questions