<posts type='array'><post><slug>ruby-1-9-date-problems</slug><title>Ruby 1.9 Date Problems</title><description>One problem with ruby19 that took me awhile to figure out was why my months and days were being switched in Rails.</description><content type='datamapper::types::text'>h2. Introduction

Some time in May I took a new job with &quot;Consolo Services, A web-based hospice management system&quot;:http://consoloservices.com, and things have been great. Also around this time, I started to play with Ruby 1.9 some, so our company decided to start developing with it, and deploy with REE still, until we know everything with 1.9 is kosher. 

h2. The Problem

One of the biggest problems we have had is this weird problem where string dates like &quot;09/03/2009&quot; would get saved in a date field as &quot;03/09/2009&quot;. What we didn&apos;t know was that Ruby&apos;s Date.parse() with Ruby 1.9 is now defaulting to the European date style where the format is &quot;DD/MM/YYYY&quot;, not &quot;MM/DD/YYYY&quot;. Bummer. 

So we figured, hey no biggie, we&apos;ll just override String&apos;s to_date() method like so..

&lt;script src=&quot;http://gist.github.com/126742.js&quot;&gt;&lt;/script&gt;

But that didn&apos;t work for mass assignments, they were still swapping the days and months. So I put on my spelunking gear and started to look through ActiveRecord&apos;s source code. I highly recommend doing this as there is some beautiful code (and not so beautiful) and since your using it, you should know it. I finally traced it back to activerecord-2.3.3/lib/active_record/connection_adapters/abstract/schema_definitions. This file holds the subclass ActiveRecord::ConnectionAdapters::Column. Go look at it, do it, now. 

It all starts with the type_cast method, which tries to convert strings to the proper type like integer, float, boolean, date, etc. Then look at the string_to_date function. This function tries to call 

&lt;pre&gt;
def string_to_date(string)
 return string unless string.is_a?(String)
 return nil if string.empty?
 
 fast_string_to_date(string) || fallback_string_to_date(string)
end
&lt;/pre&gt;

So the fast_string_to_date is for converting dates that are in the ISO format, like how they are stored in mysql. So that returns nil for us, and then goes to the fallback_string_to_date. This is where ActiveRecord calls Date.parse(), and since Date.parse is now using Euroean Dates, bam, you now have found the problem.

h2. The Solution

So now all we have to do is override that method using our AmericanDateMonkeyPatch. 

&lt;script src=&quot;http://gist.github.com/181213.js&quot;&gt;&lt;/script&gt;

We save this file in the lib directory and require it in the environment.rb file, using config.after_initialization.

h2. The Better Solution

I would to see some kind of way built into Rails or ActiveRecord that you could set an option to use American Date formats instead of European. Something that you could configure in Rails by saying ActiveRecord.use_american_dates to set that option. Nothing against the rest of the world, its just that we have a lot of users that are used to dates like this. 

I hope this will save someone time and suffering, so please spread the word!</content><creator>taelor</creator><published_at type='date'>2009-09-04</published_at><created_at type='date'>2009-09-04</created_at><updated_at type='date'>2009-09-05</updated_at></post><post><slug>ask-the-gu</slug><title>ASK THE GU!</title><description>The MIX09 web conference featured a section where you could ask Scott Guthrie questions via Twitter. I was featured!</description><content type='datamapper::types::text'>So I&apos;m sitting here at work hacking away on some C#, and my buddy is talking about &quot;The Mix 2009 Conference&quot;:http://live.visitmix.com/ session called ASKTHEGU. He actually signed up for twitter just to ask a question. I sat and watched with him for a little bit (nice live streaming video from the conference) and just couldn&apos;t take it anymore, I had to ask a question.

My question for Scott and Jeff Atwood &quot;What do you guys think about Ruby and the various Web Frameworks implemented using Ruby? (Rails, Merb, Sinatra)&quot;:http://twitter.com/taylorredden/status/1349996671 actually came up on the video. My buddy called me over and we listened to what they said.

I was really happy to hear what &quot;Scott&quot;:http://weblogs.asp.net/scottgu/ said, espically since I am a Ruby developer at heart, but know about some Pyhton, Java, PHP, C, Perl, C++, etc, and now C# and VB. To paraphrase, Scott said its important to look around, and see what&apos;s going on in other camps. Take all you need from them, and leave out what people gripe about.

You can see this going on some in the Ruby community. Alot of what Rack does, came from Pyhton&apos;s WSGI. I know right now, while I am working on C#, I try to take some of the best practices I have learned from Rails and apply them to what I hack on now. You can definitely see a big Ruby influence in the direction of C#, something I welcome wholeheartedly. 

This question being answered, along with &quot;Andre Loker&apos;s post about implementing the send method in C#&quot;:http://blog.andreloker.de/post/2009/03/18/Rubys-send-in-CSharp.aspx has got me excited for a new side project. I want to implement all of the common things that Ruby does in C#. Actually, my buddy that showed me the Mix09 Conference has already implemented the String.squeeze function. Well there is 2 down, 100 to go!</content><creator>taelor</creator><published_at type='date'>2009-03-18</published_at><created_at type='date'>2009-03-18</created_at><updated_at type='date'>2009-03-18</updated_at></post><post><slug>ruby-on-rails-gravatar-simple-integration</slug><title>Ruby on Rails Gravatar Simple Integration</title><description>Want Gravatar installation and integration in four lines of code? Easy! Now that&apos;s Gravtastic!</description><content type='datamapper::types::text'>h2. Line 1 - Installation

&quot;Gravtastic&quot;:http://github.com/chrislloyd/gravtastic/tree/master is a Gravatar gem created by &quot;Chris Lloyd&quot;:http://chrislloyd.com.au/.

&lt;source&gt;
sudo gem install gravtastic
&lt;/source&gt;

h2. Line 2 - Configuration

I like the choice of creating a gem instead of a plugin, makes it usable by more than just Rails.

&lt;source&gt;
config.gem &apos;gravtastic&apos;
&lt;/source&gt;

h2. Line 3 - Integration

Notice I&apos;m using DataMapper, works just fine, no need to tweak anything. I do have a field called email that gravtastic picks up on, but you could specify another field name if you wanted.

&lt;source&gt;
class Comment
 include DataMapper::Resource
 
 is_gravtastic 
 
 #rest of code
 end
&lt;/source&gt;

h2. Line 4 - Implementation

Finally just need to display the link to the image next to whoever is commenting.

&lt;source&gt;
&lt;%= image_tag(comment.gravatar_url(:size=&gt;25)) %&gt;
&lt;/source&gt;


4 lines for auto avatar icons? Now that&apos;s _*slightly*_ coded!

h2. Other solutions

&quot;gravatar_tag&quot;:http://hasham2.blogspot.com/2007/07/using-gravatar-plugin-to-embed-avatars.html </content><creator>taelor</creator><published_at type='date'>2009-03-10</published_at><created_at type='date'>2009-03-09</created_at><updated_at type='date'>2009-03-11</updated_at></post><post><slug>intercepting-a-clicked-link-url-using-jquery</slug><title>Intercepting a Clicked Link Url Using jQuery</title><description>Ever wanted to send a set of parameters through a link, but the only problem, is the parameters change frequently with some javascript?</description><content type='datamapper::types::text'>h2. The Problem

Ok, so I am working on this floating, draggable, fixed position panel to help administer my blog when I log in. Yes I know, it sounds really cool. I hope to wrap it up in a Rails plugin or gem soon, or at least post all of that code on &quot;github&quot;:http://github.com/taelor. While I was working on this, I was getting really annoyed at my draggable panel going back to the top 0 and left 0 position every time I clicked on a new link. I wanted it to stay where ever I moved it when I goto the next page. 

h2. The Solution

I knew the solution was simple, just send in the location values of the admin panel div on every request. The implementation on the other hand was a little more complex. Luckily jQuery is the shit. All I have to do, it create a new function on a click event for every anchor tag. *_Right now this only works with get requests, I can deal with the put/post requests resetting the position_*. After I have hooked into that event, I can manipulate the href attribute and add my parameters. 

h2. The Code

&lt;script src=&quot;http://gist.github.com/75590.js&quot;&gt;&lt;/script&gt;

h2. The Joy

Did I say that jQuery is the shit? Makes me feel like I&apos;m working with Ruby for the first time all over again. You know that feeling, when it feels like its just *_slightly_* coded. 

Grabbing the style attributes of top and left are super easier one liners. Next I just have to grab the actual href text to manipulate. After that, you have to see what is in the url already. As of right now, I deal with 4 different cases, each one of them handled by the if else statement. This will ensure that the place you add your parameters are proper when your already sending parameters, or linking to a div. At the end you just set the anchor&apos;s href attribute to the new url with your parameters added in.

h2. The Collaboration 

Now I think there might be some refactoring that could be done on this, so jump on &quot;github&quot;:http://github.com/ and fork this &quot;gist&quot;:http://gist.github.com/75590!</content><creator>taelor</creator><published_at type='date'>2009-03-08</published_at><created_at type='date'>2009-03-08</created_at><updated_at type='date'>2009-03-09</updated_at></post><post><slug>jquery-rotating-list</slug><title>jQuery Rotating List</title><description>How to automatically rotate a set of DOM items.</description><content type='datamapper::types::text'>In my quest to better use javascript, I needed something to work on to hone my jQuery skills. I&apos;m a sucker for animations. I think sometimes, if not over done, can be good tools for build great user interfaces. You can help navigate to what they need to click on. I this case, I want you to click on my blog posts. At the homepage, hopefully you will notice a rotating list on recent blog posts. 

This does use the &quot;jQuery Timers plugin&quot;:http://plugins.jquery.com/project/timers so don&apos;t forget to include that in your HTML header. That is for the everyTime function. Also, notice the enqueue and dequeue functions. This is for making sure the animation run in the proper order. Try taking them out, and notice how everything will react.

&lt;script src=&quot;http://gist.github.com/70650.js&quot;&gt;&lt;/script&gt;

If you don&apos;t queue the two groups up, then the append happens at the same time of the rotation, which doesn&apos;t really look that good. Try watching it in Firebug, its kinda cool watching the code loop around.

Pretty simple stuff. Needs a little refactoring. Early on in college modulo division is something I always thought I would never use. I was so wrong by my second year. Any time you want something to behave cyclical, modulo division is there to help. Doubly linked lists? check. Rotations, check. And I&apos;m sure it has something to do with &amp;Pi;.

</content><creator>taelor</creator><published_at type='date'>2009-02-26</published_at><created_at type='date'>2009-02-26</created_at><updated_at type='date'>2009-02-26</updated_at></post><post><slug>up-and-running</slug><title>Up and Running</title><description>A lot has happened since last I wrote.</description><content type='datamapper::types::text'>Well, where to start.

I haven&apos;t blogged in a bit, and I hope to get back in the swing of things here shortly now that I am working with Ruby again. See I got a new job working in a complete Microsoft Stack. SQL Server Management Studio owns, SSIS sucks, and then your left with .NET and IIS (I mainly do Backend work, so I can&apos;t comment on this), but at least they are working on &quot;.NET MVC&quot;:http://en.wikipedia.org/wiki/ASP.NET_MVC_Framework and have a niche community brewing over at &quot;ALT.NET&quot;:http://altnetpodcast.com/. I have been enjoying their discussions as I commute to my new job, Thanks guys.

Luckily I have been able to sneak some Ruby into my work place, for a lot of backend automated processes. Since I can&apos;t use ActiveRecord with these legacy databases, and Datamapper doesn&apos;t really support Windows, I have been working on my own little &quot;get the job done&quot; Object Relational Mapper. Meta-programming is a freaking blast, and thank God(science Robby?) for the One Click installer including the DBI class. Also, ODBC is way underrated in my opinion. I will throw the code up on &quot;github&quot;:http://github.com/taelor as soon as I get it to a semi-stable releasable state. Think Database to Database imports(with conversions) and Faker data stubbing, all defined in the model.

So... Rails and Merb Merged (Mails? or Rerb?), leaving me very shocked, confused, angry, then eventually happy. Shocked because it happened after all the drama; confused cause I wasn&apos;t sure about the seriousness of this happening; angry cause this blog is run using merb and I really liked the idea behind it; and finally came to a state of serenity. This IS going to be for the best. The idea of taking two of the most innovative and efficient development groups (Rails and Merb respectfully) we are really going to get the #1 web development framework in the mix of all of it. Unfortunately its probably not going to come for another 6 months to a year. 

So I guess instead of trying to learn Merb, I&apos;m going to go back to working with Rails, but this time I am going to try and use DataMapper and jQuery, instead of ActiveRecord and Prototype. My roomate &quot;Ralph&quot;:http://www.ralphedge.com/ has been working on trying to make a plug to use the rails helpers and jQuery unobtrusively. He hopes to release something in the future.

I&apos;ve got &quot;ShovelChat&quot;:http://shovelchat.com/ up and running again. I am going to try and work on that a bit, as well as add some more to &quot;ChatSandbox&quot;:http://github.com/taelor/chat_sandbox/. 

Now, back to the Laboratory...</content><creator>taelor</creator><published_at type='date'>2009-01-18</published_at><created_at type='date'>2009-01-19</created_at><updated_at type='date'>2009-01-19</updated_at></post><post><slug>juggernaut-on-rails-sending-private-messages</slug><title>Juggernaut on Rails - Sending Private Messages </title><description>How to send Private Messages using Juggernaut.</description><content type='datamapper::types::text'>h2. Chat_Sandbox now on GitHub!

I figured the best (and potentialy coolest) way to share this code was to just post it on &quot;GitHub&quot;:http://github.com/. So now you can find the &quot;juggernaut chat_sandbox code on github&quot;:http://github.com/taelor/chat_sandbox/. Please fork it off and fool with it. I have kept it bare bones, but if you wanna tweak it out some to show off, feel free. I&apos;ll merge it back in.

h2. Private Messaging Code Highlights

When you git the source, you will see where I have added a new controller called messages, which should have probably been called private_messages, since it only deals with just the private messages. Its not restful, but I was just going for something really quick. when a user clicks a username in the list, a chat box will open up. He is the helper to create that box.

&lt;source&gt;
module MessagesHelper
 def create_private_message(client_ids)
 users = User.find(client_ids).collect{|user| user.login}.to_sentence
 private_chat_room_id = &apos;private_chat_room_&apos;+client_ids.join(&apos;_&apos;)
 private_chat_input_id = &apos;private_chat_input_&apos;+client_ids.join(&apos;_&apos;)
 
 top =&quot;&lt;div class=&apos;private_message&apos;&gt;&lt;h3&gt;#{users}&lt;/h3&gt;&lt;div id=&apos;#{private_chat_room_id}&apos; class=&apos;private_chat_room scroller&apos;&gt;&lt;/div&gt;&lt;div id=&apos;chat_form&apos;&gt;&quot;
 
 form = form_remote_tag(:url =&gt; { :action =&gt; :send_private_message, :client_ids =&gt; client_ids }, :complete =&gt; &quot;$(&apos;#{private_chat_input_id}&apos;).value = &apos;&apos;&quot; )
 
 text = text_field_tag( private_chat_input_id, &apos;&apos;, { :size =&gt; &apos;50&apos;, :id =&gt; private_chat_input_id, :class=&gt; &apos;private_chat_input&apos;} )
 
 submit = submit_tag &quot;Chat&quot;
 
 bottom =&quot;&lt;/form&gt;&lt;/div&gt;&lt;div&quot;
 
 top+form+text+submit+bottom
 end
end
&lt;/source&gt;

Now when someone chats something into this box, it will be pushed to the other user. But what if they don&apos;t have that box created? Create it for them. This of course is the thought process for the javascript that gets pushed out. Here&apos;s the code. Notice the part where you check if private_chat_room_id is null, it is a Javascript conditional, not ruby.

&lt;source&gt;
def send_private_message
@client_ids = params[:client_ids].collect{|client_id| client_id.to_i } if params[:client_ids]

private_chat_room_id = &apos;private_chat_room_&apos;+@client_ids.join(&apos;_&apos;)
private_chat_input_id = &apos;private_chat_input_&apos;+@client_ids.join(&apos;_&apos;)

render :juggernaut =&gt; {:type =&gt; :send_to_clients, :client_ids =&gt; @client_ids } do |page| 
 
 page &lt;&lt; &quot;if ( $(&apos;#{private_chat_room_id}&apos;) == null) {&quot;
 page.insert_html :bottom, &apos;private_messages&apos;, create_private_message(@client_ids)
 page &lt;&lt; &quot;}&quot;
 
 page.insert_html :bottom, private_chat_room_id, &quot;&lt;p&gt;#{current_user.login}: #{h params[private_chat_input_id]}&lt;/p&gt;&quot;
 page.call :scrollChatPanel, private_chat_room_id
end

render :nothing =&gt; true
end
&lt;/source&gt;

Fork the code and mess around with it. Have some fun. Help me learn something. 

h2. Next Post? Draggables? JQuery?

I looked on github for some Juggernaut related things and found a jQuery fork for juggernaut. I was going to maybe use that and jRails to port everything over. If not that, I could do Prototype Draggables for the private messages. What do you suggest? Leave a comment.</content><creator>taelor</creator><published_at type='date'>2008-08-12</published_at><created_at type='date'>2008-08-12</created_at><updated_at type='date'>2009-02-18</updated_at></post><post><slug>juggernaut-0-5-6-update</slug><title>Juggernaut 0.5.6 Update</title><description>I talk about the 0.5.6 version of the Juggernaut.</description><content type='datamapper::types::text'>h2. Welcome back

It&apos;s good to see some of you are enjoying these posts. If you are new, please go back and read &quot;The Juggernaut, a Push Server for Ruby on Rails&quot;:http://slightlycoded.com/blog/the-juggernaut-a-push-server-for-ruby-on-rails and &quot;Juggernaut Part 2 - Connected Users List&quot;:http://slightlycoded.com/blog/juggernaut-part-2-connected-users-list since we will be building on top of those.

I was pretty excited to see Alex&apos;s new release of the Juggernaut gem. After updating, I went straight into the source code to learn some things. I could get show_users to work, and some others but for some reason I could not get show_users_for_channels to work. Turns out there was a typo in server.rb on the gem. Please make sure line 276 (or somewhere near that) says when :show_users_for_channels, with the &apos;s&apos; at the end. To update do these.

h2. Updating

&lt;source&gt;
gem update juggernaut

script/plugin install http://juggernaut.rubyforge.org/svn/trunk/juggernaut --force
&lt;/source&gt;

In my last post, we had add to the gem to make a request to the /connections/users url that would push to the users in the room who is logged in. Now that Alex has fully implemented :show_users_from_channels, we can just do that when the /connections/login request is made. Oh and also, I have refactored some of the controller, so lets see the whole thing now.

&lt;source&gt;
class ConnectionsController &lt; ApplicationController
 around_filter :update_user_list
 
 def login
 render :juggernaut =&gt; {:type =&gt; :send_to_channels, :channels =&gt; channels } do |page|
 page.insert_html :bottom, &apos;chat_room&apos;, &quot;&lt;p style=&apos;color:green;font-size:20px;&apos;&gt;#{@user.login} has entered the room&lt;/p&gt;&quot;
 page.call :scrollChatPanel
 end
 
 render :nothing =&gt; true
 end

 def logout
 Juggernaut.remove_channels_from_clients(@user.id, channels)
 
 render :juggernaut =&gt; {:type =&gt; :send_to_channels, :channels =&gt; channels } do |page|
 page.insert_html :bottom, &apos;chat_room&apos;, &quot;&lt;p style=&apos;color:green;font-size:20px;&apos;&gt;#{@user.login} has left the room&lt;/p&gt;&quot;
 page.call :scrollChatPanel
 end
 
 render :nothing =&gt; true
 end

 private
 
 def update_user_list
 @user = User.find(params[:client_id])
 
 @channels = params[:channels].collect{|channel| channel.to_i }
 
 yield

 users = User.find(Juggernaut.show_users_for_channels(@channels).collect{ |user| user[&quot;id&quot;] })

 render :juggernaut =&gt; {:type =&gt; :send_to_channels, :channels =&gt; @channels } do |page|
 page.replace_html &apos;user_list&apos;, users.collect{ |user| &quot;&lt;li&gt;#{user.login}&lt;/li&gt;&quot; }.join
 end
 end
end
&lt;/source&gt;

But for some reason it doesn&apos;t work for you does it? Well after a few hours of thinking about it, checking logs and everything I remembered about &quot;Deadlocks&quot;:http://en.wikipedia.org/wiki/Deadlock in my CSC networking class. The Juggernaut server makes a request for /connections/login and waits for a 200 response. But inside of that request, We query the Juggernaut and wait to get the response. But since the initial request of /connections/login is waiting for the 200, Juggernaut will not send the user list data. So how do you fix it? Run it in a new Thread!

h2. Threading

&lt;source&gt;
Thread.new do
 users = User.find(Juggernaut.show_users_for_channels(@channels).collect{ |user| user[&quot;id&quot;] })

 render :juggernaut =&gt; {:type =&gt; :send_to_channels, :channels =&gt; @channels } do |page|
 page.replace_html &apos;user_list&apos;, users.collect{ |user| &quot;&lt;li&gt;#{user.login}&lt;/li&gt;&quot; }.join
 end
end
&lt;/source&gt;

This will create a new process letting the 200 response goto the server, and then it requests the users lists. This problem may arise from the fact that Juggernaut is powered by EventMachine, which is single-threaded. Because its single threaded, it makes all the requests run really fast.

Something else you can add is to show how many people are currently chatting in a room listed on the index page. I just added two lines to show this.

&lt;source&gt;
&lt;h1&gt;Listing chat_rooms&lt;/h1&gt;

&lt;table&gt;
 &lt;tr&gt;
	&lt;th&gt;# of Users&lt;/th&gt;
 &lt;th&gt;Name&lt;/th&gt;
 &lt;th&gt;Description&lt;/th&gt;
 &lt;/tr&gt;

&lt;% for chat_room in @chat_rooms %&gt;
 &lt;tr&gt;
	&lt;td&gt;&lt;%=Juggernaut.show_users_for_channels(chat_room.id).size %&gt;&lt;/td&gt;
 &lt;td&gt;&lt;%=h chat_room.name %&gt;&lt;/td&gt;
 &lt;td&gt;&lt;%=h chat_room.description %&gt;&lt;/td&gt;
 &lt;td&gt;&lt;%= link_to &apos;Show&apos;, chat_room %&gt;&lt;/td&gt;
 &lt;td&gt;&lt;%= link_to &apos;Edit&apos;, edit_chat_room_path(chat_room) %&gt;&lt;/td&gt;
 &lt;td&gt;&lt;%= link_to &apos;Destroy&apos;, chat_room, :confirm =&gt; &apos;Are you sure?&apos;, :method =&gt; :delete %&gt;&lt;/td&gt;
 &lt;/tr&gt;
&lt;% end %&gt;
&lt;/table&gt;

&lt;br /&gt;

&lt;%= link_to &apos;New chat_room&apos;, new_chat_room_path %&gt;
&lt;/source&gt;

Hope that helps you guys out some! There might be some other lingering issues getting everything to work, I couldn&apos;t remember exactly everything I did. If the tutorial gives you problems, please leave a comment and I will help you out.

I think the next article will try and tackle private messages, unless you have another idea. Please leave your comments below. I&apos;m out.</content><creator>taelor</creator><published_at type='date'>2008-08-11</published_at><created_at type='date'>2008-08-11</created_at><updated_at type='date'>2009-02-26</updated_at></post><post><slug>juggernaut-part-2-connected-users-list</slug><title>Juggernaut Part 2 - Connected Users List</title><description>Here we tackle the user list problem.</description><content type='datamapper::types::text'>h2. In Our Last Episode...

First off, please read &quot;The Juggernaut, a Push Server for Ruby on Rails&quot;:http://slightlycoded.com/blog/the-juggernaut-a-push-server-for-ruby-on-rails, since all of the code here, is built on top of that, not to mentions the principles behind it. As for some background, please refer to &quot;a question I asked awhile back&quot;:http://groups.google.com/group/Juggernaut-for-Rails/browse_thread/thread/b692c7cb95989e0b?hl=en, and the rest of the discussion board.

Disclaimer: I know this may not be the best solution, and there are probably ones that are better, this one just worked for me.

h2. Subscription and Logout 

I first wanted to cover these basics, which are alreay used in Juggernaut, but serve as a basic idea for how my users list implementation works. When a Flash connection is made or lost, the Juggernaut server triggers some requests to your server. These are actual URLs on your webserver. Think of something like after a Paypal transaction is completed, they post a request to your server to confirm it. I learned this from &quot;Nic Cavigliano&apos;s post a little while back&quot;:http://ncavig.com/blog/?page_id=10, it maybe be a little dated, but still some of it is relevant.

First off we need to tell Juggernaut what links they need to request when a trigger is set off. Add this to your juggernaut.yml file, the one that the Juggernaut server uses to start up with.

&lt;source&gt;
#in juggernaut.yml
:subscription_url: http://shovelchat.com/connections/login

:logout_connection_url: http://shovelchat.com/connections/logout
&lt;/source&gt;


Well that looks good, but how is the Rails server going to handle it? Lets create another controller and actions to handle this. First we get the user from the client_id that Juggernaut sent us, which we told Juggy that it was the user.id. Next for some reason we have to make sure ruby knows all the channels in the array are integer, because when they are sent over http, they are as strings. There is probably a better way to do that. Next we just render some simple javascript alerting all the users in the room that a person has joined or left. I think there is some way that we could refactor this not to make a database call to the User, just not sure how yet.

&lt;source&gt;
# in your console
script/generate controller login logout

#in /app/controlers/connections_controller.rb
	def login
	 @user = User.find(params[:client_id])
 
	 #convert all the strings to integers
	 channels = params[:channels].collect{|channel| channel.to_i } 
 
	 render :juggernaut =&gt; {:type =&gt; :send_to_channels, :channels =&gt; channels } do |page|
	 page.insert_html :bottom, &apos;chat_room&apos;, &quot;&lt;p style=&apos;color:green;font-size:20px;&apos;&gt;#{@user.login} has entered the room&lt;/p&gt;&quot;
	 page.call :scrollChatPanel
	 end
 
	 render :nothing =&gt; true
	end

	def logout
	 @user = User.find(params[:client_id])
 
	 #convert all the strings to integers
	 channels = params[:channels].collect{|channel| channel.to_i }
 
	 Juggernaut.remove_channels_from_clients(@user.id, channels)
 
	 render :juggernaut =&gt; {:type =&gt; :send_to_channels, :channels =&gt; channels } do |page|
	 page.insert_html :bottom, &apos;chat_room&apos;, &quot;&lt;p style=&apos;color:green;font-size:20px;&apos;&gt;#{@user.login} has left the room&lt;/p&gt;&quot;
	 page.call :scrollChatPanel
	 end
 
	 render :nothing =&gt; true
	end
&lt;/source&gt;


Ok a pretty good start, with just minimal amounts of code we have given a lot of data to people using the app. Now for the big stuff.

h2. Cutting the Gem, Re-wiring the Plugin.

To push out the info of all the people in the chat room, I first tried what was discussed here, but couldn&apos;t get what I needed back. So after A little looking around I found people were using the database and the subscription/logout methods to track when people were in the room. This is good, just a little to much database overhead for my taste, also, the information is already stored on the Juggy server, so having it in the Rails database is a little redundant. After digging through the gem and plugin source, I kinda figured out how to do it. First off lets add something to the plugin to tell the Juggy server what we want.

&lt;source&gt;
# add this around line 75 of /vendor/plugins/
	def show_users_for_channel_and_post(channels)
	 fc = {
	 :command =&gt; :query,
	 :type =&gt; :show_users_for_channel_and_post,
	 :channels =&gt; channels
	 }
	 send_data(fc)
	end

#next add this line after the render :juggernaut in your connections controller for both login and logout actions
Juggernaut.show_users_for_channel_and_post channels
&lt;/source&gt;


The show_users_for_channel_and_post() method sends a query to the Juggy server (which is the gem source code). The line in the controller calls that method. So lets head into the gem source itself and check it out. The best way to probably do this is to unpack the gem into your vender folder, but I went ahead and just hacked it into my gem repo anyway. Btw, if you do it that way, it gets messy to deploy.

&lt;source&gt;
# /usr/local/lib/ruby/gems/1.8/gems/juggernaut-0.5.5/lib/juggernaut/server for me on my Mac OS X,
# at the bottom of the case statement in the query_command method around line 250 add this
	when :show_users_for_channel_and_post
	query_needs :channels
	users_query_request Juggernaut::Client.find_by_channels(@request[:channels]).collect{ |client| client.id }
&lt;/source&gt;


The above code will find all the client id&apos;s connected to that channel and then pass that off to the users_query_request method. So now we have to write that method. So in that same file add this at the bottom, right above the client_ip method.

&lt;source&gt;
	def users_query_request(clients)
	return false unless options[:users_request_url]
	url = URI.parse(options[:users_request_url])
	params = []
	clients.each{|client| params &lt;&lt; &quot;clients[]=#{client}&quot; }
	(@request[:channels] || []).each {|chan| params &lt;&lt; &quot;channels[]=#{chan}&quot; }
	url.query = params.join(&apos;&amp;&apos;)
	begin
	open(url.to_s, &quot;User-Agent&quot; =&gt; &quot;Ruby/#{RUBY_VERSION}&quot;)
	rescue Timeout::Error
	return false
	rescue
	return false
	end
	true
	end
&lt;/source&gt;

Ok, so you see that options[:users_request_url]? Well the options hash is loaded from the juggernaut.yml file, so lets add one more line there.

&lt;source&gt;
#in juggernaut.yml
	:users_request_url: http://localhost:3000/connections/users
&lt;/source&gt;

Ok, stay with me now, the Juggernaut server will make a request to the Rails server with all the clients in an array, so let&apos;s add that action into our Connections controller, so we can get the login names, create some javascript to show, and then push it out to everyone connected to that channel.

&lt;source&gt;
def users
	users = User.find(params[:clients])

	channels = params[:channels].collect{|channel| channel.to_i }

	render :juggernaut =&gt; {:type =&gt; :send_to_channels, :channels =&gt; channels } do |page|
	 page.replace_html &apos;user_list&apos;, users.collect{ |user| &quot;&lt;li&gt;#{user.login}&lt;/li&gt;&quot; }.join
	end

	render :nothing =&gt; true
end
&lt;/source&gt;


Simple enough right? Now this is just a normal render for the Juggernaut server, so our hacking on gems and plugins is done. But there is something we forgot to add, the actual user list in the view! We could also use some CSS im sure too.

&lt;source&gt;
#put this right after the chat_room div in /app/views/chat_rooms/show
	&lt;ul id=&quot;user_list&quot;&gt;&lt;/ul&gt;
	
#and the css
	#chat_room, #user_list{
	border:1px solid black;
	overflow-y: scroll;
	scrollbar-arrow-color:000000;
	scrollbar-track-color:000000;
	scrollbar-shadow-color:B1D0F0;
	scrollbar-face-color:B1D0F0;
	scrollbar-highlight-color:B1D0F0;
	scrollbar-darkshadow-color:B1D0F0;
	scrollbar-3dlight-color:B1D0F0;
	}

	#chat_room
	{
	float: left;
	width:600px; 
	height:400px; 
	padding:5px;
	}

	#user_list {
	list-style-type: none;
	padding:5px;
	margin-left:10px;
	float: left;
	width: 150px;
	height: 400px;
	}

	#chat_form{
	clear:both;
	}

	#chat_input{
	padding:5px;
	margin-top: 10px;
	font-size: 15px;
	border: 1px solid black;
	}
&lt;/source&gt;

h2. What&apos;s next?

Well I think it would be nice if we could just get all the clients without making Juggernaut post to /connections/users. If we can just get the Juggernaut.send_data(:command=&gt;&quot;query&quot;, :type=&gt;&quot;show_users_for_channel&quot; :channels=&gt;channels) to send back the proper JSON, we can bypass that /connections/users request and render the user_list javascript immediately. I think it might have something to do with the way the information is wrapped up (or lack there of) for the request. 

One thing to note, the information that Juggernaut.send_data(:command=&gt;&quot;query&quot;, :type=&gt;&quot;show_users_for_channel&quot; :channels=&gt;channels) returns is whats in your config/juggernaut_hosts.yml file. Not sure why, but it might be a clue as to whats going wrong.</content><creator>taelor</creator><published_at type='date'>2008-08-06</published_at><created_at type='date'>2008-08-06</created_at><updated_at type='date'>2008-08-06</updated_at></post><post><slug>the-juggernaut-a-push-server-for-ruby-on-rails</slug><title>The Juggernaut, a Push Server for Ruby on Rails</title><description>Introducing the Juggernaut Push Server.</description><content type='datamapper::types::text'>!&lt;/images/Juggernaut_comic.gif!

h2. Introduction

Well that picture pretty much sums, it up, &quot;this gem&quot;:http://juggernaut.rubyforge.com my friends, is bad ass. Look, at the picture and think about it, Juggy is pushing up right at you, and you didn&apos;t do anything to provoke him. Well that&apos;s kind of like the Juggernaut gem.

We have all heard of and used AJAX. The browser sends a request for to _pull_ some data, and the server updates the web page without refreshing the whole page. Which is really efficient. But it is two whole requests, and we can do better, so lets cut that down to *one*.

So how could we cut this bandwidth in half? By having the server just _push_ the data straight up to the client, the browser. The user doesn&apos;t have to ask to pull the info, they just get it. Now Juggernaut uses a pretty clever method of opening and keeping alive &quot;Flash&quot;:http://en.wikipedia.org/wiki/Adobe_Flash socket up for a particular webpage. The server then uses this pipe to push data, in our case usually javascript, up to that smart browser.

Juggernaut follows the &quot;Observer or Publisher/Subscriber design pattern.&quot;:http://en.wikipedia.org/wiki/Observer_pattern This pattern really lends its self to a chat like application, which is what we are going to create today.

h2. Installation

First off you need to install some prerequisites for the Juggernaut gem to work. Juggernaut uses the very scalable EventMachine and also Json. After you install those, you can install the gem.

&lt;source&gt;
sudo gem install eventmachine json

sudo gem install juggernaut
&lt;/source&gt;

Next you also have to install the Rails plugin too. You can almost think of the plugin as the subscriber(browser/client), and the gem as the publisher(on the server). So let&apos;s create a little chat_sandbox to play around in, and then install the plugin, then run a command to generate a config yaml file.

&lt;source&gt;
rails chat_sandbox

cd chat_sandbox

script/plugin install http://juggernaut.rubyforge.org/svn/trunk/juggernaut

juggernaut -g juggernaut.yml
&lt;/source&gt;

Now the plugin will generate a file in config/ called juggernaut_hosts.yml, which is not to be confused with the other configuration file that we generated on the last line which resides at the root of chat_sandbox. They should not need any editing while we are playing around in our sandbox on localhost, but once we get into some heavier apps and deployments, its a whole nother&apos; blog post.

Now that we have our Juggernaut environment, I will pause and let you setup your Rails environment. Do your database junk, delete the index.html, and any other housekeeping chores.

Next we need to go ahead and set up restful_authentication, which is a great way to facilitate the chat app and usernames. After restful_auth installation, we can create an authenticated user, and then a ChatRoom scaffold.

&lt;source&gt;
script/plugin install http://svn.techno-weenie.net/projects/plugins/restful_authentication/

script/generate authenticated user sessions

script/generate scaffold chat_room name:string description:string

rake db:create

rake db:migrate

mv app/views/layouts/chat_rooms.html.erb app/views/layouts/application.html.erb

&lt;/source&gt;

h2. Code

Finally, we get to write some code now. Lets take care of our routes file really quick, just one minor move of adding a member action. Pretty standard stuff so far.

&lt;source&gt;
#add this in your routes.rb file
	map.root :controller =&gt; &quot;chat_rooms&quot;
	map.resources :chat_rooms, :member =&gt; {:send_data =&gt; :post}
	map.signup &apos;/signup&apos;, :controller =&gt; &apos;users&apos;, :action =&gt; &apos;new&apos;
	map.login &apos;/login&apos;, :controller =&gt; &apos;sessions&apos;, :action =&gt; &apos;new&apos;
	map.logout &apos;/logout&apos;, :controller =&gt; &apos;sessions&apos;, :action =&gt; &apos;destroy&apos;
&lt;/source&gt;	

Continuing on, add the javascript tags for prototype and juggernaut. Now here is the important link that creates the &apos;subscriber&apos;. In the top of the views, we call the juggernaut helper, and subscribe to the chat_room.id channel. we also register our client_id for uniqueness. The javascript below is what keeps the chat box scrolling down. And towards the bottom a simple ajax call. Finally at the bottom we have our only css needed to be added to help with the chat room feel inside of a div.

&lt;source:rhtml&gt;
#app/views/layouts/application.html.erb, just add this somewhere in the header
	&lt;%= javascript_include_tag &apos;prototype&apos;, :juggernaut %&gt;

#app/views/chat_rooms/show.html.erb
	&lt;%= juggernaut(:channels =&gt; [@chat_room.id], :client_id =&gt; session[:user_id]) %&gt;

	&lt;script type=&quot;text/javascript&quot;&gt;
	function scrollChatPanel(){
	 div = $(&apos;chat_room&apos;);	
	 div.scrollTop = 0xffff;	
	}
	&lt;/script&gt;
	
	&lt;p&gt;&lt;%= link_to &apos;Back&apos;, chat_rooms_path %&gt;&lt;/p&gt;

	&lt;h1&gt;&lt;%=h @chat_room.name %&gt;&lt;/h1&gt;

	&lt;p&gt;&lt;%=h @chat_room.description %&gt;&lt;/p&gt;

	&lt;div id=&quot;chat_room&quot;&gt;&lt;/div&gt;


	&lt;div id=&quot;chat_form&quot;&gt;
	&lt;%= form_remote_tag(
	 :url =&gt; { :action =&gt; :send_data },
	 :complete =&gt; &quot;$(&apos;chat_input&apos;).value = &apos;&apos;&quot; ) %&gt;

	&lt;%= text_field_tag( &apos;chat_input&apos;, &apos;&apos;, { :size =&gt; &apos;50&apos;, :id =&gt; &apos;chat_input&apos;} ) %&gt;
	&lt;%= submit_tag &quot;Chat&quot; %&gt;
	&lt;/form&gt;
	&lt;/div&gt;
&lt;/source&gt;


&lt;source:css&gt;
#and for the CSS, just add it at the bottom of scaffold.css or something...
	#chat_room{
	width:600px; 
	height:400px;
	border:1px solid black;
	overflow-y: scroll;
	scrollbar-arrow-color:000000;
	scrollbar-track-color:000000;
	scrollbar-shadow-color:B1D0F0;
	scrollbar-face-color:B1D0F0;
	scrollbar-highlight-color:B1D0F0;
	scrollbar-darkshadow-color:B1D0F0;
	scrollbar-3dlight-color:B1D0F0;
	}
&lt;/source&gt;

And for the last bit of code, the controller that ties it all together. First off add the before filter to make sure people dont goto a chat page unless they are already logged in. Then toward the bottom add the send_data action which handles the ajax call we set up earlier. The send_data only renders some javascript that it passes off to the Juggernaut push server to get sent out to all the subscribers.

&lt;source&gt;

#app/controllers/stories_controller.rb, add this at the top
	before_filter :is_logged_in?, :except =&gt; :index
	
	...code...

	#and this at the bottom
	def send_data
 render :juggernaut =&gt; {:type =&gt; :send_to_channels, :channels =&gt; [params[:id].to_i] } do |page|
 page.insert_html :bottom, &apos;chat_room&apos;, &quot;&lt;p&gt;#{current_user.login}: #{h params[:chat_input]}&lt;/p&gt;&quot;
 page.call :scrollChatPanel
 end
 render :nothing =&gt; true
 	end
 
 	private

	def is_logged_in?
	 if logged_in?
	 true
	 else
	 flash[:error] = &quot;You must be logged in to chat&quot;
	 redirect_to(&quot;/login&quot;)
	 false
	 end
	end

&lt;/source&gt;

Ok, now to start the engines.

&lt;source&gt;
	juggernaut -c juggernaut.yml -d #d is for daemon, c chooses which juggernaut yaml config
	
	script/server
&lt;/source&gt;

h2. Juggernaut for the Win?

Hope everything went well, and you can create a chat room, and then enter and talk in it. Try opening two different browsers to test out. Remember this uses Adobe Flash version 8, so check the &quot;Juggernaut Homepage&quot;:http://juggernaut.rubyforge.org for more specfic details. Thanks to Alex MacCaw for creating the wonderful gem.

!&gt;/images/juggernaut_magic.jpg!

Push is where its at. A.k.a Reverse AJAX, Comet. I can only image the possiblites coming into play with cloud computing and push servers. The webserver could take in a send_message action, then it could notifiy 10 juggernaut servers, who then in turn notify all 1000 of there clients, scale from there. Sounds complicated eh? Luckily &quot;ezmobius is leading the way for us with Vertebra&quot;:http://brainspl.at/articles/2008/06/02/introducing-vertebra. His version will be using XMPP protocol instead of the Flash connection, so I am really excited to see whats comes out of the Yard.

I hope to have comments up soon, just migrated the site over to merb and slicehost, so its kinda slowing me down some. 

Now I know this app is a little barebones, but to see what a little more work can do, head over to &quot;ShovelChat, a Web Chat Application for Digg Users&quot;:http://shovelchat.com. There you can (hopefully) see where I have hacked my way through a chat room user list system. I have a little bit I added to the Juggernaut Gem, but it needs some polishing, and I hope to write about it soon. Until next time, I&apos;m dun-skees.</content><creator>taelor</creator><published_at type='date'>2008-08-05</published_at><created_at type='date'>2008-08-05</created_at><updated_at type='date'>2009-02-18</updated_at></post><post><slug>welcome-to-slightly-coded</slug><title>Welcome to Slightly Coded</title><description>A brief introduction and plan.</description><content type='datamapper::types::text'>Here at Slightly Coded, we will primarily be writing about many topics in the Ruby ecosystem, though on occasion I&apos;m sure we will stray. Things we find interesting are &quot;Rails&quot;:http://www.rubyonrails.com, &quot;Merb&quot;:http://www.merbivore.com, and &quot;Datamapper&quot;:http://www.datamapper.org.

For the first few posts, we will be giving a beginners tutorial on how to build a small-medium rails website on shared hosting. This is for people who already have a basic grasp of Ruby and Rails, but have done nothing professionally, and have just found their first client.

Later on, we will focus here and there on tips and example scripts, covering routing, caching, Content Management System Websites, SEO, Ajax, and hopefully lots and lots of Merb.</content><creator>taelor</creator><published_at type='date'>2008-06-29</published_at><created_at type='date'>2008-08-05</created_at><updated_at type='date'>2008-08-05</updated_at></post></posts>