24

i'm new in Rails and in a controller i have:

class PagesController < ApplicationController
   def home
      @temp = "Hello"
   end
end

I have read that i must put the javascript code in application.js (tell me if true) and i have:

window.onload=function(){alert("<%= j @temp %>")}

Obviously that alert print the string "<%= j @temp %>" How can i pass the variable @temp to the javascript so that the alert can print Hello?

Thanks

Tom
  • 4,007
  • 24
  • 69
  • 105
  • Did either of these solutions work? – Powers Aug 11 '13 at 12:12
  • possible duplicate of [Ruby on Rails - Send JavaScript variable from controller to external Javascript asset file](http://stackoverflow.com/questions/2721880/ruby-on-rails-send-javascript-variable-from-controller-to-external-javascript), or http://stackoverflow.com/questions/2464966/passing-ruby-variables-to-javascript-function-in-rails-view if you don't require an external Js file. – Ciro Santilli OurBigBook.com Nov 11 '14 at 10:00

3 Answers3

65

I wrote an article on how to pass Ruby objects to the client. Ryan Bates also has an excellent RailsCast on passing data to JS.

Add a div to your view that corresponds to your the PagesControlle#home action that will not be visible when you load the page but will contain the data stored in the Ruby objects:

# views/pages_controllers/home.html.erb
<%= content_tag :div, class: "temp_information", data: {temp: @temp} do %>
<% end %>

Load the page with this div included and view the page source. You can see your Ruby objects stored in the .temp_information div. Open up the JavaScript console to access the Ruby objects as JavaScript objects:

$('.temp_information').data('temp')

You do not need to add your JS to a JS partial, you can also use the asset pipeline.

Powers
  • 18,150
  • 10
  • 103
  • 108
5

I do something similar to, but simpler than gon. I have the following in my ApplicationController.

def javascript_variables(variables)
  @javascript_variables ||= {}
  @javascript_variables.merge!(variables)
end

Within a controller action I can then do something like

def some_action
  javascript_variables(user: current_user)
end

In my ApplicationHelper I have something like this

def javascript_variables(variables = nil)
  @javascript_variables ||= {}
  @javascript_variables.merge!(variables) and return if !variables.nil?

  output  = ''
  padding = @javascript_variables.keys.group_by(&:size).max.first

  @javascript_variables.each do |variable, value|
    output << "#{variable.to_s.ljust(padding)} = #{value.to_json},\n          "
  end

  raw "var " + output.strip.html_safe.gsub(/\,\Z/m, ';')
end

and finally in my layout's <head> I have

<script>
  <%= javascript_variables %>
</script>

This gives me something like this (from a real example in my application)

<script>
  var pageModule        = "site/index",
      isCustomer        = false,
      utype             = "normal",
      isAnonymous       = true,
      keyboardShortcuts = false,
      pubnub            = null,
      requestToken      = "3zj974w074ftria3j";
</script>
deefour
  • 34,974
  • 7
  • 97
  • 90
  • Is that possible that this method makes the website more vulnerable to attack – dotcomXY Aug 10 '13 at 14:36
  • 1
    I'm not sure if this is a question, or a statement, so I'm not sure how to respond. – deefour Aug 10 '13 at 15:09
  • 3
    You shouldn't create so many global variables. Instead create a single object and store values as its properties. – Juliusz Gonera Mar 05 '14 at 07:32
  • Your approach is great but you helper's code leads to errors if there are no javascript variables that was passed from controller. The correct code is `@javascript_variables ||= {} \n @javascript_variables.merge!(variables) if !variables.nil? \n return if @javascript_variables == {}` I have used `\n` just to split code lines in comment. – zavg Mar 26 '15 at 18:06
0

Take a look at this.

http://tech.thereq.com/post/17243732577/rails-3-using-link-to-remote-true-with-jquery-ujs

One of the easiest ways is to use js.erb file, where you can do ruby tags to access variables that you defined in the controller action.

You need to use a respond_to block in the controller action, specifying the action to be able to respond to javascript.

items_controller.rb

class ItemsController < ApplicationController

  def action
    respond_to do |format|
      format.js
      #format.html {}    #  These are for allowing other types of formats to be responded to.
      #format.json {}    #  But they are not necessary for using this js.erb way of doing things.
    end
  end

end

/views/items/action.js.erb

$(div).html('The cat has erased your page');
ahnbizcad
  • 10,491
  • 9
  • 59
  • 85