I'm working on a rails app (4.1.8) that requires a lot of javascript in my show view, and I need a way to access data returned from ActiveRecord within the actual js file
Here's an example:
My Show controller
def show
@user = User.find(params[:id])
end
now i need to access this data in my show javascript, but this is the only way i could do it:
My Show view
<%= javascript_tag do %>
var myEmail = "<%= j @user.email %>";
// do stuff with myEmail
<% end %>
My question is, is there a way I can render this javascript or include it in a separate script tag while maintaining the userdata? I don't want to have to write hundreds of lines of jQuery and js inside this javascript_tag and it's painful to debug. Everything I've tried so far (putting it in the asset pipeline, rendering a seperate .js.erb file) just turns myEmail into a string with the ruby statement inside it. Any ideas? Thanks in advance!
03-02-2016 21:10: Alright, got a working example - Dibbz to Sergio Tulentsev - he was right, parsing to valid JSON isn't even required, when calling .to_json
on a ruby object it will print a valid JS object literal instead. Here is the github repo with working examples, if you'd like to clone it and use the code - feel free and have a nice day! (examples are built with Rails)
Aside from Øle Bjarnstroem's answer which implies the use of AJAX, if you want to use a model in JS you could do something like this
<% javascript_tag do %>
var user = <%= @user.to_json %>;
<% end %>
Now the JS variable user
holds all the properties that the model has as well since it simply converts the ruby object to JSON directly to a JS object.
to_json
As for not having to write the JS, you could create a helper for it - this would still inject the JS into your page but you could just supply an object as an argument to this function and then simply output that in your code with 1 call instead of doing the javascript_tag do ... end
construct.
There are multiple ways to go about with this, you could use Rails' content_for
to set and get content that will be rendered in your head.
e.g.
helper
module myHelper
def obj_as_js_var(var_name, obj, content_name = nil)
output_tag = javascript_tag("var #{var_name} = #{obj.to_json};".html_safe, type: 'text/javascript')
# if content_name is set, use content_for instead of directly printing the tag inline
if content_name
content_for content_name, output_tag
else
output_tag
end
end
end
Now when using this helper in your view
view
<%= obj_as_js_var('user', @user) %>
# ... rest of page
Will render the same output on a single line, the first argument ('user'
in this case) is the name the variable will have, the second argument (@user
) will be converted to JSON.
But wait a moment... what If I want it in the <head>
of the document?
Well, the helper has an optional third argument which, if supplied will return the value of content_for
and it will set the tag in the content.
So if, in your layout.erb you have something like
layout
<head>
<!-- ... snipped -->
<%= content_for :javascript if content_for? :javascript %>
</head>
You could use the following in your view instead (notice we're not rendering anything with <%=
but using <%
instead as we're saving the content for use in the <head>
)
<% obj_as_js_var('user', @user, :javascript) %>
Now, the content_for :javascript
in the head of your layout will render the output there, always. Note that if the content_for :javascript
is loaded after the application.js then you won't have the data available there!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With