Private Chat Room in Ruby on Rails 3.0

On December 5, 2010, in Technical, by Prabhat Gupta

This sample will let you develop a private chatRoom using juggernaut. It push chats in realtime based on publish/subscribe model, hence making it extremely fast and scalable.

    Resources

Nodejs – http://nodejs.org/

Redis – http://code.google.com/p/redis/

Juggernaut – https://github.com/maccman/juggernaut/

JQuery – http://mirror.ozdiy.com/assets/b8/2f96a12bc919b37e09d303b86ea1b9_1251811910.html

    Getting started

1.  Install node-v0.2.5 – Download

2.  Install redis 2.0.4 – Download

3.  Run Redis server

./redis-server redis.conf

4.  Install juggernaut

git clone git://github.com/maccman/juggernaut.git --recursive
cd juggernaut
sudo node server.js

Till this point, you would have all things in place except that juggernaut would still not be able to publish chats onto channels. This feature will get enabled after Step#5

5.  Now you are ready to implement private chat app in RoR3. To get a sample chat application:

git clone git://github.com/prabgupt/chatclient.git --recursive
cd chatclient

6. To enable publishing by Juggernaut

sudo gem install juggernaut

7. run rails server

rails server

open URLS: localhost:3000/chat/channel1
localhost:3000/chat/channel2

channel1 and channel2 are assumed to be two users in this application who are trying to chat.

    In case you are interested to build your own app from scratch

Install jquery inside your application first before getting started


rails plugin install git://github.com/aaronchi/jrails.git

copy the javascript files in the plugin folder to your javascripts directory.

Develop two view html which will actually be chat windows for two different users say channel1 and channel2

Include javascripts library references

<%= javascript_include_tag 'jquery', 'application'%>

 

subscribe for private channel1_channel2 between users channel1 and channel2

	jug.subscribe("/chats/channel1_channel2", function(data){
		var li = $("<li/>");
		li.text(data);
		$("#mesg").append(li);
	});

 

Add ajax enabled form:

<% form_tag('/chat/send', :id => 'chat_window', :remote => true) do %> <%= text_field_tag 'msg_body', '', :size => 50 %> <%= text_field_tag 'sender', 'channel1'%>
<%= submit_tag 'Send Message' %> <% end %>

 

In the text_field_tag above sender can be choosen dynamically based on user if in session.

Add code inside controller associated with the view to publish message to server

#chat_controller.rb

require "juggernaut"class ChatController < ApplicationController

def send_message
@messg = params[:msg_body]
@sender = params[:sender]
Juggernaut.publish(select_channel("/channel1_channel2"), parse_chat_message(params[:msg_body], params[:sender]))
respond_to do |format|
format.js
end
end

...

Sub methods’ implementation are present inside code sample. You can anyways implement those in any way you like. Just keep in mind that juggernaut publish API requires channel name as first argument and second argument as message which is to be published to channel provided before. Here you can choose the channel dynamically based on users between whom message is currently being exchanged. Also you can write logic to persist messages, if you need, inside this method of controller.

Now final step would be to send_message.js.erb file with default name ‘send_message’ inside which we will reset the text fiend values

#send_message.js.erb
$("#chat_window")[0].reset();

 

You can perform various other operation here where in you can update only specific portion/fields of page depending on the user interface you choose for your chat window.

You are now ready to run this application. Please note that intend of current demo application is to just show how to build a private chat app using third party plugins in ruby on rails. You can anyways enhance it based on your usage.

I have listed below few issues which I faced while building this application which are applicable for any general applicatin being developed on ruby on rails 3.0

#1 : even after running ‘sudo gem install juggernaut’, it was showing following error at line: require “juggernaut”, which was present at top of application controller

	no such file to load -- juggernaut

 

Solution: On adding below line inside Gemfile of your project:

	gem 'juggernaut', :git => 'git://github.com/maccman/juggernaut.git'

 

and then running ‘sudo gem install juggernaut’, the issue was gone.

#2 : On running application, javascript console was throwing below error

jQuery is not defined

In my view html, I was calling jquery before application, however in default application layout call to default javascripts library was present which was mesing things up by calling application.js before jQuery was called.

Solution: Either change default javascript libraries setting or remove/change the call for the same inside application layout generated by default.

#3 : Error:

"Property '$' of object [object DOMWindow] is not a function" at line: $(document).ready(function()

 

Solution: This was coming because I was using jQuery in no conflict [jQuery.noConflict();]. After removing this mode, it worked fine. Though if you want to use jQuery mode in no conflict mode, which is btw recommended, you can check this thread: http://www.sitepoint.com/forums/showthread.php?t=712582

As per it, in “no-confict” mode, the $ shortcut is not available and the longer jQuery is used. To use the default jQuery shortcut of $, you can use the following wrapper around your code:

	jQuery(document).ready(function($) {
	    // $() will work as an alias for jQuery() inside of this function
	});

 

Comments

Tagged with:  

20 Responses to Private Chat Room in Ruby on Rails 3.0

  1. [...] This post was mentioned on Twitter by RubyOnRails Ireland, Ruby on Rails UK. Ruby on Rails UK said: Private Chat Room in Ruby on Rails 3.0 http://bit.ly/e0rJtl [...]

  2. bogeer says:

    sorry,I got a bug on trying out this….
    I opened the URLS: localhost:3000/chat/channel1
    localhost:3000/chat/channel2
    and the page was OK.but after I entered messages and pressed the button, there are no chatting messages.Can you give me some advice?

    • prabgupt says:

      Hey Bogeer,

      Sorry to reply late as somehow your comment was tagged as spam and I found it just now. Anyways, in case you still are facing this issue, it might be the case that publish command is not working for you. could you please check your server log or javascript console for any error and let me know. Also to track all the issues/updates, please follow https://github.com/prabgupt/chatclient

  3. Luke says:

    Firefox won’t connect– Juggernaut directions are to add

    window.WEB_SOCKET_SWF_LOCATION = "http://juggaddress:8080/WebSocketMain.swf"

    But it’s still not updating for me. Works fine in Chrome with Websocket.

    • prabgupt says:

      I didn’t try this workaround for firefox but copying WebSocketMain.swf from juggernaut installation to your rails app public folder did the trick. Let me know if you still faces this problem.

  4. susemi99 says:

    another solution of no such file to load — juggernaut is
    rails plugin install git://github.com/maccman/juggernaut_plugin.git

    • prabgupt says:

      you should not be using juggenaut_plugin as it is old juggernaut and doesn’t use redis / node and hence not scalable. Juggernaut 2(https://github.com/maccman/juggernaut) is the latest juggernaut version which is completely re-written and uses node/redis.

  5. susemi99 says:

    how to fix this error?

    NoMethodError (undefined method `publish’ for Juggernaut:Module):
    app/controllers/chats_controller.rb:7:in `send_message’

    • prabgupt says:

      What version of redis are you using?

      Please try ‘which redis’ in unix console to check which version is being exactly used. You should be using 2.x version of the redis, perhaps its latest stable version, the one mentioned in this blog.

      • susemi99 says:

        redis version is 2.2.0-rc3.
        but ‘which redis’ is nothing.

        • prabgupt says:

          You seems to be using juggernaut_plugin, older version which doesn’t use redis/node and that is the reason publish method is undefined in Juggernaut because it has been introduced since latest version of Juggernaut(https://github.com/maccman/juggernaut)

  6. Chris Walquist says:

    Hi,

    Excellent example, thanks! I have been hunting around quite a bit, and yours is the first example that I was able to get working.

    I am trying to move the code into another app (same Rails and Ruby version–1.9.2, 3.0.3), but the chat controller in the second app processes the request as HTML instead of JS (and hence returns the “/chat/send” page, which is not what is wanted). Here is the entry from the working chat’s webrick log:

    Started POST “/chat/send” for 127.0.0.1 at 2011-02-21 15:35:19 -0600
    Processing by ChatController#send_message as JS
    Parameters: {“utf8″=>”✓”, “authenticity_token”=>”Bjy1QUYah8UaZ8cmGBO1KUYKEjn1MrZsAALcJdHO7sM=”, “msg_body”=>”hi”, “sender”=>”channel2″}
    Rendered chat/send_message.js.erb (0.4ms)
    Completed 200 OK in 30ms (Views: 28.5ms | ActiveRecord: 0.0ms)

    …and here is the one from the broken app:

    Started POST “/chat/send_message” for 127.0.0.1 at 2011-02-21 16:56:59 -0600
    Processing by ChatController#send_message as HTML
    Parameters: {“utf8″=>”✓”, “authenticity_token”=>”pqVLQv3YVyb45hVmyTdkapDXabVv99RO5wAaz6Pm3wg=”, “msg_body”=>”hi”, “sender”=>”channel2″, “commit”=>”Send Message”}
    Completed 406 Not Acceptable in 1ms

    I see two things fishy here: the “HTML” send, and the “Completed 406 Not Acceptable”. It feels like routing may be involved, but I’m not able to isolate the difference yet.

    Any ideas how to narrow down this issue?

    Thanks!
    -chris

    • Chris Walquist says:

      Found it…the public/javascripts/application.js was slightly different:

      % diff chatclient/public/javascripts/application.js myapp/public/javascripts/application.js
      3,19d2
      < //jQuery.noConflict();
      <
      < jQuery.ajaxSetup({
      < 'beforeSend': function(xhr) {xhr.setRequestHeader("Accept", "text/javascript")}
      < })
      <
      < jQuery.fn.submitWithAjax = function() {
      < this.submit(function() {
      < $.post(this.action, $(this).serialize(), null, "script");
      < return false;
      < })
      < return this;
      < };
      <
      < $(document).ready(function() {
      < $("#chat_window").submitWithAjax();
      < })
      % cp chatclient/public/javascripts/application.js myapp/public/javascripts/application.js
      %

      • Chris Walquist says:

        Hmmm, actually it was *all the way* different! The application.js file in myapp’s directory was empty. Doh.

      • bhavesh says:

        Thank you yaar..

        I was finding solution of same problem from long days.

        Thanks again

      • bhavesh says:

        Hi chat working fine between Chrome & Mozilla but in Opera browser send messages but not receive/display on chat window ….

        I am surprised….

  7. Kyrri says:

    I couldn’t only get things to work when I installed juggernaut using npm. Not sure whether that is true for everyone but might be worth calling out in the post.

    • prabgupt says:

      Hey Kyrri,

      Yes Juggernaut has been updated recently and can now be installed using npm. I tried it myself and it worked well for me. You’ll now find installation steps different while rest of the things(usage etc.) remain the same.

  8. HY ChanHan says:

    Well, nice!
    Found you here finally. Let’s me try it now.

    Thanks,

Leave a Reply

Your email address will not be published. Required fields are marked *

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>