Coffesscript variables in ruby code pieces - javascript

I'm just trying to call rails helper from my coffeescript.
The problem is that coffee variables are unavailable in ruby code pieces that are in <%= ... %> blocks. And if they are processed with #{} it translates to JS in a wrong way.
So, let me illustrate. This is a piece of .js.coffee.erb file:
<% environment.context_class.instance_eval { include InputsHelper } %>
$('#input_input_type').change ->
t = $('#input_input_type').val()
$('.input_address .help-block').html('<%= input_type_hint(t) %>')
This code produces such error: undefined local variable or method 't' for #<#<Class:0x007f5e75ebd860>:0x007f5e785d1410>
Ok, let's put 't' into #{}:
<% environment.context_class.instance_eval { include InputsHelper } %>
$('#input_input_type').change ->
t = $('#input_input_type').val()
$('.input_address .help-block').html("<%= input_type_hint(#{t}) %>")
This translates to JS in a wrong way. The last string looks like this:
$('.input_address .help-block').html("<%= input_type_hint(" + t + ") %>");
Quotes are broken, so it causes rails to fall with the error:
syntax error, unexpected ';', expecting ')' ; _erbout.force_encoding(__ENCODING__) ^
In that way I don't know how to manage with this. Is there any way to do it?

There is no easy way to do this.
The problem is that the coffee script executes in the browser, but the stuff in the <%= ... %> executes on the server while the server builds the coffeescript.
So when you say input_type_hint(t) this is running on the server, but the poor sad server doesn't have a clue what "t" is.
To make this work you are going to have recode the entire input_type_hint method in coffeescript, so that it can run in the browser too! (and then it won't be in the <%= => thingy.
By the way you might want to check out http://ruby-hyperloop.io as instead of using coffeescript you just write ruby everywhere, and you basically don't need this clumsy ERB business.

Related

Rails ERB Inside Javascript

I'm trying to use some View instance variables inside Javascript.
My JS file is included in the head tag of my HTML. And it's a *.js file in assets/javascript.
When I try to...
console.log(<%= #some_instance_variable %>)
... I get syntax error. And if I try to...
console.log('<%= #some_instance_variable %>')
... the output is just the string <%= #some_instance_variable %>. How can I do to obtain the instance variable's actual value?. I'd really appreciate any help!.
Regards!.
You can include it with:
<%= javascript_include_tag('file_name.js.erb'.sub('.erb', '')) %>
But in fact it's a very ugly solution. If you want to use rails variables in JS scripts, use gon gem.

How to assign and access a javascript variable in Rails using ajax

I'm using the gon gem for rails, which allows you to save variables defined in a controller action and use them in your JavaScript. It works fine when I use it in non-Ajax settings, however, I'm having an issue with using it successfully when doing Ajax requests.
The problem: Ruby variables I assign to gon variables in the controller action when making Ajax requests come out as 'undefined' in the JavaScript.
The objective: I want to trigger an Ajax request on my page, which:
1) hits an action in the controller, and assigns a Ruby variable to a gon variable.
2) it then renders a js.erb file which executes JavaScript, part of which needs to take the Ruby variable defined in step 1, and treat it as a js variable.
here's the example action in step 1:
def some_action
gon.my_ajax_var = {some: 'info'}
end
here's the example js.erb file it renders:
/some_action.js.erb
console.log('gon.my_ajax_var equals ' + gon.my_ajax_var) //this doesn't work! comes out as 'undefined' when I expected {some: 'info'}
Any thoughts on how I fix this? I took a look at the gon.watch page, but I was confused as to whether that relates to this problem I'm having and how to implement the correct solution. Additionally, if there's a better way to do this without gon, I'm open to that as well.
Thanks!
I ended up solving this by doing the following:
In my controller:
def some_action
#my_ajax_var = {some: 'info'}.to_json
end
In my corresponding view:
/some_action.js.erb
var my_ajax_var = <%= #my_ajax_var.html_safe %>
Would've been nice to have piggybacked off the gon gem, but this got the job done.
It's some time ago that I used erb templates, but I think you need to add tags in your erb-file.
/some_action.js.erb
console.log('gon.my_ajax_var equals ' + <%= gon.my_ajax_var %>)

Can I use ordinary JavaScript in CoffeeScript file?

I am trying to add some JavaScript code in my Ruby on Rails application. I have already created for me, some js.coffee files for each view in my assets. Since, I am not familiar with the CoffeeScript I just passe some ordinary JavaScript/jQuery line in the file, such as:
if ($('#cart').length == 1) { $('#cart').hide("blind", {direction: "vertical" }, 1000); }
$('#cart tr').not('.total_line').remove();
but the following error was thrown:
Error: Parse error on line 1: Unexpected 'POST_IF' (in
/home/gotqn/Aptana
Projects/depot/app/assets/javascripts/carts.js.coffee)
The source is pointed on
Showing /home/gotqn/Aptana
Projects/depot/app/views/layouts/application.html.erb where line #6
raised:
and in this file on line #6 I got:
<%= javascript_include_tag "application" %>
I am new in Ruby on Rails, but what I suppose is happening is that I am not able to write simple JavaScript in the CoffeeScript. If this is true, can I only remove the .coffe extension and be sure that the Rails magic will work and load the file?
From the docs on coffeescript.org:
Hopefully, you'll never need to use it, but if you ever need to intersperse snippets of JavaScript within your CoffeeScript, you can use backticks to pass it straight through.
So yes, you can use JavaScript in CoffeeScript - just surround it in backticks:
`function greet(name) {
return "Hello "+name;
}`
# Back to CoffeeScript
greet "Coffee"
# => "Hello Coffee"
hello = `function (name) {
return "Hello "+name
}`
hello "Coffee"
# => "Hello Coffee"
It's highly advisable that you just convert your code to CoffeeScript instead, though.

Interpolate ruby if statement in haml javascript block

This is the code I currently have:
:javascript
// do something
- if current_user.role? :client
:javascript
//do something else
It's obviously not very clean since I'm repeating the :javascript haml filter. I'd like to avoid that, but I don't know how to properly write a Ruby "if" statement inside a HAML :javascript block.
I know how to interpolate variables with #{}, but how do you do the same for whole if/for/etc. statements?
I do this:
if(#{params[:param_to_check_for].blank? ? "true" : "false"})
In the above case, the condition is
params[:param_to_check_for].blank?.
It renders the JavaScript as either: if(false) or if(true)
I haven't tried it, but I'd think you could do
:javascript
// do something
- if current_user.role? :client
="//do something else"
(As in the second example here.)
For a very short bit of javascript, you could also try
:javascript
// do something
#{current_user.role? :client ? "//do something else" : ""}
I've interpolated the Ruby/HAML variable into explicit JS true or false for JS condition like this:
$("#cancel").click( function() {
if (#{ !!my_flag_variable })
window.location.href = "./";
else
$("#dialog").hide();
} );
I've accomplished this via a = yield :foot_scripts call in my layout, then then:
= if condition
- content_for :foot_scripts do
- render :partial => "page_specific_javascript"
in my views — that way I can ensure the Javascript is executed exactly where I want it to be in the DOM (AFTER everything else), and maintain it in a separate file, which is vastly cleaner. Getting script out of your view files? GOOD!
That's pretty much right.
The other option is you could put it in a .js.erb partial and render that from your haml view.
Then you can just do
// do something
<% if condition == true %>
// do something else
<% end %>

How can I use callback when output was printed to stdout in ruby

I am writing scripts for watching servers status.
I can write the code in javascript, but I have to write it in ruby.
In javascript,it can be done using node.js like this.
var iostat = require('child_process').spawn("iostat", ["-w 1"]);
iostat.stdout.on('data', function (data) {
console.log(data);
});
This code executes iostat command and output to console every second.
How can I implement the same thing in ruby?
In other words, I want to use callback when stdout was printed in ruby.
There are probably better ways to do this, but you can do things like this:
module PutsWatcher
def puts(string)
super("***#{string}***")
end
end
$stdout.extend PutsWatcher
puts "here"
# => "***here***"
It's a little weird if you do this in IRB or Pry, because they produce output themselves, on top of your own (i.e. the nil after you do puts), but here's a copy/paste from pry:
pry(main)> module PutsWatcher
pry(main)* def puts(string)
pry(main)* super("***#{string}***")
pry(main)* end
pry(main)* end
=> nil
pry(main)> $stdout.extend PutsWatcher
***=> #<IO:<STDOUT>>
***
pry(main)> puts "yo"
***yo***
***=> nil
***
pry(main)>
By the way, I'm not advising you do this... patching core classes is generally a bad idea. I mention it purely for academic purposes.

Categories