As everyone knows the Rails framework advices for strict separation of JavaScript and Html via what’s called UJS, however sometimes, I find myself in the need to include impromptu snippets of JavaScripts in my Views. First of all, I would like to know if this is correct at all? Or is it frowned upon?
The most common case in which I find myself doing this, is when for example I have a condition block like this one:
= form_for @place do |f|
%h5 Address:
.input-prepend
%span{ :class => "add-on" }
%i{ :class => "icon-road" }
= f.text_field :address
%h5 Name:
.input-prepend
%span{ :class => "add-on" }
%i{ :class => "icon-pencil" }
= f.text_field :name
= f.hidden_field :latitude
= f.hidden_field :longitude
#post-button
%button{ :class => "btn btn-primary", :type => "submit" } Post it!
- unless logged_in?
:javascript
$('#post-button > button, .input-prepend input').addClass('disabled');
$('.input-prepend input').addClass('disabled');
$('.input-prepend input').attr('disabled', 'disabled');
new PopOver().setPopOver($('#post-button > button'), "You must be logged in to register your Business");
Take a look at the code nested within the unless condition, I wonder if it’s OK to have it there, or should I somehow generate that portion of code from a controller? (and pass it(render it)to the view: In which case I have no idea how to do it…)
Please let me know your thoughts, I need to know how the most experienced of Rails developers would handle these type of situations, so, If you are one I’d love to read your answer.
Thanks in advance!
PS. Oh, and please let me see code options about how you would address this if possible, Thanks again!
UJS is certainly the most popular approach in the Rails world currently, but different developers take it to different extremes. Some developers I know shun it entirely because according to them you don’t know if a particular element will be acted upon via JS when you are just looking at the html (which I personally think is fine, since HTML is just about structure, not functionality).
In terms of your particular issue, it is clear that you cannot simply just put the javascript into a regular javascript folder to be loaded with the page, because the javascript will not know if you are logged in. You could put an indicator somewhere in the DOM indicating that you are logged in, but to me that would be too easy to spoof. One fairly secure way to decide whether to run javascript based on data on the server is to make an AJAX call to the server, as follows:
This way, you keep the javascript (functionality) out of your html (structure) while still being able to make server side decisions. There is a similar scenario in the railscast for dynamic page caching
For example, if in your application.js you had:
Then this would call your
UsersController#showaction. Rails would then look for theapp/views/users/show.js.erbtemplate. In this file you could have the following:The javascript would automatically run as soon as the response from the server is received by the browser. In this case, it would only run the javascript if the user wasn’t logged in.