Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rails 3.1 - JS - Socket.io-emit in *.js.erb gets not executed and prevents execution of jQuery-Function

I want to use node.js with my Rails-Project to serve asynchronous io. I don't want to use juggernaut, faye or something like this, because I need clean connections with web-socket, server-sent events and spdy without an alternative. My first try to use node.js is now to use Socket.io, just to get in use with serving data to a node.js-module with JavaScript. But it doesn't work at all.

My application.js looks like this:

// This is a manifest file that'll be compiled into including all the files listed below.
// Add new JavaScript/Coffee code in separate files in this directory and they'll automatically
// be included in the compiled file accessible from http://example.com/assets/application.js
// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
// the compiled file.
//
//= require jquery
//= require jquery_ujs
//= require_tree .

window.socket = io.connect('http://localhost:8080/');

The requirements for io get correctly loaded in my application.html.erb:

 <%= javascript_include_tag "application", "http://localhost:8080/socket.io/socket.io.js" %>

Now I want to use the socket to emit a event sent to all listening clients like this in a create.js.erb:

$(function() {
  window.socket.emit('message', <%= @message =>);
};
$("#new_article")[0].reset();

The message gets created in the ArticlesCrontroller this way:

def create
  @article = current_user.articles.build(params[:article])
  if @article.save
    msg = {:data => @article.to_json}
    @message = msg.to_json
  end
end

I listen at this event in an other view called index.js.erb this way:

$(function() {
  window.socket.on('message', function (msg) {
    $("#articles").prepend(<%= escape_javascript render(Article.new.from_json(msg.data)) %>);
  });
});

The Socket.io looks like this:

var io = require('socket.io').listen(8080);

io.sockets.on('connection', function (socket) {
  socket.on('message', function () { });
  socket.on('disconnect', function () { });
});

and seems to work right, because it tells me right how it serves the requested js-File:

info  - socket.io started
debug - served static /socket.io.js

But it doesn't work at all, although the create.js.erb gets rendered without an error:

Rendered articles/create.js.erb (0.5ms)
Completed 200 OK in 268ms (Views: 70.0ms | ActiveRecord: 14.6ms)

Even the jQuery-Function for resetting the form gets not executed, what works without the try to emit the socket-event. The article gets saved to the database correctly, so that isn't the problem. Can someone tell me where the problem might be?

Update: I figured out by using the JavaScript-debugger of chrome, that the problem starts with the definition of window.socket in the application.js. The error-code is:

Uncaught ReferenceError: io is not defined
  (anonymous function)

But io is defined in the socket.io.js-File I load in my application.html.erb. I did a workaround for application.js this way:

$.getScript('http://localhost:8080/socket.io/socket.io.js', function(){
  window.socket = io.connect('http://localhost:8080/');
});

The question is now: Why do I have to get the script this way, although it is loadet in the application.html.erb? But despite this workaround the create.js.erb still doesn't work yet. I will try to workaround that after having a bit of sleep.

like image 661
NordishBen Avatar asked Nov 14 '22 16:11

NordishBen


1 Answers

I generally include dependencies in the relevant manifest (in this case, application.js).

Rails has awareness of many different asset paths, all of which are checked prior to compilation. I'd be inclined to put (e.g. socket.io.js) in vendor/assets/javascripts and add an extra line to the manifest as follows:

//= require jquery
//= require jquery_ujs
//= require socket.io
//= require_tree .
like image 122
Sasha Avatar answered Dec 20 '22 01:12

Sasha