<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-719065923860450374</id><updated>2011-12-30T22:17:14.651-08:00</updated><category term='ruby rest dojo components'/><title type='text'>MysteryCoder</title><subtitle type='html'></subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://mysterycoder.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/719065923860450374/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://mysterycoder.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>MysteryCoder</name><uri>http://www.blogger.com/profile/12085440439301444384</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_cYfx1Pq0Irc/TOXJ5wxxOVI/AAAAAAAAABQ/bDRzQsFRG6E/S220/Photo%2B15.jpg'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>31</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-719065923860450374.post-6247372958032224440</id><published>2011-07-10T17:18:00.000-07:00</published><updated>2011-07-10T17:18:15.372-07:00</updated><title type='text'>Why it's the late Cretaceous for server side MVC frameworks</title><content type='html'>We're at an inflection point with web application development. &amp;nbsp;I've been developing web applications for 15+ years, and it seems like we're at a familiar place. &amp;nbsp;The last time I remember being here was in the late 90s when the first server side MVC frameworks started becoming popular. &amp;nbsp;Up til that point, most of the web applications were big lumps of code that handled a request and returned some html. &amp;nbsp;For the most part, apps glommed together strings of html and sent back. &amp;nbsp;Next we got to html with embedded code, &amp;nbsp;and that was an improvement but still things were a mass. &amp;nbsp;We had no concept of separation of concerns, no good way to organize our code. &amp;nbsp;SQL was spread willy nilly amongst the angle brackets. &amp;nbsp;It was baaaaad.&lt;br /&gt;&lt;br /&gt;And then someone had the idea to apply the Model View Controller pattern to web development. &amp;nbsp;Frameworks to do so abounded. &amp;nbsp;I wrote my own, and then abandoned it when the world standardized on Struts, which was, at the time, A Good Thing. &amp;nbsp;Web browsers in this era were fairly dumb, so it was clear where the code need to be for such a framework: on the server. &amp;nbsp;The interaction with web browsers was strictly limited to a request/response cycle. &lt;br /&gt;&lt;br /&gt;Over the past 10 years or so, the basic idea of a server side MVC framework has remained the predominant way to develop web applications. &amp;nbsp;Variations such as component oriented frameworks like Tapestry and WebObjects have emerged, but the core idea of a server side framework that handles requests and returns responses and manages the UI and navigation for the application remains pretty much unchanged. &amp;nbsp;If you look at Struts from 2000, you easily recognize many of the same pieces as you will find in ruby on rails of 2011. &amp;nbsp;This for a good reason: server side MVC has been a great way to develop web applications for most of this time.&lt;br /&gt;&lt;br /&gt;In the last few years, I've felt this start to shift. &amp;nbsp;Web application UIs have gotten more interactive, dynamic, and sophisticated. &amp;nbsp;The limitation of the request/response cycle during an application has started to feel positively archaic. &amp;nbsp;Having to reload the whole page to see what happened when I attempt to perform an action just isn't cutting it when so many apps have proved we can do better. &amp;nbsp;Server side frameworks have done their best to adapt and allow for richer UIs. &amp;nbsp;But as clients get richer, it becomes clear that a lot more UI logic has to be on the client. &amp;nbsp;Eventually it becomes unclear where to put what. &amp;nbsp;Our clean separation of concerns begins to break down. &amp;nbsp;We are back to a mess.&lt;br /&gt;&lt;br /&gt;I'm going to suggest that it's time to do something radical: Let's stop.&lt;br /&gt;&lt;br /&gt;Server side MVC frameworks have served us nobly, and we should thank them for their years of service. &amp;nbsp;But it's time to move on. &amp;nbsp;We need to embrace a different architecture for web application development. &amp;nbsp;UI logic needs to be on the client. &amp;nbsp;Communication with back end services and persistence stores can take place via RESTful HTTP calls with JSON payloads. &amp;nbsp;Server side code doesn't go away, but it assumes a new place with more limited responsibilities.&lt;br /&gt;&lt;br /&gt;This is a big change. &amp;nbsp;A lot of our skills as web developers will need to be updated or replaced. &amp;nbsp;But the ecosystem for building these kinds of application is booming. &amp;nbsp;Many of the things that made developing applications in this manner painful a few years ago are dramatically different. &amp;nbsp;Unit testing tools like Jasmine abound. &amp;nbsp;A better javascript syntax thanks to coffeescript makes our code much more enjoyable to write. &amp;nbsp;And frameworks like Backbone.js give us a clear separation of concerns while we build applications in this new way. &lt;br /&gt;&lt;br /&gt;As I've started developing apps this way, I've been really excited by the results. &amp;nbsp;The frustrations and&amp;nbsp;foreboding&amp;nbsp;sense of "this doesn't feel right" I found developing rich client apps with server side MVC is completely gone. &amp;nbsp;It definitely took some time to change over, but I wouldn't go back.&lt;br /&gt;&lt;br /&gt;There's a lot to learn though. &amp;nbsp;To give you a jump start we've put together a &lt;a href="http://gaslightsoftware.com/beautiful-front-end-code.html"&gt;two day training class&lt;/a&gt; so that you can jump in and be productive immediately. &amp;nbsp;We hope that you'll join us in Cincinnati on September 8th and 9th.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/719065923860450374-6247372958032224440?l=mysterycoder.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mysterycoder.blogspot.com/feeds/6247372958032224440/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=719065923860450374&amp;postID=6247372958032224440' title='17 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/719065923860450374/posts/default/6247372958032224440'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/719065923860450374/posts/default/6247372958032224440'/><link rel='alternate' type='text/html' href='http://mysterycoder.blogspot.com/2011/07/why-its-late-cretaceous-for-server-side.html' title='Why it&apos;s the late Cretaceous for server side MVC frameworks'/><author><name>MysteryCoder</name><uri>http://www.blogger.com/profile/12085440439301444384</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_cYfx1Pq0Irc/TOXJ5wxxOVI/AAAAAAAAABQ/bDRzQsFRG6E/S220/Photo%2B15.jpg'/></author><thr:total>17</thr:total></entry><entry><id>tag:blogger.com,1999:blog-719065923860450374.post-6155606486462674218</id><published>2011-05-30T09:31:00.000-07:00</published><updated>2011-05-30T09:34:18.680-07:00</updated><title type='text'>Managing coffeescript/js dependencies with the Rails 3.1 asset pipeline</title><content type='html'>We've been using and loving coffeescript and backbone on my current project. &amp;nbsp;In the last couple days we've upgraded our project to rails 3.1rc1 and been able to take advantage of the new asset pipeline therein. &amp;nbsp;This feature elegantly solves some super annoying problems we've had with managing dependencies in our app, but is not yet well documented. &amp;nbsp;I thought I'd take a few minutes and share what I've learned. &lt;br /&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-size: large;"&gt;Where the assets live&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Before rails 3.1, we'd lump all our javascript and stylesheets in the "junk drawer" that is public. &amp;nbsp;No more. &amp;nbsp;Now they can go in 3 different dirs depending on their purpose:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;app/assets for things that our your application code&lt;/li&gt;&lt;li&gt;lib/assets for shared-ish things (not sure I grok what I'd put here yet)&lt;/li&gt;&lt;li&gt;vendor/assets to put things that your app uses but is provided by others&lt;/li&gt;&lt;/ul&gt;These directories are magically put on the asset pipeline for you. &amp;nbsp;In your views, you can reference things in any of these directories under the prefix /assets, eg. if foo.js was in app/assets (or lib or vendor) you would refer to it as /assets/foo.js. &amp;nbsp;The rails helpers such as javascript_include_tag will do this for you.&lt;br /&gt;&lt;br /&gt;So this gives places to put stuff, which is nice, but only the beginning. &amp;nbsp;The killer features (for me) are the ability to package assets and manage dependencies. &amp;nbsp;To see how this works, take a look the app/assets/application.js file you get when generate a new rails 3.1 app.&lt;br /&gt;&lt;script src="https://gist.github.com/998193.js?file=application.js"&gt;&lt;/script&gt;&lt;br /&gt;Nothing but comments, weird huh.  That's because this is what we're calling a "manifest file" which is basically just a file that requires in other files.  When you include /assets/application.js at runtime, rails will package all the files you required and concatenate (and optionally minimize) them.  Let's look at those last 3 lines, as there's magic in them thar comments.  The first 2 require in jquery and jquery_ujs.  It seems like this must mean that there are jquery.js and jquery_ujs.js files somewhere in one of the assets directories, but this isn't so.  That's because gems can contribute to the asset pipeline as well.  More on this later.  The last line says to include all files in this directory or subdirectories as well. &amp;nbsp;In our apps so far we find it nice to have 2 such manifest files, vendor/assets/javascripts/vendor.js and app/assets/javascripts/application.js. &amp;nbsp;Not sure I can call this "best practice" or not yet, just that it seems nice to us so far.&lt;br /&gt;&lt;br /&gt;It's also worth pointing out that files that need to processed (eg coffeescript and sass) will be handled automatically as well.  Simply drop a file named whatever.coffee into the /app/assets directory and it will be compiled and included into application.js&lt;br /&gt;&lt;br /&gt;Where this all gets more interesting to me is where we have files in the application that depend on each other.  Files that are required can have requires of their own.  The example I have in my app is coffeescript class inheritance.  Imagine a couple classes like so:&lt;br /&gt;&lt;script src="https://gist.github.com/999077.js?file=fruit.coffee"&gt;&lt;/script&gt;&lt;br /&gt;&lt;script src="https://gist.github.com/999082.js?file=apple.coffee"&gt;&lt;/script&gt;&lt;br /&gt;When you're building apps with a lot of front end code, it's to be able to organize code with each class in it's own file.  But this means you have to make sure to have the script that brings in fruit before apple.  With the ability to require in rails 3.1, this problem is nicely solved for us.  If we add a require statement to apple.coffee like so, the asset pipeline will take care of making sure things are in the correct order:&lt;br /&gt;&lt;script src="https://gist.github.com/999091.js?file=apple_with_require.coffee"&gt;&lt;/script&gt;&lt;br /&gt;This is a huge win for me, as before this I was naming files with numbers such as 1_fruit.coffee to get around this problem.  Yuck.&lt;br /&gt;&lt;br /&gt;I mentioned earlier that I'd talk about assets living in gems. &amp;nbsp;This is a feature that allows you to take front end code and easily share it between multiple projects. &amp;nbsp;In my next post I'll talk about my experience building a rails 3.1 asset containing gem.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/719065923860450374-6155606486462674218?l=mysterycoder.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mysterycoder.blogspot.com/feeds/6155606486462674218/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=719065923860450374&amp;postID=6155606486462674218' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/719065923860450374/posts/default/6155606486462674218'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/719065923860450374/posts/default/6155606486462674218'/><link rel='alternate' type='text/html' href='http://mysterycoder.blogspot.com/2011/05/managing-coffeescriptjs-dependencies.html' title='Managing coffeescript/js dependencies with the Rails 3.1 asset pipeline'/><author><name>MysteryCoder</name><uri>http://www.blogger.com/profile/12085440439301444384</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_cYfx1Pq0Irc/TOXJ5wxxOVI/AAAAAAAAABQ/bDRzQsFRG6E/S220/Photo%2B15.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-719065923860450374.post-8183937735827795859</id><published>2011-05-15T13:02:00.000-07:00</published><updated>2011-05-15T13:07:41.883-07:00</updated><title type='text'>2 easy things you can screw up in backbone</title><content type='html'>First off let's be clear. &amp;nbsp;Backbone is awesome. &amp;nbsp;It's totally changed the way I develop web applications for the better. &amp;nbsp;Before backbone, working on javascript code for a rich client web app was a miserable experience. &amp;nbsp;With backbone (and coffeescript) I'm now enjoyably writing code I can be proud of. &amp;nbsp;But because we are now developing our apps in a new way, we've found new ways to mess things up ;) &amp;nbsp;Here are a couple ways we found that could save you some hours of frustration if you avoid doing them.&lt;br /&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-size: large;"&gt;Don't have multiple views using the same element&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;This one I did early on in my backbone days the first time I had one view that created another view. &amp;nbsp;Imagine some code like the following:&lt;br /&gt;&lt;br /&gt;&lt;script src="https://gist.github.com/972628.js?file=FooView.coffee"&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;Seems ok at first.  When we click a button in FooView it creates a BarView giving it an element and telling it to render.  The problem happens the second time the button gets clicked.  At that point you have 2 instances of BarView which each use the same element.  And if those BarViews are listening to events on (or within) said element, mayhem ensues.  I've found it to work out better to write the code like so:&lt;br /&gt;&lt;br /&gt;&lt;script src="https://gist.github.com/972638.js?file=FooView2.coffee"&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;In this version the BarView is created during the render method, right after his element has been created presumably.  Then the BarView instance is displayed when needed.  I've found this to be a good rule of thumb: backbone view objects should have the same life cycle as their elements.  They should be created when their elements are created and destroyed when they are removed.&lt;br /&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-size: large;"&gt;Beware model defaults that initialize complex attributes&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;The second gotcha I've run into cost us a good few hours today actually. &amp;nbsp;Backbone models have a nice feature for allowing default attributes. &amp;nbsp;It's a handy feature, but by using it to initialize array or object properties we found it caused a subtle (to us) but pretty terrible bug. &amp;nbsp;In our model we had code like so:&lt;br /&gt;&lt;br /&gt;&lt;script src="https://gist.github.com/973326.js?file=Foo.coffee"&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;The problem here is what happens when you create a second Foo.  Turns out backbone does a shallow clone of defaults, which means the same array object in memory is used for both.  This spec describes the problem nicely:&lt;br /&gt;&lt;br /&gt;&lt;script src="https://gist.github.com/973337.js?file=foo_spec.coffee"&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;Turns out there is a pretty easy fix for this too.  Defaults don't have to be an object literal, they can also be a function and backbone will be smart enough to invoke it to build the model's attributes.  In coffeescript, this fix is exactly 2 characters:&lt;br /&gt;&lt;br /&gt;&lt;script src="https://gist.github.com/973344.js?file=Foo.coffee"&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;Hopefully these two tips will save you some frustration as you dig deeper into backbone.  In a future post I'll share some of the code we've refactored out of our app that we feel like is generally useful for other backbone + coffeescript + rails apps.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/719065923860450374-8183937735827795859?l=mysterycoder.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mysterycoder.blogspot.com/feeds/8183937735827795859/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=719065923860450374&amp;postID=8183937735827795859' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/719065923860450374/posts/default/8183937735827795859'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/719065923860450374/posts/default/8183937735827795859'/><link rel='alternate' type='text/html' href='http://mysterycoder.blogspot.com/2011/05/2-easy-things-you-can-screw-up-in.html' title='2 easy things you can screw up in backbone'/><author><name>MysteryCoder</name><uri>http://www.blogger.com/profile/12085440439301444384</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_cYfx1Pq0Irc/TOXJ5wxxOVI/AAAAAAAAABQ/bDRzQsFRG6E/S220/Photo%2B15.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-719065923860450374.post-5785850873677266094</id><published>2011-03-13T20:05:00.000-07:00</published><updated>2011-03-14T06:51:38.448-07:00</updated><title type='text'>CoffeeScript + Backbone.js + Rails = Superfantasticalness</title><content type='html'>Lately I've been working on application by writing the front end in &lt;a href="http://coffeescript.org/"&gt;CoffeeScript&lt;/a&gt; using &lt;a href="http://documentcloud.github.com/backbone/"&gt;Backbone.js&lt;/a&gt; and the back end in Rails.  A few people have asked me about it and so I thought I'd share my experience so far.&lt;br /&gt;&lt;br /&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-size: large;"&gt;Backbone.js&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I've been looking for a front end javascript framework for quite awhile, ever since I realized that server side MVC frameworks were probably coming to the end of their time in the sun. &amp;nbsp;I've even tried several aborted attempts to write one.  I've spent good amounts of time playing around with both Sproutcore and JavascriptMVC, but when I picked up Backbone.js I didn't want to put it down again.  I don't really want to spend the time right now to delve into critiques of the other two, so I'm going to focus on what I like about Backbone.js&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;For me, the big attraction of Backbone is there's so little to it. &amp;nbsp;Earlier in my career, I was enamored by frameworks and tools that did "everything I would ever need". &amp;nbsp;The idea of learning one environment where I could do everything was appealing. &amp;nbsp;I was attracted by neato whiz bang features even I didn't need them just yet. &amp;nbsp;But as I've grown older and more curmudgeonly, I now prefer tools that just barely do what I need and then stay out of the way. &amp;nbsp;In my mind pivotal tracker is such a tool. &amp;nbsp;Backbone.js &amp;nbsp;feels like this too. &amp;nbsp;It provides a nice structure for the code of a rich client web MVC application. &amp;nbsp;It allows me to continue to use html, css, and jquery without insisting that I give up one of these or do all my design and layout in javascript. &amp;nbsp;I prefer to work a designer who can create visually appealing UI in html/css, so frameworks that don't accomodate this workflow are a non-starter for me.&lt;br /&gt;&lt;br /&gt;I don't intend this to be a Backbone.js guide, the excellent documentation is where to go for that. &amp;nbsp;But I'll briefly touch on my experience with the different pieces I've used thus far.&lt;br /&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-size: large;"&gt;Views&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;The first Backbone code I wrote was a view. &amp;nbsp;I had started building my app in the usual (for me) way of just adding a some jquery to make my client side UI more dynamic. &amp;nbsp;But this time, when it started to get unmanagable as it always does, I refactored it into a Backbone View. &amp;nbsp;This is just a "class" that extends from Backbone.View. &amp;nbsp;The only thing this does for you is allow you to specify an element that the view contains, and a set of events scoped within this element that bind to functions of your view. &amp;nbsp;But it turns out this feels just right for organizing my code. &amp;nbsp;In my case I ended with a tree view component that uses jstree to do a lot of the heavy lifting. &amp;nbsp;Later on, I actually extracted it into a superclass and reused it on a couple other pages. &amp;nbsp;Over time I've found that my view classes tend to end up as nicely reusable components.&lt;br /&gt;&lt;br /&gt;Interestingly, backbone views don't mandate any particular choice for producing the html. &amp;nbsp;After some experimentation, we came up with a convention we like on our project. &amp;nbsp;Each of our views generally has a template file, we're using mustache right now so the files are named things like foo_view.mustache.html. &amp;nbsp;Originally we were just embedding our templates into our rails views as hidden divs or in script tags. &amp;nbsp;But we found ourselves repeating the same markup in our jquery-jasmine fixtures, and this made us sad so we searched for a better way. &amp;nbsp;We settled on having templates in a separate file, and then wrote a rails helper method that renders the views template on the page. &amp;nbsp;We also wrote a jasmine jquery method that loads the template into a fixture so we can use them in our specs as well. &amp;nbsp;Here's what that code looks like, if anyone else wants it:&lt;br /&gt;&lt;script src="https://gist.github.com/868660.js?file=jasmine.jquery.load_template.js"&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;There are a couple of other things worth passing along we've learned working with Backbone views. &amp;nbsp;The first is that you really want to have your view's element have the same lifespan as your view object. &amp;nbsp;I ran into this issue by creating new view objects inside the listener method of another view. &amp;nbsp;There's nothing inherently wrong with this (that I know of), but in my case the element for the view I was creating already existed. &amp;nbsp;The net effect was that if if the listener method that created the view was called multiple times you could end up with a multiple views listening to events on the same DOM element. &amp;nbsp;This caused no end of confusion. &amp;nbsp;It was a much better idea to create the view once and just reuse-it as needed with different models (as necessary).&lt;br /&gt;&lt;br /&gt;The other idea I feel like we're learning is how to communicate between models and views. &amp;nbsp;We regularly have views talk directly to models, getting and setting properties, telling models to persist themselves, etc. &amp;nbsp;But when it comes time for models to communicate with views, it really feels right to use the Backbone event framework. &amp;nbsp;There are a set of nice built in events on models, and it is trivial to add your own. &amp;nbsp;It's worked out well for models to trigger events when interesting things happen and let the views listen to them and do what they will. &amp;nbsp;So our best practice is shaping up that views can interact with models, including listening to events from them, but models should never talk to views directly. &amp;nbsp;It would probably seem obvious to do it this way for anyone coming from rails-land, but I thought it might be worth mentioning anyways.&lt;br /&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-size: large;"&gt;Models&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Backbone.js models know how to speak json to a restful back end out with little to no coding required. &amp;nbsp;This ended up being a pretty big selling point for me, as it made it trivially to integrate Backbone with my rails app and it pretty much Just Worked. &amp;nbsp;The only gotcha here is that rails would prefer to have the attributes for a model be grouped into a name parameter, but telling backbone to do this as as trivial as the following code:&lt;br /&gt;&lt;br /&gt;&lt;script src="https://gist.github.com/868693.js?file=Foo.coffee"&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;I guess the biggest difference working with Backbone models than Rails models is that everything is asynchronous. &amp;nbsp;Calling a fetch (think find in rails) or a save in backbone means you also have to specify a function to invoke on success or failure, or listen to an event. &amp;nbsp;This would seem to add up to a lot of extra code, were it not for...&lt;br /&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-size: large;"&gt;Coffeescript&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;I've been searching for Coffeescript without realizing it for many years. &amp;nbsp;I've been treating javascript as a first class language for a few years, test driving, trying to use clearly communicative object oriented design, etc. &amp;nbsp;This has made the experience of writing javascript immensely more satisfying, and I hope, helped me produce higher quality code. &amp;nbsp;But it's always chafed a bit. &amp;nbsp;I didn't get to choose javascript. &amp;nbsp;There's a lot of syntax is in it that I don't like, and feels noisier than I wish it was. &amp;nbsp;I spent a good amount of time looking for solutions to let me use a language of my choosing in the browser, but in the end they've all fallen short.&lt;br /&gt;&lt;br /&gt;Until now. &amp;nbsp;Coffeescript is a lovely language that compiles into readable, &lt;b&gt;debuggable&lt;/b&gt;, javascript. &amp;nbsp;It's documentation is fantastic and it's source code is beautifully documented. &amp;nbsp;The most annoying bits of javascript go away, and the coffescript code I've written is so much cleaner and less noisy it's been a joy to use. &amp;nbsp;I'm finding it difficult to convey how big a deal coffeescript is. &amp;nbsp;Someone smart I know responded to coffeescript allegedly by saying "But isn't it just nicer syntax?". &amp;nbsp;Yes it is! &amp;nbsp;And it turns out this is incredibly valuable and important. &amp;nbsp;I chose ruby because I can express my intent, in elegant, readable code. &amp;nbsp;Coffeescript feels the same way to me. &amp;nbsp;But I can use Coffeescript in all the places I would have had to use javascript before. &amp;nbsp;It's been huge to me. &amp;nbsp;I'm pretty much at the point where I'll go back to writing javascript when you pry Coffeescript from out of my hands. &lt;br /&gt;&lt;br /&gt;Though I dig backbone a lot, it's still possible one of the other frameworks might mature into something awesome and be the way to go. &amp;nbsp;Coffeescript, on the other hand, doesn't appear to have anything close.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/719065923860450374-5785850873677266094?l=mysterycoder.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mysterycoder.blogspot.com/feeds/5785850873677266094/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=719065923860450374&amp;postID=5785850873677266094' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/719065923860450374/posts/default/5785850873677266094'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/719065923860450374/posts/default/5785850873677266094'/><link rel='alternate' type='text/html' href='http://mysterycoder.blogspot.com/2011/03/coffeescript-backbonejs-rails.html' title='CoffeeScript + Backbone.js + Rails = Superfantasticalness'/><author><name>MysteryCoder</name><uri>http://www.blogger.com/profile/12085440439301444384</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_cYfx1Pq0Irc/TOXJ5wxxOVI/AAAAAAAAABQ/bDRzQsFRG6E/S220/Photo%2B15.jpg'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-719065923860450374.post-2349908298071324437</id><published>2010-11-18T16:52:00.000-08:00</published><updated>2010-11-18T19:31:11.657-08:00</updated><title type='text'>Highlights of rubyconf</title><content type='html'>So here is my rubyconf recap, in no particular order:&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;As always, I enjoyed tenderloves presentation.  He's always hilarious, and this year was no exception.  This year he really hit the technical material hard and did an excellent job.  It was all about the performance tuning and eventual rewrite of Arel.  It was a practical deep dive into how to improve the performance of your ruby code.  Awesome stuff, definitely worth catching on confreaks.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I was also inspired by DHH's talk.  He was basically talk about why he loved ruby.  I really liked his thoughts about rejecting the "best tool for the job" idea as if we choose a programming language based on a feature matrix.  For me it was the same: ruby code made me happy.  What got me inspired though, is that I feel a lot of the same kind of almost giddy happiness about my coffeescript code.  &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;So I've spent time trying to learn write the best javascript I can.  It's certainly got some nice features and is not as terrible as people make it out to be.  I can write code that I'm pleased with, and gets the job done.  But the fact is, I didn't choose the language, the browsers did.  With coffeescript on the other hand, all the most annoying things about javascript are just gone.  The code I've written (not enough yet, mind you) comes out just so sparse, elegant, and communicative that it makes me feel all warm and fuzzy.  It really is much like how I first felt (and still feel) about ruby.  &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I gave a very lame 3 minute lightning talk on coffeescript on Sunday, and got to talk to a few other people that seem as excited about it as I am.  It also felt very reassuring to talk to DHH and one of the other 37 signals guys, Sam Stephenson, about their use of it and how impressed we both are with backbone.js as well.  It's still early time here but I can't wait to see how things develop.  It's exciting.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Another session I really enjoyed was the redcar session.  I was already geeked about redcar before, but after seeing Dan crank out a plugin live in a few minutes I got excited and have been coding on it ever since in my spare hacking moments.  I managed to fix a bug (turns out it only happened because I was a version of date with Safari) and then coded up a plugin for the feature I wanted the most, running a single test by name based on where the cursor is.  It only talk an hour or two while waiting for a flight.  I don't think I've ever had an editor where coding in it was actually FUN.  It's quite empowering.  There's still lots and lots to do.  Hope I can keep finding some spare to time to hack.  It's also worth noting that I've been productively using redcar for real coding for all of this week.  Rubymine, I loved you for a time, but in the end the performance woes made you too frustrating.  Best wishes and fond regards, we wrote some lovely codes together.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;And of course, the Polite Programmers session.  There were definitely some issues.  The banter back and forth didn't seem to work as well as I hoped.  Jim left me my openings, I just got nervous and had trouble coming up with natural sounding responses.  But we got lots of positive reviews, and it's always a privilege to present and learn from Jim.  Ed did a fine job as Mr. Manners as well, what with his inimitable cultured accent and all :)&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Can't wait for next year!&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/719065923860450374-2349908298071324437?l=mysterycoder.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mysterycoder.blogspot.com/feeds/2349908298071324437/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=719065923860450374&amp;postID=2349908298071324437' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/719065923860450374/posts/default/2349908298071324437'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/719065923860450374/posts/default/2349908298071324437'/><link rel='alternate' type='text/html' href='http://mysterycoder.blogspot.com/2010/11/highlights-of-rubyconf.html' title='Highlights of rubyconf'/><author><name>MysteryCoder</name><uri>http://www.blogger.com/profile/12085440439301444384</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_cYfx1Pq0Irc/TOXJ5wxxOVI/AAAAAAAAABQ/bDRzQsFRG6E/S220/Photo%2B15.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-719065923860450374.post-8997066542830033845</id><published>2010-07-14T14:08:00.000-07:00</published><updated>2010-07-14T15:55:00.547-07:00</updated><title type='text'>JSpec tests running in CI</title><content type='html'>A lot of people, myself included, have been TDDing our javascript for awhile but it seems like it's still fairly rare for the tests to be run in the CI build.  I've taken some time today to get our existing suite of JSpec tests to run in our CI server (Hudson in our case) and thought I would share what I did.  My general approach should be useful regardless of which CI server you are using.  &lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;It's actually fairly simple: I'm using the capybara selenium driver to run the JSpec tests and grab the results from the DOM when they finish.  Here's the testcase:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;script src="http://gist.github.com/476200.js"&gt;&lt;/script&gt;&lt;/div&gt;I define an array of all my jspec tests, loop over them, munge them into a legal test method name and define a method that delegates to run_jspec.  run_spec opens a file url (had to go underneath capy here so its a little icky) and then waits for the .failures div to appear.  It should be noted that capybara will wait for an element to appear when you call page.has_css?&lt;div&gt;&lt;br /&gt;From here, running it under CI is trivial.  In fact I didn't have to do anything at all, the tests was found by rake test:integrations and ran (and passed!) in the next build.  Most of the heavy lifting is done by capybara and selenium-webdriver.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Obviously there is a lot that could be done to improve this code.  I could grab the jspec file from a FileList, and grab some better failure messages from the DOM.  I could also probably write a custom JSpec formatter to make this easier on myself even.  I'm thinking if there is interest I could finish this up and turn it into a gem.  Please comment if you'd use such a thing.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Also, one more thing you will need is the JSpec runner file that can run a single test.  I did that like so:&lt;/div&gt;&lt;div&gt;&lt;script src="http://gist.github.com/476209.js"&gt;&lt;/script&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Enjoy!&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/719065923860450374-8997066542830033845?l=mysterycoder.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mysterycoder.blogspot.com/feeds/8997066542830033845/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=719065923860450374&amp;postID=8997066542830033845' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/719065923860450374/posts/default/8997066542830033845'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/719065923860450374/posts/default/8997066542830033845'/><link rel='alternate' type='text/html' href='http://mysterycoder.blogspot.com/2010/07/jspec-tests-running-in-ci.html' title='JSpec tests running in CI'/><author><name>MysteryCoder</name><uri>http://www.blogger.com/profile/12085440439301444384</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_cYfx1Pq0Irc/TOXJ5wxxOVI/AAAAAAAAABQ/bDRzQsFRG6E/S220/Photo%2B15.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-719065923860450374.post-8238472614661949521</id><published>2009-01-31T08:54:00.000-08:00</published><updated>2009-01-31T12:34:22.873-08:00</updated><title type='text'>Why don't I pair more?</title><content type='html'>I've been watching a video of the hashrocket guys just now that Corey Haines twittered about.  I've been amazed and inspired by Corey's &lt;a href="http://programmingtour.blogspot.com/"&gt;pair programming tour&lt;/a&gt;: talk about turning lemons into lemonade.  What an awesome idea.   I've paired with Corey on some open source stuff at conferences, so I naturally wanted to get in on his tour.  As a result I had the good fortune to have Corey stay with me on his tour.  Unfortunately the timing of his stop happened on a day I had to spend dealing with client issues and didn't get to spend time pairing with him.  And this leads into my topic: Why don't I pair more?&lt;br /&gt;&lt;br /&gt;This isn't another post about why pair programming doesn't work, isn't a good idea, or any other such nonsense.  I'm a true believer in pair programming.  I've been sold on the concept since I first read about it in the first edition of Kent Beck's &lt;span style="font-style: italic;"&gt;Extreme Programming&lt;/span&gt; late in the prior millenium.  I've experienced pair programming and so I know the benefits first hand:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;It consistently produces the best code, the code I'm proudest of in my entire career.  And not a little prouder of.  I mean, like, an order of magnitude more proud of.&lt;/li&gt;&lt;li&gt;I'm operating at about twice the velocity I would normally, which is a rush, and incidentally, means there is no negative effect on team velocity.  I've actually measured this on a real project.&lt;/li&gt;&lt;li&gt;I learn way more&lt;/li&gt;&lt;li&gt;I enjoy my job way more&lt;/li&gt;&lt;/ul&gt;And on an on.  But that's not what I actually want to talk about.  This post is a way for me to put down in writing the reasons that I don't pair nearly as much as I want to.  I'm doing this chiefly as an exercise so I can better understand the issues and change them.  If it helps someone else, hey, that's pure bonus.  The first few are about me.  Which is good news, because it means I can change them.&lt;br /&gt;&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Part of me is afraid to&lt;br /&gt;I'll just go ahead and lead with this one since it's the hardest to talk about.  I really like how the hashrocket guy put it: "Pairing is a burning crucible".  Heat reveals impurities and exposes the true nature of things.   If I'm having a self-doubting, insecure kind of day, I might not want this.  Intellectually I'm totally convinced this is BS and the benefits far outweigh the minor pain of revealing what's obvious to everyone: I don't know everything.  I like to think this reason is not a major factor preventing me from pairing, but in the interest of self-disclosure I'm putting it out there.&lt;/li&gt;&lt;li&gt;But I might not get &lt;span style="font-weight: bold;"&gt;my&lt;/span&gt; stuff done&lt;br /&gt;This one is a bit more insidious, but like the prior reason begins with self-centered fear.  If I pair on your task, I might not get mine done.  And conversely if you help me you might not get yours done.  There are at least two ways to address this.  The first is to get over it: I believe that the software I produce will be way better if I pair.  And obviously producing better software is what's best for me and whoever I work for.  I have to be clear on this and act on it, which in my experience is not always easy.  And of course the other members of my team do as well.&lt;br /&gt;The other way to fix this is organizationally: don't assign tasks to individuals.  I've been in situations where this was out of my control.  Some clients like having a single "go to" person for a given feature or issue.  But this doesn't have to stop pair programming if the team doesn't let it.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Inertia&lt;br /&gt;This one is a little more nebulous but I don't think it's less real.  Sometimes I don't pair because I don't put forth enough effort to find someone to pair with.  Other times I might be "in the middle of something".  Either of these fall into the same general category of inertia: an object at rest (me, by myself, in front of my computer) tends to stay at rest.&lt;/li&gt;&lt;/ol&gt;The next few are harder to change, because they are about other people.  Obviously I can't pair program if no one will pair with me.  And no matter how much I would like to and am &lt;span style="font-style: italic;"&gt;sure&lt;/span&gt; I know what's best for them, I can't actually control other people.  But I'm going to list these issues anyways in the hopes that solutions will become clearer if we understand the problems.&lt;br /&gt;&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Odd number of people on your team&lt;br /&gt;This is so obvious an issue it seems silly to put down, but I've seen it make a big impact.  I know the song says "One is the loneliest number" but three is also not very good.  What tends to happen is pairing becomes awkward as one gal or guy is left out and sometimes leads to little or no pairing at all.  I suppose you could address this by making a pair your smallest unit of staffing a project.  But it's also true that even if you have 3 people on your team you could still pair 2/3 of the time if you are intentional about it.&lt;/li&gt;&lt;li&gt;Distributed team&lt;br /&gt;Remote pair programming is a whole nother topic and I have some experience with it that perhaps I'll share in another post.  Suffice to say: it's not as good as pairing in person, but better than not pairing at all.  Because there are some technical details to work out and do, there is that much more barrier to overcome and it requires even more sustained effort to keep up.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;They won't let me&lt;br /&gt;This is supposed to be the elephant in the room: management won't let me pair program.  My thinking is that this one is mostly a myth.  I've worked in a lot of places, some of them quite draconian.  The truth however is that pair programming can start so innocuously that it's hard to have a mandate against it.  Imagine management saying: you're not allowed to help other people.  Even the pointiest of pointy haired bosses would see how stupid that is.  I'm sure someone will comment that "No, that really does happen".  Fine.  I just don't think it's all that common.  Most people, in my experience, actually do want to be useful and contribute something positive.  They just may (wildly) disagree about how best to do so.&lt;/li&gt;&lt;li&gt;They code in X and X sucks&lt;br /&gt;This one requires compromise, but can be a a positive sometimes if you let it.  My first ruby project I got to pair with my friend &lt;a href="http://onestepback.org"&gt;Jim&lt;/a&gt;, a dedicated emacs guy.  As a result I had to learn emacs, something which I probably wouldn't have decided to do if I hadn't see what a productive environment it is first hand.  There are other times where I pair with someone and they use something and even after trying it I still think it sucks.  In that situation I try to get them to always pair on my machine.  Err, I mean, switch back and forth between each others machines in the interest of fairness ;)&lt;br /&gt;&lt;/li&gt;&lt;li&gt;No one wants to pair (except me)&lt;br /&gt;Alas, this has been the hardest to solve.  You can be fortunate enough to work for (or start) a company that mandates pair programming.  Or else you can attempt to influence people.  My only advice, based on experience, is that less is more.  Don't talk about pair programming at all, just offer to help people.  And then ask for help when you're stuck.  I've sadly tried the approach of trying to convert people to pair programming, unit testing, or any other number of quite good ideas by incessantly talking to people about them.  Don't do this.&lt;br /&gt;&lt;/li&gt;&lt;/ol&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/719065923860450374-8238472614661949521?l=mysterycoder.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mysterycoder.blogspot.com/feeds/8238472614661949521/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=719065923860450374&amp;postID=8238472614661949521' title='12 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/719065923860450374/posts/default/8238472614661949521'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/719065923860450374/posts/default/8238472614661949521'/><link rel='alternate' type='text/html' href='http://mysterycoder.blogspot.com/2009/01/why-dont-i-pair-more.html' title='Why don&apos;t I pair more?'/><author><name>MysteryCoder</name><uri>http://www.blogger.com/profile/12085440439301444384</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_cYfx1Pq0Irc/TOXJ5wxxOVI/AAAAAAAAABQ/bDRzQsFRG6E/S220/Photo%2B15.jpg'/></author><thr:total>12</thr:total></entry><entry><id>tag:blogger.com,1999:blog-719065923860450374.post-1103198702907383398</id><published>2009-01-15T19:50:00.000-08:00</published><updated>2009-01-15T20:47:52.167-08:00</updated><title type='text'>Announcing Edit Me: a teeny weeny CMS plugin for Rails</title><content type='html'>I've been working for awhile on Rails plugin that makes it easy for users to edit their own content.  I started it to scratch an itch I've had for a long time.   The problem I have with most CMS systems is that they want run your whole site.  Sometimes this is ok, but a lot of times you have a rails app where you have pieces of it that it would be nice to to let your client edit for example.  For those cases, the edit_me plugin is your friend.&lt;br /&gt;&lt;br /&gt;The idea is pretty simple: when in editing mode, edit_me gives you an edit icon next to the content produced by rhtml and html.erb files (you can configure which files you want to be editable).  Click the edit icon and up pops an editor (using wymeditor).  Save your changes and the page reloads with your changes.  Edit me assumes you're using git (why wouldn't you?) and lets your roll back your changes in the History tab of the editor.&lt;br /&gt;&lt;br /&gt;To check it out, head on over to http://github.com/superchris/edit_me/tree/master and follow the instructions in the README.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/719065923860450374-1103198702907383398?l=mysterycoder.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mysterycoder.blogspot.com/feeds/1103198702907383398/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=719065923860450374&amp;postID=1103198702907383398' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/719065923860450374/posts/default/1103198702907383398'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/719065923860450374/posts/default/1103198702907383398'/><link rel='alternate' type='text/html' href='http://mysterycoder.blogspot.com/2009/01/announcing-edit-me-teeny-weeny-cms.html' title='Announcing Edit Me: a teeny weeny CMS plugin for Rails'/><author><name>MysteryCoder</name><uri>http://www.blogger.com/profile/12085440439301444384</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_cYfx1Pq0Irc/TOXJ5wxxOVI/AAAAAAAAABQ/bDRzQsFRG6E/S220/Photo%2B15.jpg'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-719065923860450374.post-7208275457947902210</id><published>2008-10-18T19:45:00.000-07:00</published><updated>2008-10-18T19:54:48.877-07:00</updated><title type='text'>"Fun" with Hook Methods in Ruby</title><content type='html'>I've been wrestling with what turned out to be a rather interesting issue involving ruby hook methods.  I don't yet have a solution to the problem but perhaps the activity of describing the problem in writing will illuminate a solution.  Hook methods in ruby are callback methods you can implement in your code to get notified at interesting points in the lifecycle of a ruby object.  The one which caused trouble in my case is inherited.  By implementing the inherited method in a class you can get called back when another class inherits from  it.  It's quite useful when you want to do something like record each descendant of a given class, for example.&lt;br /&gt;&lt;br /&gt;I ran into an issue with inherited while trying to understand a very strange behaviour in my IDE of choice, NetBeans.  When running my rails test cases from NetBeans, I noticed they were not transactional, but when run on the command line they were.  After sending a flame-o-gram which I will soon need to retract to the nb ruby mailing list, I decided to poke around in their code.  I finally narrowed the problem down to their testrunner code. &lt;br /&gt;&lt;br /&gt;In the newest version of NetBeans they have added a nicer ruby testrunner.  In order to provide some features this new testrunner keeps track of all descendants of Test::Unit::TestCase.  It does this, by, you guessed it, using the inherited method.  When I delved into this code the first problem I saw was pretty obvious.  The author had violated what I will now credit my friend Jim by referring to as Weirich's Hook Method Implementation Commandment:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Thou Shalt Always Delegate to the Previous Implementation&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;The reason this is important is that when you implement a hook method, you can easily step on someone else who had implemented it for another reason.  Using the rails alias_method_chain will normally take care of this for you, but because this code loads before rails they didn't have that option and had not done the right thing and delegated explicitly.&lt;br /&gt;&lt;br /&gt;And sure enough, I noticed that when I commented out the inherited method in the testrunner my tests became transactional.  I figured at this point I had it licked.  I went ahead and changed the NB testrunner code to delegate correctly and tried again.  Sadly, it had no affect on the transactional issue.  Much head scratching ensued.  After many hours of investigation, I finally tracked down the real problem.  I noticed that the use_transactional_fixtures class attribute of Test::Unit::TestCase was not being set.  This led me to investigate how class_inheritable_attributes works in rails.  Eventually I was able to put together a failing test case which expresses the problem.  Here it is:&lt;br /&gt;&lt;pre name="code" language="ruby"&gt;&lt;br /&gt;require File.dirname(__FILE__) + '/inheritable_accessor'&lt;br /&gt;require File.dirname(__FILE__) + '/../test_helper'&lt;br /&gt;&lt;br /&gt;class A&lt;br /&gt;  class_inheritable_accessor :foo&lt;br /&gt;  self.foo = "bar"&lt;br /&gt;end&lt;br /&gt;&lt;br /&gt;class B &lt; A&lt;br /&gt;&lt;br /&gt;end&lt;br /&gt;&lt;br /&gt;class InheritableAttributesTest &lt; Test::Unit::TestCase&lt;br /&gt;&lt;br /&gt;  def test_foo&lt;br /&gt;    assert_equal "bar", B.foo&lt;br /&gt;  end&lt;br /&gt;end&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;And here what's in inheritable_accessor.rb:&lt;br /&gt;&lt;pre language="ruby" name="code"&gt;&lt;br /&gt;class A&lt;br /&gt;  class &lt;&lt; self&lt;br /&gt;    alias_method :a_old_inherited, :inherited&lt;br /&gt;    &lt;br /&gt;    def inherited(base)&lt;br /&gt;      puts "A inherited"&lt;br /&gt;      a_old_inherited(base)&lt;br /&gt;    end&lt;br /&gt;  end&lt;br /&gt;end&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;To try this at home, simply make a new rails project and drop these two files into your test/units directory.  It should fail.  But why?  The inherited method does delegates to the previous implementation correctly, right?  Now try switching the order of those two require statements.  Poof, it passes.  &lt;br /&gt;&lt;br /&gt;Turns out the problem happens because of how class_inheritable_accessor is implemented.  As you probably have guessed, it uses inherited.  And yes, it does correctly delegate to the previous implementation.  But it's where its implemented that is the problem: in order to let all classes be able to use this method, it's implemented on Class.  However, there is an unfortunate side effect to this decision: it breaks for any class loaded before this code which itself defines inherited.  In our example, the A class defines the inherited method before the rails code is loaded.  But since the A class extends the Class class it's definition of inherited overrides the version rails adds to Class.  The net outcome is that for the A class, and any class loaded before rails that defines inherited, class_inheritable_accessor is broken.&lt;br /&gt;&lt;br /&gt;What's the right way to fix this?  I'm not honestly sure.  It could be that in order to do something like this which effectively adds a feature to the language, you need to be loaded first.  On the flip side, it could be considered a bug that class_inheritable_accessor is broken in cases like this.  Well, I had hoped that by the time I got this point in the post a clear solution would emerge.  I suppose I'll have to leave it, as they say, as an exercise for the reader :)&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Update&lt;/span&gt;: I was about to post this, and I went to grab some dinner and finally realized the solution: A still does not entirely obey Weirich's law.  It correctly delegates to a previous implementation in the same class, but not to the superclass.  A call to super at the end of the inherited method causes the test to pass.  Adding the super call to the NB test runner code also causes my tests to be transactional again.  Yay!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/719065923860450374-7208275457947902210?l=mysterycoder.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mysterycoder.blogspot.com/feeds/7208275457947902210/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=719065923860450374&amp;postID=7208275457947902210' title='22 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/719065923860450374/posts/default/7208275457947902210'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/719065923860450374/posts/default/7208275457947902210'/><link rel='alternate' type='text/html' href='http://mysterycoder.blogspot.com/2008/10/fun-with-hook-methods-in-ruby.html' title='&quot;Fun&quot; with Hook Methods in Ruby'/><author><name>MysteryCoder</name><uri>http://www.blogger.com/profile/12085440439301444384</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_cYfx1Pq0Irc/TOXJ5wxxOVI/AAAAAAAAABQ/bDRzQsFRG6E/S220/Photo%2B15.jpg'/></author><thr:total>22</thr:total></entry><entry><id>tag:blogger.com,1999:blog-719065923860450374.post-4706868227156986740</id><published>2008-09-13T10:17:00.000-07:00</published><updated>2008-09-13T11:44:22.761-07:00</updated><title type='text'>Ruby in the browser at Rubyconf</title><content type='html'>Just got the news this week that my submission on &lt;a href="http://www.rubyconf.org/talks/56"&gt;ruby in the browser&lt;/a&gt;, has been accepted for Rubyconf.  This looks like an awesome conference and I am really psyched to be included.  It is also inspiring me to do some more work on rubyjs_on_rails and try to finish up an activeresource client.  I'll be hacking on that in whatever free time I have available this weekend.  &lt;br /&gt;&lt;br /&gt;I'm also thrilled that I get to be part of another &lt;a href="http://www.rubyconf.org/talks/70"&gt;dialogue session&lt;/a&gt; with Joe O'Brien and Jim Weirich.  This session will be a similar format to our railsconf dialogue which seemed to go over pretty well.  It's always a ton of fun to collaborate with these two phenomenal guys.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/719065923860450374-4706868227156986740?l=mysterycoder.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mysterycoder.blogspot.com/feeds/4706868227156986740/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=719065923860450374&amp;postID=4706868227156986740' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/719065923860450374/posts/default/4706868227156986740'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/719065923860450374/posts/default/4706868227156986740'/><link rel='alternate' type='text/html' href='http://mysterycoder.blogspot.com/2008/09/ruby-in-browser-at-rubyconf.html' title='Ruby in the browser at Rubyconf'/><author><name>MysteryCoder</name><uri>http://www.blogger.com/profile/12085440439301444384</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_cYfx1Pq0Irc/TOXJ5wxxOVI/AAAAAAAAABQ/bDRzQsFRG6E/S220/Photo%2B15.jpg'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-719065923860450374.post-6079672384887704231</id><published>2008-08-25T21:30:00.000-07:00</published><updated>2008-08-25T21:37:31.100-07:00</updated><title type='text'>rubyjs_on_rails hackfest at erubycon</title><content type='html'>I had a really fun time hacking on rubyjs at eRubycon.   It's amazing how much more fun and productive it is to hack with someone else than by yourself.   Thanks to Corey Haines for staying up late at the hotel being my hacking buddy.  As a result, we now have what will be the beginning of an ActiveResource client for rubyjs_on_rails.  I generated a simple scaffold resource example called Customer with a few fields.  I then created a Customer class in the view and started getting it to speak restfully with rails.  Here's the result:&lt;br /&gt;&lt;br /&gt;&lt;pre name="code" language="ruby"&gt;&lt;br /&gt;require 'dom_element'&lt;br /&gt;require 'json'&lt;br /&gt;require 'rwt/HTTPRequest'&lt;br /&gt;&lt;br /&gt;class Customer&lt;br /&gt;  &lt;br /&gt;  &lt;br /&gt;  attr_accessor :attributes&lt;br /&gt;  &lt;br /&gt;  def initialize(attrs)&lt;br /&gt;    @attributes = attrs&lt;br /&gt;  end&lt;br /&gt;  &lt;br /&gt;  def method_missing(method, *args)&lt;br /&gt;    if method =~ /(.*)=$/&lt;br /&gt;      attributes[$1] = args[0]&lt;br /&gt;    elsif attributes[method]&lt;br /&gt;      attributes[method]&lt;br /&gt;    else&lt;br /&gt;      super&lt;br /&gt;    end&lt;br /&gt;  end&lt;br /&gt;  &lt;br /&gt;  def self.main&lt;br /&gt;    @name = DOMElement.find("name")&lt;br /&gt;    @address = DOMElement.find("address")&lt;br /&gt;    find_button = DOMElement.find("choose_customer_button")&lt;br /&gt;    save_button = DOMElement.find("save_button")&lt;br /&gt;    customer_id_text = DOMElement.find("customer_id")&lt;br /&gt;    &lt;br /&gt;    find_button.observe("click") do |event|&lt;br /&gt;      Customer.find(customer_id_text["value"]) do |customer|&lt;br /&gt;        @name["value"] = customer.name&lt;br /&gt;        @address["value"] = customer.address&lt;br /&gt;        @customer = customer&lt;br /&gt;      end&lt;br /&gt;    end&lt;br /&gt;    &lt;br /&gt;    save_button.observe("click") do |event|&lt;br /&gt;      @customer.name = @name["value"]&lt;br /&gt;      @customer.address = @address["value"]&lt;br /&gt;      @customer.save&lt;br /&gt;    end&lt;br /&gt;    &lt;br /&gt;    rescue StandardError =&gt; ex&lt;br /&gt;      puts ex&lt;br /&gt;  end&lt;br /&gt;  &lt;br /&gt;  def self.find(id)&lt;br /&gt;    HTTPRequest.asyncGet "/customers/#{id}.json" do |json|&lt;br /&gt;      hash = JSON.load(json)&lt;br /&gt;      yield Customer.new(hash["customer"])&lt;br /&gt;    end    &lt;br /&gt;  end&lt;br /&gt;  &lt;br /&gt;  def save&lt;br /&gt;    request_json = {:customer =&gt; attributes}.to_json&lt;br /&gt;    HTTPRequest.asyncImpl "/customers/#{id}.json", "PUT", request_json, "application/json" do |json|&lt;br /&gt;      self.attributes = JSON.load(json)&lt;br /&gt;    end&lt;br /&gt;  end&lt;br /&gt;  &lt;br /&gt;  def to_json&lt;br /&gt;    attributes.to_json&lt;br /&gt;  end&lt;br /&gt;end&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The first part I did was find.  I've had that done for a couple weeks.  This was super easy because rubyjs and rails support json so easily.  The only odd bit is that it takes a block instead of returning a result.  This is because the find call does an ajax request, and the a in ajax stands for.. you guessed it, asynchronous.  Passing a block in makes it nice and simple to handle the result easily though.&lt;br /&gt;&lt;br /&gt;The part I got working at rubycon was the save.  This proved to be much easier than I thought it would be as well due to rails now supporting json updates natively.  The controller code doesn't even need to be aware that the parameters are coming in as json, you can access param[:customer] the same as you would if it was coming from a normal form submission.  I had to be sure and specify it was a PUT request when I sent it in, which I didn't realize was as straightforward to do as it is.  I monkeyed around with a _method param and all sorts of stuff before realizing I could just tell the HTTPRequest object what kind of request I wanted to make.  Duh.&lt;br /&gt;&lt;br /&gt;Though this is a specific example right now, I think a large portion of this code should be easy to extract out into an ActiveResouce client base class.  I haven't had any more time to hack on this since erubycon, sadly, but this is what I'll be focusing on when next I do.  Also, I just now put up a new repo on github to hold this and any other rubyjs_on_rails example code: git://github.com/superchris/rubyjs_rails_example.git.  Enjoy!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/719065923860450374-6079672384887704231?l=mysterycoder.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mysterycoder.blogspot.com/feeds/6079672384887704231/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=719065923860450374&amp;postID=6079672384887704231' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/719065923860450374/posts/default/6079672384887704231'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/719065923860450374/posts/default/6079672384887704231'/><link rel='alternate' type='text/html' href='http://mysterycoder.blogspot.com/2008/08/rubyjsonrails-hackfest-at-erubycon.html' title='rubyjs_on_rails hackfest at erubycon'/><author><name>MysteryCoder</name><uri>http://www.blogger.com/profile/12085440439301444384</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_cYfx1Pq0Irc/TOXJ5wxxOVI/AAAAAAAAABQ/bDRzQsFRG6E/S220/Photo%2B15.jpg'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-719065923860450374.post-7774432782423058117</id><published>2008-07-09T20:19:00.000-07:00</published><updated>2008-07-09T21:40:33.202-07:00</updated><title type='text'>Announcing rubyjs_on_rails: ARAX sans silverlight</title><content type='html'>So maybe you're like me: sure javascript is nice and all but you really like ruby better.  And as we move toward richer web apps, there are times it sure would be nice to write some of the client side code in ruby.  Along comes M$ with their sexy silverlight DLR magic to make it happen.  But you're suspicious: it requires a browser plugin, and can you &lt;span style="font-style: italic;"&gt;really&lt;/span&gt; trust that it will be there on all the platforms you want to support.  Sure, maybe M$ has learned how to play nice and it will be different this time.  Maybe.&lt;br /&gt;&lt;br /&gt;Well, you can quit holding your breath and exhale, girls and boys.  You can  write ruby code that runs in the browser right now.  Today.  No plugin or nuthin.  So here's how.  First, you'll need my forked version of the rubyjs ruby to javascript compiler.  It's a little like GWT for you Java folk.   Get it &lt;a href="http://www.christophernelsonconsulting.com-a.googlepages.com/rubyjs-0.8.1.gem"&gt;here&lt;/a&gt;.  Sorry, until githubs gem building process decides to show me some love you'll need to download and install it locally with:&lt;br /&gt;&lt;pre name="code"&gt;&lt;br /&gt;gem install --local rubyjs-0.8.1.gem&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Next, you take standard rails app and install my superfantastic* rubyjs_on_rails plugin like so:&lt;br /&gt;&lt;pre name="code"&gt;&lt;br /&gt;script/plugin install git://github.com/superchris/rubyjs_on_rails.git&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;So what did you get?  Well, basically, one measly helper method.  Sad, huh.  Hey! Don't judge me!  Cool your jets and let's see what it does already.  First make a rails controller with a single action.  Any old action will do, but let's imagine it's called hello.  Go find hello.html.erb and put a single button button that doesn't do anything in it like so:&lt;br /&gt;&lt;pre name="code" language="html"&gt;&lt;br /&gt;&amp;lt;input type="button" id="button" value="Say Hello"&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Now let's write some ruby code to respond to the button click.  Make a file called hello.rb in the same directory as your view and put this in it:&lt;br /&gt;&lt;pre name="code" language="ruby"&gt;&lt;br /&gt;require 'dom_element'&lt;br /&gt;&lt;br /&gt;class Hello&lt;br /&gt; def self.main&lt;br /&gt;   button = DOMElement.find("button")&lt;br /&gt;   button.observe("click") { puts "Hello from rubyjs!"}&lt;br /&gt; end&lt;br /&gt;end&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;DOMElement is a class provided by the rubyjs gem that makes it easy to, surprise surprise, work with dom elements.  In our case we just use it to grab hold of our button and observe the click event with a block of ruby code.  Kind of cool I think.&lt;br /&gt;&lt;br /&gt;But how to get this code into the brower?  You remember earlier when I said all this plugin gives you is one measly helper method and you were all "Meh.  I am sooo not impressed."  Well now let's see it in action.  Add this to your view right below the the button:&lt;br /&gt;&lt;pre name="code" language="html"&gt;&lt;br /&gt;&amp;lt;%= rubyjs "Hello", "main" %&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Now hit this action in your browser.  Click the button and you'll see your ruby block fire.  The rubyjs helper method goes and finds hello.rb, compiles into javascript, and outputs a script tag to serve it up.  The arguments to it are the class name and and a class method to invoke.  It needs to be a class method; As this is the entry point to the code there is no instance yet to invoke methods on.&lt;br /&gt;&lt;br /&gt;So that's it.  Ruby running in the browser.  You're welcome.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:78%;"&gt;*Your superfasticalness may vary.  No actual superfantasticness is either expressed nor implied by this blog post&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/719065923860450374-7774432782423058117?l=mysterycoder.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mysterycoder.blogspot.com/feeds/7774432782423058117/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=719065923860450374&amp;postID=7774432782423058117' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/719065923860450374/posts/default/7774432782423058117'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/719065923860450374/posts/default/7774432782423058117'/><link rel='alternate' type='text/html' href='http://mysterycoder.blogspot.com/2008/07/announcing-rubyjsonrails-arax-sans.html' title='Announcing rubyjs_on_rails: ARAX sans silverlight'/><author><name>MysteryCoder</name><uri>http://www.blogger.com/profile/12085440439301444384</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_cYfx1Pq0Irc/TOXJ5wxxOVI/AAAAAAAAABQ/bDRzQsFRG6E/S220/Photo%2B15.jpg'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-719065923860450374.post-3614972790499245979</id><published>2008-07-03T13:44:00.000-07:00</published><updated>2008-07-03T13:47:49.956-07:00</updated><title type='text'>eRubyCon: Be There!</title><content type='html'>Just a quick little post to get the word out to my readers about &lt;a href="http://www.erubycon.com/"&gt;eRubyCon&lt;/a&gt; in Columbus, OH Aug. 15-17th.  It's shaping up to be an awesome conference.  And the early bird rate makes it the best conference deal I've ever heard of.  Heck, even the post early bird rate makes it the best conference deal I've ever heard of.  So register already.  You know you wanna.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/719065923860450374-3614972790499245979?l=mysterycoder.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mysterycoder.blogspot.com/feeds/3614972790499245979/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=719065923860450374&amp;postID=3614972790499245979' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/719065923860450374/posts/default/3614972790499245979'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/719065923860450374/posts/default/3614972790499245979'/><link rel='alternate' type='text/html' href='http://mysterycoder.blogspot.com/2008/07/erubycon-be-there.html' title='eRubyCon: Be There!'/><author><name>MysteryCoder</name><uri>http://www.blogger.com/profile/12085440439301444384</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_cYfx1Pq0Irc/TOXJ5wxxOVI/AAAAAAAAABQ/bDRzQsFRG6E/S220/Photo%2B15.jpg'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-719065923860450374.post-665596467705572856</id><published>2008-06-04T09:17:00.000-07:00</published><updated>2008-06-04T20:22:10.134-07:00</updated><title type='text'>Write your javascript in ruby with rubyjs</title><content type='html'>I was inspired by Nathaniel Talbott's awesome railsconf talk to do some hacking.  I had a lot of fun, and I think I came up with something worth sharing, so here it is.  My willing victim was rubyjs, Michael Neumann's excellent little project I mentioned in an earlier post.  If you want to play along at home, the first thing you'll need to do is fetch my code like so:&lt;br /&gt;&lt;pre name="code" class="ruby"&gt;git clone git://github.com/superchris/rubyjs.git&lt;/pre&gt;&lt;br /&gt;There are some things in my repo that haven't made it into the gem version of rubyjs yet.  My hack was a little "port" of the hangman example from Tapestry.  It's there in examples/hangman.  You can try it &lt;a href="http://www.christophernelsonconsulting.com-a.googlepages.com/hangman.html"&gt;here&lt;/a&gt;.  Or if you're so inclined, you can build it your dang self by running:&lt;br /&gt;&lt;pre name="code"&gt;&lt;br /&gt;rake "examples/hangman/hangman.js"&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;This command uses a rake rule to run the rubyjs compiler which compiles hangman.rb to hangman.js.&lt;br /&gt;&lt;br /&gt;So let's see some code how about, hmm?&lt;br /&gt;&lt;pre name="code" language="ruby"&gt;&lt;br /&gt;class DOMElement&lt;br /&gt;  def initialize(element)&lt;br /&gt;    @dom_element = element&lt;br /&gt;  end&lt;br /&gt;  &lt;br /&gt;  def observe(event, &amp;block)&lt;br /&gt;    element = @dom_element&lt;br /&gt;    `&lt;br /&gt;      if (#&amp;lt;element&amp;gt;.addEventListener) {&lt;br /&gt;        #&amp;lt;element&amp;gt;.addEventListener(#&amp;lt;event&amp;gt;, #&amp;lt;block&amp;gt;, false);&lt;br /&gt;      } else {&lt;br /&gt;        #&amp;lt;element&amp;gt;.attachEvent("on" + #&amp;lt;event&amp;gt;, #&amp;lt;block&amp;gt;);&lt;br /&gt;      }&lt;br /&gt;    `&lt;br /&gt;    nil&lt;br /&gt;  end  &lt;br /&gt;  &lt;br /&gt;  def [](attribute)&lt;br /&gt;    element = @dom_element&lt;br /&gt;    `return #&amp;lt;element&amp;gt;[#&amp;lt;attribute&amp;gt;]`&lt;br /&gt;  end&lt;br /&gt;  &lt;br /&gt;  def []=(attr, value)&lt;br /&gt;    element = @dom_element&lt;br /&gt;    `#&amp;lt;element&amp;gt;[#&amp;lt;attr&amp;gt;] = #&amp;lt;value&amp;gt;;`&lt;br /&gt;    nil&lt;br /&gt;  end&lt;br /&gt;  &lt;br /&gt;  def self.find_js_element(element)&lt;br /&gt;    `return document.getElementById(#&amp;lt;element&amp;gt;);`&lt;br /&gt;  end&lt;br /&gt;  &lt;br /&gt;&lt;br /&gt;  def self.find(element)&lt;br /&gt;    dom_element = self.find_js_element(element)&lt;br /&gt;    DOMElement.new(dom_element)&lt;br /&gt;  end&lt;br /&gt;  &lt;br /&gt;  #&lt;br /&gt;  # Gets an HTML representation (as String) of an element's children.&lt;br /&gt;  #&lt;br /&gt;  # elem::   the element whose HTML is to be retrieved&lt;br /&gt;  # return:: the HTML representation of the element's children&lt;br /&gt;  #&lt;br /&gt;  def inner_html &lt;br /&gt;    elem = @dom_element&lt;br /&gt;    `&lt;br /&gt;    var ret = #&amp;lt;elem&amp;gt;.innerHTML;&lt;br /&gt;    return (ret == null) ? #&amp;lt;nil&amp;gt; : ret;`&lt;br /&gt;  end&lt;br /&gt;&lt;br /&gt;  #&lt;br /&gt;  # Sets the HTML contained within an element.&lt;br /&gt;  #&lt;br /&gt;  # elem:: the element whose inner HTML is to be set&lt;br /&gt;  # html:: the new html&lt;br /&gt;  #&lt;br /&gt;  def inner_html=(html) &lt;br /&gt;    elem = @dom_element&lt;br /&gt;    `&lt;br /&gt;    #&amp;lt;elem&amp;gt;.innerHTML = #&amp;lt;html&amp;gt;;&lt;br /&gt;    return #&amp;lt;nil&amp;gt;;`&lt;br /&gt;  end&lt;br /&gt;  &lt;br /&gt;end&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;The first class you see here is DOMElement.  This gives some basic dom manipulation abilities in a ruby friendly way.  I got this working by looking at the work Michael had done on porting GWT to ruby and extracting the bit I wanted and "rubifying" it a little.  Basically, you can find elements by id, observe events with ruby blocks, and get/set attributes and inner html.  Pretty simple, but has what I need.  I should probably extract this into a separate file in rubyjs in case other people want it.  You can also see lots of examples of how rubyjs and javascript talk to each other here.&lt;br /&gt;&lt;br /&gt;Then it's on to the hangman code.  First it's worth looking at the html so you can see what dom elements the code refers to:&lt;br /&gt;&lt;br /&gt;And finally here's the hangman class:&lt;br /&gt;&lt;pre name="code" language="ruby"&gt;&lt;br /&gt;class Hangman&lt;br /&gt;  &lt;br /&gt;  attr_accessor :word, :letters, :misses&lt;br /&gt;  &lt;br /&gt;  MAX_MISSES = 6&lt;br /&gt;  &lt;br /&gt;  def initialize&lt;br /&gt;    @word = "snail"&lt;br /&gt;    @letters = @word.split ""&lt;br /&gt;    @guessed_letters = {}&lt;br /&gt;    @letters.each { |letter| @guessed_letters[letter] = false }&lt;br /&gt;    @misses = 0&lt;br /&gt;    @scaffold_div = DOMElement.find("scaffold_div")&lt;br /&gt;    @letters_div = DOMElement.find("letters")&lt;br /&gt;    @guess_input = DOMElement.find("letter")&lt;br /&gt;    @guess_button = DOMElement.find("guess")&lt;br /&gt;    @guess_button.observe("click") do &lt;br /&gt;      guess(@guess_input["value"])&lt;br /&gt;    end&lt;br /&gt;    @letters_div.inner_html = display_word    &lt;br /&gt;  end&lt;br /&gt;  &lt;br /&gt;  def display_word&lt;br /&gt;    letters.collect do |letter|&lt;br /&gt;      @guessed_letters[letter] ? letter : "_"&lt;br /&gt;    end.join&lt;br /&gt;  end&lt;br /&gt;  &lt;br /&gt;  def guess(letter)&lt;br /&gt;    if letters.include?(letter)&lt;br /&gt;      @guessed_letters[letter] = true&lt;br /&gt;      @letters_div.inner_html = display_word&lt;br /&gt;      puts "You win!" if won? &lt;br /&gt;    else&lt;br /&gt;      @misses += 1&lt;br /&gt;      @scaffold_div.inner_html = "&amp;lt;img src='scaffold-#{@misses}.png' /&amp;gt;"&lt;br /&gt;      if lost? &lt;br /&gt;        puts "You lost!" &lt;br /&gt;        @guess_button["disabled"] = true&lt;br /&gt;      end&lt;br /&gt;    end&lt;br /&gt;    @guess_input["value"] = ""&lt;br /&gt;  end&lt;br /&gt;  &lt;br /&gt;  def lost?&lt;br /&gt;    @misses &gt;= 6&lt;br /&gt;  end&lt;br /&gt;  &lt;br /&gt;  def won?&lt;br /&gt;    @guessed_letters.values.each do |guessed|&lt;br /&gt;      return false unless guessed&lt;br /&gt;    end&lt;br /&gt;    return true&lt;br /&gt;  end&lt;br /&gt;&lt;br /&gt;  def self.main&lt;br /&gt;    hangman = Hangman.new&lt;br /&gt;  rescue StandardError =&gt; ex&lt;br /&gt;    puts ex&lt;br /&gt;  end&lt;br /&gt;end&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;First you see the initialize method.  Here is where we lookup our DOM elements, setup a Hash of which letters are guessed yet, and bind a block to the click event of our guess_button. Next comes the display_word method, which displays each letter or a blank if it's not been guessed.&lt;br /&gt;&lt;br /&gt;The meat of the matter is in guess_letter, which is pretty simple.  If the letter guessed is in the word we mark it, redisplay the word with the guessed letter and check if the user has won.  If not, we update our miss count, display the right image, and check to see if the user lost.  Won? and lost? are both trivial and not worth talking about.&lt;br /&gt;&lt;br /&gt;Well, I had a lot of fun hacking on this.  I think rubyjs has a good chance to be really useful as well as fun.  It needs some love, certainly, but one of the things I did was start of woefully inadequate port of miniunit I'm calling microunit.  It's in rubyjs/lib.  This should make it easier and, I think, funner, to flesh out the core library for rubyjs.&lt;br /&gt;&lt;br /&gt;For next steps I may expand on this example some.  I'm thinking it would be a blast to tie to a Rails backend that gives me random words (right now it is always the same word :( ) or stores scores or some such foolishness.  I could use this as an excuse to build an ActiveResource client for rubyjs and maybe a rubyjs on rails plugin.&lt;br /&gt;&lt;br /&gt;If anyone cares about this, drop me a comment and let me know.  Or if you think it's utterly stupid, tell me why.  I promise to read all your comments and do whatever I feel like doing anyways :)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/719065923860450374-665596467705572856?l=mysterycoder.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mysterycoder.blogspot.com/feeds/665596467705572856/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=719065923860450374&amp;postID=665596467705572856' title='29 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/719065923860450374/posts/default/665596467705572856'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/719065923860450374/posts/default/665596467705572856'/><link rel='alternate' type='text/html' href='http://mysterycoder.blogspot.com/2008/06/write-your-javascript-in-ruby-with.html' title='Write your javascript in ruby with rubyjs'/><author><name>MysteryCoder</name><uri>http://www.blogger.com/profile/12085440439301444384</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_cYfx1Pq0Irc/TOXJ5wxxOVI/AAAAAAAAABQ/bDRzQsFRG6E/S220/Photo%2B15.jpg'/></author><thr:total>29</thr:total></entry><entry><id>tag:blogger.com,1999:blog-719065923860450374.post-5414476921568558356</id><published>2008-06-03T09:13:00.000-07:00</published><updated>2008-06-03T09:52:05.533-07:00</updated><title type='text'>Back from Railsconf 2008</title><content type='html'>Wow, that was fun.  Here's a quick recap of my personal highlights of Railsconf 2008.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;Our Modelling Dialogue session&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;So I'm self-centered, but this was the talk I had the most concern about since I was in it.  To be honest I had no idea how this was going to be received, so I was relieved and excited by the great response.  I had this vision of all our laugh lines receiving the dead silence, crickets chirping response.  But gratefully this was not the case.  Jim Weirich has a great recap and lists the books we recommend on his &lt;a href="http://onestepback.org/index.cgi/Tech/Conferences/RailsConf2008/RailsConf2008Summary.red"&gt;blog.&lt;/a&gt;  The feedback was so positive that we're already cooking up ideas for other talks in this format.  To all those who came up and said something to us about our session: Thanks a ton!  You have no idea what a help it is to hear from audience members about how it worked or didn't work for them.  In short, there's nothing like going out on a limb and having it not break :)  Major kudos to Jim and Joe for the idea for this one and for doing a great job pulling it off.&lt;br /&gt;&lt;span style="font-size:130%;"&gt;&lt;br /&gt;Nathaniel Talbott's hacking session&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;This was for me the most inspiring session.  In a nutshell: hacking is good for you.  If it's not fun it's not hacking.  Being useful is not the point, enjoying yourself is.  It inspired me to hack on rubyjs some more.  I had a great time, and managed to come up with something worth sharing I think (tho as I said this was not the point, just a happy accident).  More to come.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;DHH Keynote&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;I actually enjoyed this quite a bit.  Some of his points I really appreciated: he called BS on the whole IMO messed up american work culture idea that working more and sleeping less makes you supercoderdude.  This is total crap, makes us less effective, and it's high time someone said so.  Sleep more, and find some hobbies that don't involve computers.  Get a life in other words.  Great stuff.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;Alternative Ruby impls&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;There was a lot of talk at the conference about non-MRI Ruby interpreters running Rails.  I went to the IronRuby session.  They run Rails and showed a simple scaffold example working.  But I was most impressed by their silverlight demo of ruby running in the browser.  Of course, only works in windows and maybe OSX.  Allegedly moonlight will catch up.  I'd love to really believe MS on that, but I'll believe it when I see it.&lt;br /&gt;&lt;br /&gt;I didn't see the Rubinius talk but the did show it running Rails in a keynote.  Boy is it slow, but if they can get performance up to snuff it sure is cool to have ruby in ruby.&lt;br /&gt;&lt;br /&gt;Maglev IMO got a ton of unwarranted buzz.  The part Avi did was cool, but the next part with the gemstone guy ruined it.  They are nowhere close to running rails, and the sales guy was casting these sneaky sideways slams of other impls and selling a lot of vaporware.  The perf numbers are impressive, but I totally agree with Charles that they mean nothing until they implement all of Ruby.  Overall, I thought it kind of FUDDY, and I was quite saddened that the community just went along with it hook line and sinker.&lt;br /&gt;&lt;br /&gt;JRuby was there, and had some good talks but since they've been running rails for a long while this wasn't really news and didn't get so much attention.  I really like the JRuby rack stuff a lot tho, it opens even more doors.  And I had at least one awesome hallway conversation about some big companies adopting JRuby and doing interesting stuff.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/719065923860450374-5414476921568558356?l=mysterycoder.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mysterycoder.blogspot.com/feeds/5414476921568558356/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=719065923860450374&amp;postID=5414476921568558356' title='6 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/719065923860450374/posts/default/5414476921568558356'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/719065923860450374/posts/default/5414476921568558356'/><link rel='alternate' type='text/html' href='http://mysterycoder.blogspot.com/2008/06/back-from-railsconf-2008.html' title='Back from Railsconf 2008'/><author><name>MysteryCoder</name><uri>http://www.blogger.com/profile/12085440439301444384</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_cYfx1Pq0Irc/TOXJ5wxxOVI/AAAAAAAAABQ/bDRzQsFRG6E/S220/Photo%2B15.jpg'/></author><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-719065923860450374.post-2061586655406407076</id><published>2008-05-01T12:19:00.000-07:00</published><updated>2008-05-01T13:10:53.160-07:00</updated><title type='text'>The best motivational poster ever</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp1.blogger.com/_cYfx1Pq0Irc/SBoYK4LagfI/AAAAAAAAAAQ/D71LEzFGb-c/s1600-h/KeepEmGreen.jpeg"&gt;&lt;img style="cursor:pointer; cursor:hand;" src="http://bp1.blogger.com/_cYfx1Pq0Irc/SBoYK4LagfI/AAAAAAAAAAQ/D71LEzFGb-c/s320/KeepEmGreen.jpeg" border="0" alt=""id="BLOGGER_PHOTO_ID_5195491695283306994" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Credit to &lt;a href="http://onestepback.org"&gt;Jim Weirich&lt;/a&gt; for this one :)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/719065923860450374-2061586655406407076?l=mysterycoder.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mysterycoder.blogspot.com/feeds/2061586655406407076/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=719065923860450374&amp;postID=2061586655406407076' title='7 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/719065923860450374/posts/default/2061586655406407076'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/719065923860450374/posts/default/2061586655406407076'/><link rel='alternate' type='text/html' href='http://mysterycoder.blogspot.com/2008/05/best-motivational-poster-in-world.html' title='The best motivational poster ever'/><author><name>MysteryCoder</name><uri>http://www.blogger.com/profile/12085440439301444384</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_cYfx1Pq0Irc/TOXJ5wxxOVI/AAAAAAAAABQ/bDRzQsFRG6E/S220/Photo%2B15.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://bp1.blogger.com/_cYfx1Pq0Irc/SBoYK4LagfI/AAAAAAAAAAQ/D71LEzFGb-c/s72-c/KeepEmGreen.jpeg' height='72' width='72'/><thr:total>7</thr:total></entry><entry><id>tag:blogger.com,1999:blog-719065923860450374.post-4849966948760508026</id><published>2008-04-29T11:00:00.000-07:00</published><updated>2008-04-29T08:11:03.674-07:00</updated><title type='text'>Ruby in the browser: a crazy idea whose time has come</title><content type='html'>This point of this blog post is first, to explain why I think the seemingly nutty idea having ruby execute in the web browser is actually a good one, and second, to show how you can actually do it.  Today.  It might be a little long, but bear with me.&lt;br /&gt;&lt;br /&gt;I've been spending a lot of my free time over the past few months with various different approaches for getting ruby to work inside the web browser.  The obvious question would be: Why?  Let me start by stating this unequivocally: I do not hate Javascript.  I've more than once argued that we as programmers have given not javascript nearly the respect that it deserves.   In fact, it was only through treating javascript with respect that I arrived at the conclusions that brought me here.&lt;br /&gt;&lt;br /&gt;A few months ago I was working on a project where we needed to move some reasonably complex business logic from the server to the client.  The requirements were such that we just couldn't call the logic on the server and have the application behave as desired.  I decided to try to use it as an excuse to improve my javascript skills.  I used the object oriented features of Prototype, and some visual effects and the unit testing framework of Scriptaculous.  To the best of my ability, I tried to approach it my javascript the same way I would any of my "main" development languages.  I wrote the code using test driven development and attempted to make it as clearly communicative as possible.  And you know what?  I actually enjoyed it quite a bit.  I was pleased with the code and the users seemed to like the result.  I came away with a greatly improved opinion of javascript.&lt;br /&gt;&lt;br /&gt;But something I observed bothered me: I ended up creating exactly the same classes in javascript as I had in server side language (in this case Java).  This really shouldn't be surprising, since I used test driven design on the server side java code and the client side javascript code it only makes sense it would lead to a similar outcome.  But duplicate code has always been (for me) the number one code smell that indicates a need to refactor.  As far as I can tell, in order to get rid of this kind of duplicate code I need to develop my core business logic in a language which can execute on both the client (web browser) and the server.  I mentioned earlier that I don't think javascript is a bad language, it's not very common for server side development right now and not my first choice.  Currently my favorite language for server side code is ruby.  If only ruby could execute in the browser.  Pure fantasy, right?   Believe it or not, there are actually at least 3 possible ways to do it.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;JRuby&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;First up in my explorations was JRuby.  Quite a while back there was an experiment by Dion Almaer to a JRuby applet to execute ruby code in the web page.  While this was a nifty experiment when I tried to push this idea further I hit one brick wall after another.  The first is that the current JRuby implementation does a lot of things that require additional privileges which means a signed applet.  The second which proved more formidable is that javascript code can't call privileged java code at all.  This meant that having javascript interact with my ruby code was out.  Not good.  Though JRuby is near and dear to my heart, this limitation, along with the potential barrier to entry of requiring the Java plugin seemed to make this not a promising solution for what I'm trying to do.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;HotRuby&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;So I gave up on the idea for awhile, until I recently came across &lt;a href="http://hotruby.accelart.jp/"&gt;HotRuby.&lt;/a&gt;  HotRuby is a Ruby VM written in javascript.  It's a fascinating idea, and it actually works.  Under the covers it's really a javascript interpreter for the YARV instruction set.  It requires Ruby 1.9 since it depends on YARV.  There is a script which dumps out the YARV instructions for a Ruby file in json format. In the browser you include the HotRuby javscript which creates a HotRuby javascript object which executes the jsonified YARV instructions. I installed 1.9 on my machine and checked out the HotRuby code from SVN.  In a few hours of playing around, I was able to get it talking with prototype.js and had a simple example where i assigned a ruby block to an onclick event of a button.  Although the project seems fairly experimental at this point, it shows great promise.  In fact, I was getting ready to blog about it when I came across:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;Rubyjs&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/297702"&gt;Rubyjs&lt;/a&gt; is a ruby compiler that outputs javascript.  It requires only Ruby 1.8.6 and installs as a gem which made it easy to get up and running with.  Be aware, Ruby 1.8.5 will not work with it, which meant I had to upgrade.  Rubyjs leverages another gem, ParseTree, which parses ruby code intos-expressions, which are kind of like a syntax tree.  Rubyjs then emits javascript based on these.  A bit more complex but seems to work well and can support more of Ruby than HotRuby can so far.&lt;br /&gt;&lt;br /&gt;So far Rubyjs seems to be the most viable solution to me.  And if you've made it this far into the post, you deserve to be rewarded with some code.  To get running is easy, just gem install rubyjs.  This will give you a rubyjs command which will take your ruby code and output javascript for it.  Rubyjs comes with a few examples but none which really did what I was interested in doing.  I wanted to show a simple block of ruby code listening to a button's onclick event.  It took a bit of delving into the rubyjs code to figure out how to do it but I think the resulting code came out to be fairly understandable.  Here it is:&lt;br /&gt;&lt;br /&gt;&lt;pre name="code" class="ruby"&gt;&lt;br /&gt;class DOM&lt;br /&gt;def self.find(element)&lt;br /&gt;  `return document.getElementById(#&amp;lt;element&amp;gt;);`&lt;br /&gt;end&lt;br /&gt;end&lt;br /&gt;&lt;br /&gt;class Button&lt;br /&gt;def initialize(js_element)&lt;br /&gt;  @js_element = js_element&lt;br /&gt;end&lt;br /&gt;&lt;br /&gt;def onclick(&amp;amp;block)&lt;br /&gt;  element = @js_element&lt;br /&gt;  `&lt;br /&gt;    if (#&amp;lt;element&amp;gt;.addEventListener) {&lt;br /&gt;      #&amp;lt;element&amp;gt;.addEventListener("click", #&amp;lt;block&amp;gt;, false);&lt;br /&gt;    } else {&lt;br /&gt;      #&amp;lt;element&amp;gt;.attachEvent("onclick", #&amp;lt;block&amp;gt;);&lt;br /&gt;    }&lt;br /&gt;  `&lt;br /&gt;end&lt;br /&gt;end&lt;br /&gt;&lt;br /&gt;class Main&lt;br /&gt;def self.main&lt;br /&gt;  button = Button.new(DOM.find("button"))&lt;br /&gt;  button.onclick { puts "clicked!"}&lt;br /&gt;end&lt;br /&gt;end&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;I create a simple DOM class to help me find an element by id.  This shows how you talk to javascript code in rubyjs: by enclosing your javascript code in backticks.  Rubyjs does automatically maps javascript objects to ruby and vice versa.  I'm not going to delve into the nitty gritty of this too much, I'll do so in a later post.&lt;br /&gt;&lt;br /&gt;The more interesting class here is Button.  A Button instance gets pass in a DOM element in initialize and instances of button have a single method onclick which receives a block.  As you would expect, this allows you to set the onclick handler of a button using a ruby block.  The code in the onclick method of Button is also interesting: it shows how you can pass ruby objects into javascript (the javascript code I ripped of from Prototype to do cross browser event observing).  Rubyjs will interpolate the javascript code in backticks and replace #&lt;foo&gt; type declarations with local variables converting the ruby objects to javascript as appropriate.  What this means here is rubyjs is transforming our block into a javascript function for us.  Pretty cool, eh?&lt;br /&gt;&lt;br /&gt;To see this action, we'll need to compile this ruby code to javascript.  The command to do it:&lt;br /&gt;&lt;br /&gt;&lt;pre name="code" class="ruby"&gt;&lt;br /&gt;rubyjs button.rb -m Main -d -o button.js&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The options tell rubyjs to compile button.rb to button.js.  Rubyjs also needs an entry point, which is what -m Main is about.  It expects Main to define a class method called Main.  Very javaesque, but this is a minor gripe.  You can see this code in action &lt;a href="http://www.christophernelsonconsulting.com-a.googlepages.com/button.html"&gt;here.&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;There's a lot more to talk about with rubyjs, and I plan this to be the first in a series of posts about it.  As part of the project there is also the beginning of a port of GWT to ruby.  Altho the code is a bit to javaesque for my tastes so far (as you might expect for a direct port), the idea is very interesting.  Let me also issue a giant thank you to &lt;strong style="font-weight: normal;"&gt;Michael Neumann for writing rubyjs and for being incredibly helpful and responsive while I was experimenting.  When I asked a question he posted a new version of the gem to address my concern within a few hours.  Impressive.&lt;/strong&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/719065923860450374-4849966948760508026?l=mysterycoder.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mysterycoder.blogspot.com/feeds/4849966948760508026/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=719065923860450374&amp;postID=4849966948760508026' title='16 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/719065923860450374/posts/default/4849966948760508026'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/719065923860450374/posts/default/4849966948760508026'/><link rel='alternate' type='text/html' href='http://mysterycoder.blogspot.com/2008/04/ruby-in-browser-crazy-idea-whose-time.html' title='Ruby in the browser: a crazy idea whose time has come'/><author><name>MysteryCoder</name><uri>http://www.blogger.com/profile/12085440439301444384</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_cYfx1Pq0Irc/TOXJ5wxxOVI/AAAAAAAAABQ/bDRzQsFRG6E/S220/Photo%2B15.jpg'/></author><thr:total>16</thr:total></entry><entry><id>tag:blogger.com,1999:blog-719065923860450374.post-6351123038139595311</id><published>2008-04-26T10:18:00.001-07:00</published><updated>2008-04-26T10:29:00.160-07:00</updated><title type='text'>I'm presenting at RailsConf</title><content type='html'>Long overdue to blog about this, as I found out a few weeks ago now.  Amazing but true: I'm speaking at Railsconf.  I got invited to participate in a very non-conventional presentation with Joe O'Brien and Jim Weirich, two guys I respect enormously.  We're presenting a dialogue between several developers on modeling.  It's actually proving very challenging to write, as coming up with enough things for the characters to say in 50 minutes is a lot of text.  But what an opportunity.  All in all, the prospect of sharing the stage with Jim and Joe has me feeling a little like &lt;a href="http://www.youtube.com/watch?v=VQauQ6f72Zk"&gt;this.&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/719065923860450374-6351123038139595311?l=mysterycoder.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mysterycoder.blogspot.com/feeds/6351123038139595311/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=719065923860450374&amp;postID=6351123038139595311' title='7 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/719065923860450374/posts/default/6351123038139595311'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/719065923860450374/posts/default/6351123038139595311'/><link rel='alternate' type='text/html' href='http://mysterycoder.blogspot.com/2008/04/im-presenting-at-railsconf.html' title='I&apos;m presenting at RailsConf'/><author><name>MysteryCoder</name><uri>http://www.blogger.com/profile/12085440439301444384</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_cYfx1Pq0Irc/TOXJ5wxxOVI/AAAAAAAAABQ/bDRzQsFRG6E/S220/Photo%2B15.jpg'/></author><thr:total>7</thr:total></entry><entry><id>tag:blogger.com,1999:blog-719065923860450374.post-7537790598533419363</id><published>2008-03-09T20:10:00.000-07:00</published><updated>2008-03-09T20:15:48.684-07:00</updated><title type='text'>JRuby at TSSJS</title><content type='html'>Just a quick post to say I'll be presenting on JRuby at &lt;a href="http://javasymposium.techtarget.com/lasvegas/index.html"&gt;TSSJS.&lt;/a&gt;  The JRuby core team is all at Scotland on Rails I presume, so I'll be doing my level best to represent.   Drop me a line if you're going to be there.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/719065923860450374-7537790598533419363?l=mysterycoder.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mysterycoder.blogspot.com/feeds/7537790598533419363/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=719065923860450374&amp;postID=7537790598533419363' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/719065923860450374/posts/default/7537790598533419363'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/719065923860450374/posts/default/7537790598533419363'/><link rel='alternate' type='text/html' href='http://mysterycoder.blogspot.com/2008/03/jruby-at-tssjs.html' title='JRuby at TSSJS'/><author><name>MysteryCoder</name><uri>http://www.blogger.com/profile/12085440439301444384</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_cYfx1Pq0Irc/TOXJ5wxxOVI/AAAAAAAAABQ/bDRzQsFRG6E/S220/Photo%2B15.jpg'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-719065923860450374.post-235784661456906595</id><published>2008-02-03T13:57:00.000-08:00</published><updated>2008-02-03T10:59:34.943-08:00</updated><title type='text'>Rails "components": I do not think that word means what you think it means.</title><content type='html'>Right now I have 2 gigs.  One is a java gig where I am working on an application I helped develop about two years ago using Tapestry.  The other is a Rails gig.  This has given me a good opportunity to compare and contrast the two.  So far my experience is that I love the Ruby language and don't want to go back to doing Java except when/if I need to to pay the bills.  But Rails I'm not as sold on.  Mind you I'm not here to bash on Rails, there are some great things there and other people have done a fine job of praising them.  But there are some things I definitely miss from Tapestry, and the most significant one is components.  &lt;br /&gt;&lt;br /&gt;Now when I say components I don't mean that abomination they stuck in Rails and then deprecated.  I mean "real" components in the style of WebObjects, Tapestry, and other frameworks in that lineage.  To qualify as "real" components in my mind means 3 things:&lt;br /&gt;&lt;br /&gt;1. &lt;span style="font-weight:bold;"&gt;Reusable view and controller logic.  &lt;/span&gt;&lt;br /&gt;This is the easiest and this is I think what the deprecated Rails components thing was attempting to address.  I've seen several other attempts to do this in Rails with varying degrees of success.  I think the Presenter pattern being bandied about is essentially another attempt to have this same aspect of "componenty-ness". &lt;br /&gt;&lt;br /&gt;2. &lt;span style="font-weight:bold;"&gt;Composability.&lt;/span&gt;&lt;br /&gt;Components should be able to be composed out of other components.  I haven's seen something in Rails that did this well yet.  It could be out there, but if it is I haven't seen it.  And this is also where it gets a little controversial.  From what I've seen, DHH and rails core seems to believe that "high level" component reuse is either not possible or worthwhile.  Having seen it absolutely work and work well in Tapestry I have to respectfully disagree.  The Tapestry Palette and Table components are both "high-level" and reusable on multiple projects to great affect.  However even the discussion around component reuse seemed to me to be framed incorrectly, as it seemed focused on components being reused between applications.  This is certainly possible, but I find much greater levels of component reuse &lt;span style="font-style:italic;"&gt;within&lt;/span&gt; an application.  &lt;br /&gt;&lt;br /&gt;3. &lt;span style="font-weight:bold;"&gt;Binding.&lt;/span&gt;&lt;br /&gt;This to me seems to be the most neglected feature of components, but in my mind is perhaps the most important.  This is simply the ability to say something like "the value property of this text field is bound to @person.name".  This should result in me being able to access @person with the name already set.  I shouldn't have to touch the params hash at all.  This would get rid of what I see as an imporant non-dry part of Rails.  For example, why should I have to say in my view:&lt;br /&gt;&lt;br /&gt;text_field "person", "name"&lt;br /&gt;&lt;br /&gt;And then in my controller:&lt;br /&gt; &lt;br /&gt;@person = Person.new(params[:person])&lt;br /&gt;&lt;br /&gt;With binding I wouldn't have to.&lt;br /&gt;&lt;br /&gt;The other place binding comes into play in component frameworks is events.  Not only properties support binding, but events do as well.  For example, a Button component could have a block bound to the "onlick" property.  The framework then manages and abstracts away all the details of HTTP, etc.&lt;br /&gt;&lt;br /&gt;I guess that's really what I miss: with a good component framework (and not all of them are) I feel like I am working at a higher level of abstraction.  When building reasonably sophisticated web applications, I really miss that.  With simple web sites, I don't so much.&lt;br /&gt;&lt;br /&gt;So where am I going with all this?  Well, I've been thinking about these ideas a lot since I started doing Rails and talking about them with my pairmate.  Recently the ruby-component-web-frameworks Google group has been getting active again so I thought I'd blog about my ideas.  I've started doing a little code experiment to see how it might look to implement some of these ideas as a Rails plugin.  It seems not too difficult so far; it never ceases to amaze me how much I can say in so little Ruby code.  When we have an SVN repo setup I'll share what I have but it's just an architecture spike right now.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/719065923860450374-235784661456906595?l=mysterycoder.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mysterycoder.blogspot.com/feeds/235784661456906595/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=719065923860450374&amp;postID=235784661456906595' title='22 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/719065923860450374/posts/default/235784661456906595'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/719065923860450374/posts/default/235784661456906595'/><link rel='alternate' type='text/html' href='http://mysterycoder.blogspot.com/2008/02/rails-components-i-do-not-think-that.html' title='Rails &quot;components&quot;: I do not think that word means what you think it means.'/><author><name>MysteryCoder</name><uri>http://www.blogger.com/profile/12085440439301444384</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_cYfx1Pq0Irc/TOXJ5wxxOVI/AAAAAAAAABQ/bDRzQsFRG6E/S220/Photo%2B15.jpg'/></author><thr:total>22</thr:total></entry><entry><id>tag:blogger.com,1999:blog-719065923860450374.post-5873809169579925509</id><published>2007-11-24T18:35:00.000-08:00</published><updated>2007-11-24T17:16:18.341-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ruby rest dojo components'/><title type='text'>Making our RESTful grid editable</title><content type='html'>In my &lt;a href="http://mysterycoder.blogspot.com/2007/11/dojo-grid-jester-rails-restful-grid.html"&gt;last post&lt;/a&gt;, I showed you how to hook up the new dojo grid component to a RESTful resource in Rails.  Now we're ready to make it editable.  I promise this will be a shorter post than last time. The key piece is making a new model object to handle our edits.  The dojo grid already provides the key pieces to make editing happen; we just need to provide a way to pass the edited values into our Jester-made object to send them along to our application.  The way we do this is by creating our own model class which extends dojox.grid.data.Objects.  Then we create an instance of this class.  This is what the code looks like:&lt;br /&gt;&lt;pre class="code"&gt;&lt;br /&gt;    dojo.declare(&lt;span class="ST3"&gt;&amp;quot;MyModel&amp;quot;&lt;/span&gt;, dojox.grid.data.Objects, {&lt;br /&gt;      beginModifyRow : &lt;span class="ST1"&gt;function&lt;/span&gt;() {},&lt;br /&gt;      endModifyRow : &lt;span class="ST1"&gt;function&lt;/span&gt;() {} ,&lt;br /&gt;      setDatum: &lt;span class="ST1"&gt;function&lt;/span&gt;(inDatum, inRowIndex, inColIndex)&lt;br /&gt;      {&lt;br /&gt;        &lt;span class="ST1"&gt;this&lt;/span&gt;.data[inRowIndex][&lt;span class="ST1"&gt;this&lt;/span&gt;.fields.get(inColIndex).key] = inDatum;&lt;br /&gt;        &lt;span class="ST1"&gt;this&lt;/span&gt;.data[inRowIndex].save();&lt;br /&gt;        &lt;span class="ST1"&gt;this&lt;/span&gt;.datumChange(inDatum, inRowIndex, inColIndex);&lt;br /&gt;      }&lt;br /&gt;    });&lt;br /&gt;&lt;br /&gt;    &lt;span class="ST1"&gt;var&lt;/span&gt; model = &lt;span class="ST1"&gt;new&lt;/span&gt; MyModel([{key: &lt;span class="ST3"&gt;&amp;quot;make&amp;quot;&lt;/span&gt;}, {key: &lt;span class="ST3"&gt;&amp;quot;year&amp;quot;&lt;/span&gt;}], cars);  &lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;I'm definitely doing some hackery to make it simpler for myself here.  The beginModifyRow and endModifyRow are dojo methods that get called at the beginning and end of editing a cell.  In the normal dojo implementation these methods make a copy of the object being edited so it can be restored if a user cancels the edit.  In a final version of this code we would want to clone our Car object when we start an edit, but we're just not worrying about it yet.&lt;br /&gt;&lt;br /&gt;The code which actually handles the edit is in the setDatum method.  It get's called with 3 arguments, the new value to set, the row index, and the column index.  We have an array of cars to which makes it easy to lookup the right row, but how do we know which field is in which column?  Well, dojo holds that information for us in the fields property of our model.  The fields property provides a method to get a field object by index, and this field object has a key property which is the name of the property of car that lives in this column. This allows us to set the right property of car.  Saving our changes back is a snap thanks to Jester.  We call save on our car object and we are done.&lt;br /&gt;&lt;br /&gt;Finally, we need to make some changes to our structure object to tell it which cells we want to be editable.  We'll use dojo's simplest built in editor and make both cells editable.  Here's how we do it:&lt;br /&gt;&lt;pre class="code"&gt;&lt;br /&gt; &lt;span class="ST1"&gt;var&lt;/span&gt; structure = [ {&lt;br /&gt;    rows: [[&lt;br /&gt;         {name: &lt;span class="ST3"&gt;'Make'&lt;/span&gt;, editor: dojox.grid.editors.Input},&lt;br /&gt;         {name: &lt;span class="ST3"&gt;'Year'&lt;/span&gt;, editor: dojox.grid.editors.Input}&lt;br /&gt;    ]]&lt;br /&gt; } ];&lt;br /&gt;&lt;/pre&gt;So this is it.  We now have an editable dojo grid saving changes by making REST calls into our Rails app.&lt;br /&gt;&lt;br /&gt;Using a JS component framework like Dojo (or ext, mootools, etc, etc) in combination with Jester seems like it opens up a new way to approach web application development.  I might expound on this in another post.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/719065923860450374-5873809169579925509?l=mysterycoder.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mysterycoder.blogspot.com/feeds/5873809169579925509/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=719065923860450374&amp;postID=5873809169579925509' title='6 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/719065923860450374/posts/default/5873809169579925509'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/719065923860450374/posts/default/5873809169579925509'/><link rel='alternate' type='text/html' href='http://mysterycoder.blogspot.com/2007/11/making-our-restful-grid-editable.html' title='Making our RESTful grid editable'/><author><name>MysteryCoder</name><uri>http://www.blogger.com/profile/12085440439301444384</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_cYfx1Pq0Irc/TOXJ5wxxOVI/AAAAAAAAABQ/bDRzQsFRG6E/S220/Photo%2B15.jpg'/></author><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-719065923860450374.post-1519574261652574577</id><published>2007-11-10T18:07:00.000-08:00</published><updated>2007-11-12T20:11:47.280-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ruby rest dojo components'/><title type='text'>Dojo Grid + Jester + Rails = RESTful grid goodness</title><content type='html'>&lt;style type="text/css"&gt;&lt;br /&gt;&lt;!-- body {color: #000000; background-color: #ffffff; font-family: Monospaced} table {color: #000000; background-color: #e9e8e2; font-family: Monospaced} .ST5 {color: #2e92c7; background-color: #d8eed2} .ST0 {color: #628fb5} .ST6 {color: #ce7b00; background-color: #d8eed2} .line-number {background-color: #e9e8e2} .ST2 {color: #009900} .ST3 {color: #ce7b00} .ST1 {color: #0000e6} .ruby {background-color: #d8eed2} .ST4 {background-color: #d8eed2; font-family: Monospaced; font-weight: bold} --&gt;&lt;br /&gt;&lt;/style&gt;&lt;br /&gt;&lt;br /&gt;I've been experimenting with Javascript component frameworks lately, and that let me to look at Dojo. With their 1.0 release, they have added what looks to be a very powerful Grid component. I thought it would be fun to see how easy it is to get it talking with Rails. It proved to be not much code at all, and I think, kind of nifty. Here's how to do it.&lt;br /&gt;&lt;span style="font-size:130%;"&gt;&lt;br /&gt;Create a Rails app with a RESTful service&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Not gonna go thru how to make a rails app, I'll assume you know that already. I created a little RESTful service with the scaffold generator something like this:&lt;br /&gt;&lt;br /&gt;&lt;pre class="code"&gt;script/generate scaffold_resource Car make:string year:integer&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;Install &lt;a href="http://jesterjs.org/"&gt;Jester&lt;/a&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;When I found Jester it was one of those Open Source Moments for me. You know, the ones where you think: "Hey, wouldn't it be cool if you could..." and then Google and find out someone has already done it. Jester is basically ActiveResource in Javascript. The result makes so ridiculously easy to talk to RESTful services it's not even funny. I installed by unzipping the script and dropping jester.js in public/javascripts in my Rails app.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;Install Dojo 1.0&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Go &lt;a href="http://dojotoolkit.org/"&gt;get it&lt;/a&gt;, unzip it, drop it into public/javascripts.  Nuff said&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;Write the code&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;And now for the fun part :) We'll start with a simple grid that pulls in data by making a RESTful call to our Rails app using Jester.  Later on we'll enhance it to make it editable. First thing you need to know about Dojo is that it is CSS driven. This is definitely a good thing IMO, but it does mean you have to include the right CSS or it won't work at all, trust me ;) So make you sure you include the Dojo Grid CSS like so:&lt;br /&gt;&lt;br /&gt;&lt;pre class="code"&gt;&lt;br /&gt;&lt;span class="line-number"&gt; 5&lt;/span&gt;     &lt;span class="ST1"&gt;&amp;lt;&lt;/span&gt;&lt;span class="ST1"&gt;style&lt;/span&gt; &lt;span class="ST2"&gt;type&lt;/span&gt;&lt;span class="ST2"&gt;=&lt;/span&gt;&lt;span class="ST3"&gt;"text/css"&lt;/span&gt;&lt;span class="ST1"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="line-number"&gt; 6&lt;/span&gt;       &lt;span class="ST1"&gt;@import&lt;/span&gt; &lt;span class="ST3"&gt;"/javascripts/dojo-release-1.0.0/dijit/themes/tundra/tundra.css"&lt;/span&gt;;&lt;br /&gt;&lt;span class="line-number"&gt; 7&lt;/span&gt;       &lt;span class="ST1"&gt;@import&lt;/span&gt; &lt;span class="ST3"&gt;"/javascripts/dojo-release-1.0.0/dojox/grid/_grid/Grid.css"&lt;/span&gt;;&lt;br /&gt;&lt;span class="line-number"&gt; 8&lt;/span&gt;       &lt;span class="ST1"&gt;@import&lt;/span&gt; &lt;span class="ST3"&gt;"/javascripts/dojo-release-1.0.0/dojox/grid/_grid/tundraGrid.css"&lt;/span&gt;;&lt;br /&gt;&lt;span class="line-number"&gt; 9&lt;/span&gt;  &lt;br /&gt;&lt;span class="line-number"&gt;10&lt;/span&gt;     &lt;span class="ST1"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="ST1"&gt;style&lt;/span&gt;&lt;span class="ST1"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Next, we'll need to include Jester and Dojo:&lt;br /&gt;&lt;br /&gt;&lt;pre class="code"&gt;&lt;br /&gt;&lt;span class="line-number"&gt;12&lt;/span&gt;     &lt;span class="ST4"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="ruby"&gt;javascript_include_tag&lt;/span&gt; &lt;span class="ST5"&gt;:&lt;/span&gt;&lt;span class="ST5"&gt;defaults&lt;/span&gt; &lt;span class="ST4"&gt;%&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="line-number"&gt;13&lt;/span&gt;     &lt;span class="ST4"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="ruby"&gt;javascript_include_tag&lt;/span&gt; &lt;span class="ST6"&gt;"&lt;/span&gt;&lt;span class="ST6"&gt;jester&lt;/span&gt;&lt;span class="ST6"&gt;"&lt;/span&gt; &lt;span class="ST4"&gt;%&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="line-number"&gt;14&lt;/span&gt;     &lt;span class="ST1"&gt;&amp;lt;&lt;/span&gt;&lt;span class="ST1"&gt;script&lt;/span&gt; &lt;span class="ST2"&gt;type&lt;/span&gt;&lt;span class="ST2"&gt;=&lt;/span&gt;&lt;span class="ST3"&gt;"text/javascript"&lt;/span&gt;&lt;br /&gt;&lt;span class="line-number"&gt;15&lt;/span&gt;             &lt;span class="ST2"&gt;src&lt;/span&gt;&lt;span class="ST2"&gt;=&lt;/span&gt;&lt;span class="ST3"&gt;"/javascripts/dojo-release-1.0.0/dojo/dojo.js"&lt;/span&gt;&lt;br /&gt;&lt;span class="line-number"&gt;16&lt;/span&gt;             &lt;span class="ST2"&gt;djConfig&lt;/span&gt;&lt;span class="ST2"&gt;=&lt;/span&gt;&lt;span class="ST3"&gt;"parseOnLoad: true"&lt;/span&gt;&lt;span class="ST1"&gt;&amp;gt;&lt;/span&gt;&lt;span class="ST1"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="ST1"&gt;script&lt;/span&gt;&lt;span class="ST1"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Including Jester is just a matter of including using the standard javascript_include_tag helper, but dojo is a little wierd.  You'll notice the djConfig attribute for starters.  How does this even work?  djConfig is not even a valid attribute for a script tag, right?  As best I understand it, and someone please jump in if I'm wrong, dojo has a parser of it's own that comes along after your page load sand does things to it.  This let's you add dojo components to your page "declaratively", or in html, instead of have to use so much javascript.  Kind of interesting.&lt;br /&gt;&lt;br /&gt;Now let's look at the script block that sets up the objects our grid will need:&lt;br /&gt;&lt;br /&gt;&lt;pre class="code"&gt;&lt;br /&gt;&lt;span class="line-number"&gt;18&lt;/span&gt;     &lt;span class="ST1"&gt;&amp;lt;&lt;/span&gt;&lt;span class="ST1"&gt;script&lt;/span&gt; &lt;span class="ST2"&gt;type&lt;/span&gt;&lt;span class="ST2"&gt;=&lt;/span&gt;&lt;span class="ST3"&gt;"text/javascript"&lt;/span&gt;&lt;span class="ST1"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="line-number"&gt;19&lt;/span&gt;     dojo.require(&lt;span class="ST3"&gt;"dojo.parser"&lt;/span&gt;);&lt;br /&gt;&lt;span class="line-number"&gt;20&lt;/span&gt;     dojo.require(&lt;span class="ST3"&gt;"dojox.grid.Grid"&lt;/span&gt;);&lt;br /&gt;&lt;span class="line-number"&gt;21&lt;/span&gt;     dojo.require(&lt;span class="ST3"&gt;"dojox.grid._data.model"&lt;/span&gt;);&lt;br /&gt;&lt;span class="line-number"&gt;22&lt;/span&gt;&lt;br /&gt;&lt;span class="line-number"&gt;23&lt;/span&gt;     Resource.model(&lt;span class="ST3"&gt;"Car"&lt;/span&gt;);&lt;br /&gt;&lt;span class="line-number"&gt;24&lt;/span&gt;     cars = Car.find(&lt;span class="ST3"&gt;"all"&lt;/span&gt;);&lt;br /&gt;&lt;span class="line-number"&gt;25&lt;/span&gt;&lt;br /&gt;&lt;span class="line-number"&gt;26&lt;/span&gt;     &lt;span class="ST1"&gt;var&lt;/span&gt; model = &lt;span class="ST1"&gt;new&lt;/span&gt; dojox.grid.data.Objects([{key: &lt;span class="ST3"&gt;"make"&lt;/span&gt;}, {key: &lt;span class="ST3"&gt;"year"&lt;/span&gt;}], cars);&lt;br /&gt;&lt;span class="line-number"&gt;27&lt;/span&gt;&lt;br /&gt;&lt;span class="line-number"&gt;28&lt;/span&gt;     &lt;span class="ST1"&gt;var&lt;/span&gt; structure = [ {&lt;br /&gt;&lt;span class="line-number"&gt;29&lt;/span&gt;        rows: [[&lt;br /&gt;&lt;span class="line-number"&gt;30&lt;/span&gt;             {name: &lt;span class="ST3"&gt;'Make'&lt;/span&gt;},&lt;br /&gt;&lt;span class="line-number"&gt;31&lt;/span&gt;             {name: &lt;span class="ST3"&gt;'Year'&lt;/span&gt;}&lt;br /&gt;&lt;span class="line-number"&gt;32&lt;/span&gt;        ]]&lt;br /&gt;&lt;span class="line-number"&gt;33&lt;/span&gt;     } ];&lt;br /&gt;&lt;span class="line-number"&gt;34&lt;/span&gt;&lt;br /&gt;&lt;span class="line-number"&gt;35&lt;/span&gt;&lt;br /&gt;&lt;span class="line-number"&gt;36&lt;/span&gt;     &lt;span class="ST1"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="ST1"&gt;script&lt;/span&gt;&lt;span class="ST1"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;The first thing you'll notice is those dojo.require statements.  These are how you tell dojo to go get all of the pieces it needs.  Dojo is broken down into lots of individual javascript files, and while you could just include them all in script tags, that would be kind of a pain.  dojo.require basically says "go get this piece and all of it's dependencies".  It makes it easier to use some of dojo and not all of dojo as well.&lt;br /&gt;&lt;br /&gt;Next we see Jester in action.  Kind of puts dojo to shame from an ease of use standpoint, doesn't it?  You tell Jester which model you want, and it makes a javascript class for you.  We then call find all and it gives us back an array javascript proxy objects with the fields and methods you would expect.  Like I said, ridiculously easy.  There are options to have it do find (and save) asynchronously as well, which you would probably want to use for a real application.&lt;br /&gt;&lt;br /&gt;Next we setup some objects our dojo grid needs.  The first is a model, it tells dojo where to get it's data from.  We're able to use of the built in types of models, dojo.grid.data.Objects.  This kind of model will display an array of Javascript objects, which, conveniently enough, is exactly what we got back from the call to find.  We have to give it a little more information, though, namely what properties to display in which columns of our grid.  This is what we're doing in the first argument to the constructor.  The second argument is our array of cars we got back from the call to Car.find("all").&lt;br /&gt;&lt;br /&gt;Finally, we have an object that tells how we want our grid organized.  I have to say this seems a lot more complicated than I'd like.  It seems to me sometimes dojo is more focused on making the hard things possible than making the simple things simple.  So I'm not even going to try to cover all the details of the structure object here, but briefly dojo grid structures consist of an array of views which have an array of rows which have an array of subrows.  Phew.  I think it would be possible to come up with a simpler structure object for simpler cases, but that would require more dojo-fu than I have yet.&lt;br /&gt;&lt;br /&gt;At last, we're ready to put in the html for our grid.  Here it is:&lt;br /&gt;&lt;br /&gt;&lt;pre class="code"&gt;&lt;br /&gt;&lt;span class="line-number"&gt;42&lt;/span&gt;   &lt;span class="ST1"&gt;&amp;lt;&lt;/span&gt;&lt;span class="ST1"&gt;div&lt;/span&gt; &lt;span class="ST2"&gt;id&lt;/span&gt;&lt;span class="ST2"&gt;=&lt;/span&gt;&lt;span class="ST3"&gt;"grid"&lt;/span&gt; &lt;span class="ST2"&gt;dojoType&lt;/span&gt;&lt;span class="ST2"&gt;=&lt;/span&gt;&lt;span class="ST3"&gt;"dojox.Grid"&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="line-number"&gt;43&lt;/span&gt;        &lt;span class="ST2"&gt;model&lt;/span&gt;&lt;span class="ST2"&gt;=&lt;/span&gt;&lt;span class="ST3"&gt;"model"&lt;/span&gt; &lt;span class="ST2"&gt;structure&lt;/span&gt;&lt;span class="ST2"&gt;=&lt;/span&gt;&lt;span class="ST3"&gt;"structure"&lt;/span&gt;&lt;br /&gt;&lt;span class="line-number"&gt;44&lt;/span&gt;        &lt;span class="ST2"&gt;autoWidth&lt;/span&gt;&lt;span class="ST2"&gt;=&lt;/span&gt;&lt;span class="ST3"&gt;"true"&lt;/span&gt; &lt;span class="ST2"&gt;autoHeight&lt;/span&gt;&lt;span class="ST2"&gt;=&lt;/span&gt;&lt;span class="ST3"&gt;"true"&lt;/span&gt;&lt;span class="ST1"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="line-number"&gt;45&lt;/span&gt;   &lt;span class="ST1"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="ST1"&gt;div&lt;/span&gt;&lt;span class="ST1"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Not much to it is there.  Notice how we can set properties of our grid with html attributes.  This is what the dojo parser does for us, as I understand it.  Here we're passing in the model and structure we created in our script block.&lt;br /&gt;&lt;br /&gt;So this is all that's required to use the dojo grid component and have it pull data from a REST service implemented in Rails.  In my next post I'll show you how to have it be editable and save it's data using thru REST as well.  It's easier than you might think.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/719065923860450374-1519574261652574577?l=mysterycoder.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mysterycoder.blogspot.com/feeds/1519574261652574577/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=719065923860450374&amp;postID=1519574261652574577' title='10 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/719065923860450374/posts/default/1519574261652574577'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/719065923860450374/posts/default/1519574261652574577'/><link rel='alternate' type='text/html' href='http://mysterycoder.blogspot.com/2007/11/dojo-grid-jester-rails-restful-grid.html' title='Dojo Grid + Jester + Rails = RESTful grid goodness'/><author><name>MysteryCoder</name><uri>http://www.blogger.com/profile/12085440439301444384</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_cYfx1Pq0Irc/TOXJ5wxxOVI/AAAAAAAAABQ/bDRzQsFRG6E/S220/Photo%2B15.jpg'/></author><thr:total>10</thr:total></entry><entry><id>tag:blogger.com,1999:blog-719065923860450374.post-6979417773804597857</id><published>2007-10-24T20:44:00.000-07:00</published><updated>2007-10-24T21:23:52.116-07:00</updated><title type='text'>Debugging a JRuby on Rails app with jruby-debug and NetBeans</title><content type='html'>We've been working on the java port of ruby-debug for awhile and it's getting perilously close to usable.  And with the latest builds of NetBeans, you can actually use the NB ruby debugger with it.  If you're very brave, you can try it for your yourself.  Be warned, it's still a work in progress, but here's how to get started:&lt;br /&gt;&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Check out jruby from trunk and build it.  You'll need java and ant, but if you're interested in jruby chances are good you have those already.  It's super easy to build, check it out from http://svn.codehaus.org/jruby/trunk and do &lt;span style="font-family:courier new;"&gt;ant dist&lt;/span&gt; and you're good to go.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Check out jruby-debug from http://debug-commons.rubyforge.org/svn/jruby-debug/trunk.  In this directory, do rake install_gem.  This will compile and build a jruby version ruby-debug-base, which ruby-debug (command line rdebug debugger) and ruby-debug-ide (which NetBeans and Eclipse use) both depend on.&lt;/li&gt;&lt;li&gt;Check out ruby-debug-ide from http://debug-commons.rubyforge.org/svn/trunk/ruby-debug-ide.  Then do a rake gem to build the gem and gem install pkg/ruby-debug-ide-0.1.8.gem to install it.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Grab a copy of NetBeans daily builds ruby ide from here: http://deadlock.netbeans.org/hudson/job/ruby/&lt;/li&gt;&lt;li&gt;Fire up NetBeans like with some extra command line switches: ./netbeans -J-Dorg.netbeans.modules.ruby.debugger.force.rdebug=true -J-Dorg.netbeans.modules.ruby.debugger.fast.not.required=true&lt;br /&gt;The first tells NetBeans to always use the fast debugger even tho the classic debugger is what appears selected in the UI.  The second tells NB to ignore the fact that the classic debugger is selected and allow us to debug a rails app anways.  These flags were just added to allow us to play with jruby-debug in NetBeans for now, they won't be necessary once jruby-debug matures a little and full support for it comes into NB.&lt;/li&gt;&lt;li&gt;In NetBeans Tools | Options be sure and have your ruby interpreter pointing at the jruby you built from trunk in Step 1.&lt;/li&gt;&lt;/ol&gt;You should now be able to debug Ruby and ROR apps using the fast ruby debugger inside of jruby.  Like I said, this is all very experimental.  All these steps will go away in the next few weeks or months and jruby-debug, jruby, NetBeans, ruby-debug-ide do releases.&lt;br /&gt;&lt;br /&gt;Things which seem to work ok:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;setting breakpoints&lt;/li&gt;&lt;li&gt;looking at variables (global and local)&lt;/li&gt;&lt;li&gt;watches&lt;/li&gt;&lt;/ul&gt;A little flaky (tho it may already be fixed by the time you read this):&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Stepping over some code in Rails&lt;/li&gt;&lt;li&gt;Stepping out of a method&lt;/li&gt;&lt;/ul&gt;Finally, big time kudos to Martin for kicking this whole thing off and Peter for knocking out bugs and implementing more features every hour just about.  It's definitely looking close now.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/719065923860450374-6979417773804597857?l=mysterycoder.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mysterycoder.blogspot.com/feeds/6979417773804597857/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=719065923860450374&amp;postID=6979417773804597857' title='6 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/719065923860450374/posts/default/6979417773804597857'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/719065923860450374/posts/default/6979417773804597857'/><link rel='alternate' type='text/html' href='http://mysterycoder.blogspot.com/2007/10/debugging-jruby-on-rails-app-with-jruby.html' title='Debugging a JRuby on Rails app with jruby-debug and NetBeans'/><author><name>MysteryCoder</name><uri>http://www.blogger.com/profile/12085440439301444384</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_cYfx1Pq0Irc/TOXJ5wxxOVI/AAAAAAAAABQ/bDRzQsFRG6E/S220/Photo%2B15.jpg'/></author><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-719065923860450374.post-2855378454738701612</id><published>2007-10-21T14:09:00.000-07:00</published><updated>2007-10-21T11:43:02.913-07:00</updated><title type='text'>Avoiding Helpful Tools Considered Stupid</title><content type='html'>Rarely does a blog post get me all fired up like &lt;a href="http://gilesbowkett.blogspot.com/2007/10/debugger-support-considered-harmful.html"&gt;Giles Bowketts&lt;/a&gt; here.  As part of the team working on improving debugging support for JRuby, it probably struck a particularly personal chord.  Nothing like having your hard work publicly ridiculed to get you exicted.  I might have ignored it, and maybe I probably should, but the post contains some truly exceptional BS that needs to be addressed.&lt;br /&gt;&lt;br /&gt;First off, it claims to inspired by a good friend of mine.  So Giles, to quote from that famous vice presedential debate: I know Jim Weirich, and you sir, are no Jim Weirich!  Ok, so maybe Giles didn't actually claim to &lt;span style="font-weight: bold;"&gt;be&lt;/span&gt; Jim Weirich, but the fact that he even attributed Jim in any way while spouting such blatent poppycock just shouldn't be.&lt;br /&gt;&lt;br /&gt;As part of my job I have the incredible good fortune to pair with Jim on a Rails project. At the risk of pointing out what should be obvious, we do write test cases.  And, it's true, when we first started working together, we did not use a debugger.  Most of the time, we didn't need one.  But every so often, we would have a situation where we couldn't understand what some code was doing.  More embarrassing still, sometimes it was &lt;span&gt;even &lt;/span&gt;&lt;span style="font-weight: bold;"&gt;code that we wrote&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;So, when confronted with such a situation, when we couldn't think of any more test cases to write, we would add statements like this to our code "puts DBG: #{some_value_we_want_to_see}".  Wow, perty high tech, eh?  And it worked.  We could always solve our problem this way.  Jim even had a little rake task that would comb thru the code to find DBG: in our code so we could easily remove these when we were done.&lt;br /&gt;&lt;br /&gt;Then one day I got tired of us typing DBG: in our code and I said something like "Let's try using rdebug". And guess what: &lt;span style="font-style: italic;"&gt;rdebug was often handier than adding puts statements to our code&lt;/span&gt;.  We could inspect all kinds of stuff.  Sometimes it helped us learn more about how Rails works, especially when it did things that were, umm, a little unexpected.  It was a good thing.  So much so, in fact, Jim spent some time working on getting it working better with emacs so it was even easier to use.&lt;br /&gt;&lt;br /&gt;And, hard to believe tho it may be, it &lt;span style="font-weight: bold;"&gt;did not cause us to write less test cases&lt;/span&gt;.  Every time we learned something while debugging, we could go back and write a test case which documented our learning. In the end it helped us to write more and better test cases &lt;span style="font-style: italic;"&gt;because we were actively trying to do so&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;So it should be obvious, but since it didn't seem to be I'll state it: &lt;span style="font-weight: bold;"&gt;debuggers are tools&lt;/span&gt;.  Like any tool, if it helps you do your work better, you might want to use it.  If it doesn't you probably shouldn't.  Using a tool does not lead to bad habits, bad habits lead to using a tool incorrectly.  And it's worth pointing out, the technique of classifying a technology or tool as bad because it can be used incorrectly is &lt;span style="font-weight: bold;"&gt;exactly&lt;/span&gt; the argument that I hear made against metaprogramming and run time type checking.  Kind of ironic.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/719065923860450374-2855378454738701612?l=mysterycoder.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mysterycoder.blogspot.com/feeds/2855378454738701612/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=719065923860450374&amp;postID=2855378454738701612' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/719065923860450374/posts/default/2855378454738701612'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/719065923860450374/posts/default/2855378454738701612'/><link rel='alternate' type='text/html' href='http://mysterycoder.blogspot.com/2007/10/avoiding-helpful-tools-considered.html' title='Avoiding Helpful Tools Considered Stupid'/><author><name>MysteryCoder</name><uri>http://www.blogger.com/profile/12085440439301444384</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_cYfx1Pq0Irc/TOXJ5wxxOVI/AAAAAAAAABQ/bDRzQsFRG6E/S220/Photo%2B15.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-719065923860450374.post-5591526712319666799</id><published>2007-08-08T09:40:00.000-07:00</published><updated>2007-08-08T09:58:36.318-07:00</updated><title type='text'>Geeky Fatherhood Moment</title><content type='html'>Some dads live for moments like when their son can beat them at basketball or throw a touchdown pass at a high school football game.  Since my family seems to share my, ahem, lack of athletic prowess, I mostly get my "dad pride" fixes in different ways.  For example, today my 10 yr old son asked me a question that nearly brought a tear to his old man's eye:&lt;br /&gt;&lt;br /&gt;"Dad is there a job you can have when you grow up where you use Gimp?"&lt;br /&gt;&lt;br /&gt;:)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/719065923860450374-5591526712319666799?l=mysterycoder.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mysterycoder.blogspot.com/feeds/5591526712319666799/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=719065923860450374&amp;postID=5591526712319666799' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/719065923860450374/posts/default/5591526712319666799'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/719065923860450374/posts/default/5591526712319666799'/><link rel='alternate' type='text/html' href='http://mysterycoder.blogspot.com/2007/08/geeky-fatherhood-moment.html' title='Geeky Fatherhood Moment'/><author><name>MysteryCoder</name><uri>http://www.blogger.com/profile/12085440439301444384</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_cYfx1Pq0Irc/TOXJ5wxxOVI/AAAAAAAAABQ/bDRzQsFRG6E/S220/Photo%2B15.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-719065923860450374.post-5124376258279196761</id><published>2007-08-02T17:53:00.000-07:00</published><updated>2007-08-02T14:54:13.342-07:00</updated><title type='text'>Spring Rails Plugin 0.1</title><content type='html'>Well, I finally checked in my code for a Spring Rails plugin.  Consider it pre-alpha at this point.  It's unit tested, and I made a simple example app to prove that it works.  But that's about it.  So if you find it useful, try it out and let me know so I can decide where to go with it next.&lt;br /&gt;&lt;br /&gt;To install the plugin:&lt;br /&gt;&lt;br /&gt;&lt;pre class="code"&gt;script/plugin install svn://rubyforge.org/var/svn/jruby-extras/trunk/rails-integration/plugins/spring&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;You'll need to get a basic Rails application working with the goldspike plugin in order for the Spring plugin to be of use.  Currently it loads the Spring ApplicationContext by getting it from the ServletContext (which assumes you are using the Spring context listener to put it there).  So if you're not running Rails in a servlet engine it doesn't work.  If there is real interest in having the plugin be able to get an app context from somewhere else I'll look at supporting that down the road.&lt;br /&gt;&lt;br /&gt;For an example of how to use it in a controller, see my previous post.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Why you shouldn't use it&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;If you're a Java programmer new to (J)Ruby and are thinking: "Awesome, I'll use Spring in all my Rails apps because Spring is awesome!" you need to hold up a second.  Spring is awesome -- when you are developing Java applications.  But in Ruby, dependency injection turns out to be unnecessary a whole lot of the time.  This is because the Ruby language allows you to change things in a more straightforward way.  And even if there were cases where you needed DI in Ruby there are probably better choices.  I see the Spring plugin being useful where you have existing J2EE code wired together with Spring and want to front end it in JRuby on Rails.  So use this plugin if you need it, but if you don't, then don't.&lt;br /&gt;&lt;br /&gt;Don't take my word for DI and Ruby, my friend Jim had this &lt;a href="http://onestepback.org/index.cgi/Tech/Ruby/DependencyInjectionInOneSentence.red"&gt;blog post&lt;/a&gt; about it after our IM conversation.  See the comments where other Ruby heavyweights weigh in on the subject.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/719065923860450374-5124376258279196761?l=mysterycoder.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mysterycoder.blogspot.com/feeds/5124376258279196761/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=719065923860450374&amp;postID=5124376258279196761' title='10 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/719065923860450374/posts/default/5124376258279196761'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/719065923860450374/posts/default/5124376258279196761'/><link rel='alternate' type='text/html' href='http://mysterycoder.blogspot.com/2007/08/spring-rails-plugin-01.html' title='Spring Rails Plugin 0.1'/><author><name>MysteryCoder</name><uri>http://www.blogger.com/profile/12085440439301444384</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_cYfx1Pq0Irc/TOXJ5wxxOVI/AAAAAAAAABQ/bDRzQsFRG6E/S220/Photo%2B15.jpg'/></author><thr:total>10</thr:total></entry><entry><id>tag:blogger.com,1999:blog-719065923860450374.post-3202364894286187288</id><published>2007-07-28T09:52:00.000-07:00</published><updated>2007-07-28T10:28:40.130-07:00</updated><title type='text'>eRubyCon was awesome</title><content type='html'>Just wanted to get in a blog, albeit a week and a half late, about eRubyCon.  It was an awesome conference; I felt honored being involved as a speaker doing a presentation on JRuby.  Being among such incredible speakers as Jim Weirich, Glen Vandenburg, Stuart Holloway, and many others made me a little like the scene in Wayne's World where Wayne and Garth meet Alice Cooper: I'm not worthy!&lt;br /&gt;&lt;br /&gt;As far as I know, this is the first conference specifically devoted to Ruby in the Enterprise.  If all you've gotten is the 30 second soundbytes about Ruby and Rails this may sound like an oxymoron, but it's not.  The other speakers, particularly Glen in his "Enterprise Schmenterprise" keynote made this point eloquently.  Ruby, because of it's excellence at producing easily understood and therefore much more maintainable code, is the perfect language to develop the kind of applications thought of as "enterprisey".  Glen: "Enterprises aren't ready for Ruby, they're &lt;span style="font-weight:bold;"&gt;desperate&lt;span style="font-weight:bold;"&gt;&lt;/span&gt;&lt;/span&gt; for it".&lt;br /&gt;&lt;br /&gt;Stuart made a point in his blog about this too.  His &lt;a href="http://www.relevancellc.com/2007/6/6/ruby-vs-java-myth-5-it-s-a-zero-sum-game"&gt;series&lt;/a&gt; on Ruby vs Java myths made the point that Ruby is actually better for large applications than for small ones.  Definitely worth a read.&lt;br /&gt;&lt;br /&gt;Finally a big Thanks! to Joe at &lt;a href="http://www.theedgecase.com/"&gt;Edgecase&lt;/a&gt; for putting this together.  Joe, I know it was a lot of effort time and finance wise but I hope the community can grow enough to make this a viable yearly conference: the word about Ruby really needs to get out in the enterprise development area.  For their sake and ours.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/719065923860450374-3202364894286187288?l=mysterycoder.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mysterycoder.blogspot.com/feeds/3202364894286187288/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=719065923860450374&amp;postID=3202364894286187288' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/719065923860450374/posts/default/3202364894286187288'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/719065923860450374/posts/default/3202364894286187288'/><link rel='alternate' type='text/html' href='http://mysterycoder.blogspot.com/2007/07/erubycon-was-awesome.html' title='eRubyCon was awesome'/><author><name>MysteryCoder</name><uri>http://www.blogger.com/profile/12085440439301444384</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_cYfx1Pq0Irc/TOXJ5wxxOVI/AAAAAAAAABQ/bDRzQsFRG6E/S220/Photo%2B15.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-719065923860450374.post-1520192763386860917</id><published>2007-06-21T08:36:00.000-07:00</published><updated>2007-06-21T12:54:54.428-07:00</updated><title type='text'>include Spring</title><content type='html'>I've gotten a little farther with my JRuby on Rails Spring integration code.  I think I have what may make the beginning of a Spring plugin for JRuby on Rails.  Here's the code for the Spring module.  This is my first foray into metaprogramming in Ruby, I'd welcome any feedback.&lt;br /&gt;&lt;br /&gt;&lt;pre class="code"&gt;&lt;span class="comment"&gt;# spring.rb&lt;/span&gt;&lt;br /&gt;&lt;span class="comment"&gt;# June 20, 2007&lt;/span&gt;&lt;br /&gt;&lt;span class="comment"&gt;#&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="keyword"&gt;module &lt;/span&gt;&lt;span class="module"&gt;Spring&lt;/span&gt;&lt;br /&gt;  &lt;span class="ident"&gt;include&lt;/span&gt; &lt;span class="constant"&gt;Java&lt;/span&gt;&lt;br /&gt;  &lt;span class="ident"&gt;import&lt;/span&gt; &lt;span class="ident"&gt;javax&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;servlet&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;ServletContext&lt;/span&gt;&lt;br /&gt;  &lt;span class="ident"&gt;import&lt;/span&gt; &lt;span class="ident"&gt;org&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;springframework&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;web&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;context&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;WebApplicationContext&lt;/span&gt;&lt;br /&gt;  &lt;span class="ident"&gt;import&lt;/span&gt; &lt;span class="ident"&gt;org&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;springframework&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;web&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;context&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;support&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;WebApplicationContextUtils&lt;/span&gt;&lt;br /&gt;  &lt;br /&gt;  &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;spring_bean&lt;/span&gt; &lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;bean&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;&lt;br /&gt;    &lt;span class="ident"&gt;class_eval&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;def &lt;span class="expr"&gt;#{bean.to_s}&lt;/span&gt;; application_context.get_bean(&lt;span class="escape"&gt;\&amp;quot;&lt;/span&gt;&lt;span class="expr"&gt;#{bean.to_s}&lt;/span&gt;&lt;span class="escape"&gt;\&amp;quot;&lt;/span&gt;); end;&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt; &lt;br /&gt;  &lt;span class="keyword"&gt;end&lt;/span&gt;&lt;br /&gt;  &lt;br /&gt;  &lt;span class="comment"&gt;# dunno if there is a better way to do this.  I need the spring_bean method&lt;/span&gt;&lt;br /&gt;  &lt;span class="comment"&gt;# to become a class method on the includee, but application_context needs to be&lt;/span&gt;&lt;br /&gt;  &lt;span class="comment"&gt;# a normal instance method&lt;/span&gt;&lt;br /&gt;  &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;self.append_features&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;includee&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;&lt;br /&gt;    &lt;span class="ident"&gt;includee&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;extend&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="constant"&gt;Spring&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;&lt;br /&gt;    &lt;span class="ident"&gt;includee&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;class_eval&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt;&lt;br /&gt;      &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;application_context&lt;/span&gt;&lt;br /&gt;        &lt;span class="constant"&gt;WebApplicationContextUtils&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;getWebApplicationContext&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="global"&gt;$servlet_context&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;&lt;br /&gt;      &lt;span class="keyword"&gt;end&lt;/span&gt;      &lt;br /&gt;    &lt;span class="keyword"&gt;end&lt;/span&gt;&lt;br /&gt;  &lt;span class="keyword"&gt;end&lt;/span&gt;&lt;br /&gt;&lt;span class="keyword"&gt;end&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;This gives you a handy spring_bean method in any class where you've included Spring.  The spring_bean method will then dynamically add an accessor to the class you use it in.  This is what it looks like in a controller:&lt;br /&gt;&lt;br /&gt;&lt;pre class="code"&gt;&lt;span class="keyword"&gt;class &lt;/span&gt;&lt;span class="class"&gt;TestSpringController&lt;/span&gt; &lt;span class="punct"&gt;&amp;lt;&lt;/span&gt; &lt;span class="constant"&gt;ApplicationController&lt;/span&gt;&lt;br /&gt; &lt;span class="ident"&gt;include&lt;/span&gt; &lt;span class="constant"&gt;Spring&lt;/span&gt;&lt;br /&gt; &lt;span class="ident"&gt;spring_bean&lt;/span&gt; &lt;span class="symbol"&gt;:descriptor1&lt;/span&gt;&lt;br /&gt; &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;showcontext&lt;/span&gt;  &lt;br /&gt;   &lt;span class="ident"&gt;render_text&lt;/span&gt; &lt;span class="ident"&gt;descriptor1&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;displayName&lt;/span&gt;&lt;br /&gt; &lt;span class="keyword"&gt;end&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="keyword"&gt;end&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Obviously to have this working you need several things.  You need to have the goldspike plugin (from SVN trunk as per my earlier post).  You also need to have Spring and its dependent jars in your WEB-INF/lib.  I just copied em in for playing around purposes, with a little tweaking of my conf/war.rb file I could probably make goldspike fetch them.  And lastly, it assumes you have an applicationContext.xml in WEB-INF, and that you have the Spring ContextLoaderListener declared in your web.xml.&lt;br /&gt;&lt;br /&gt;Wow, that's a lot of trouble, why the heck would I want to do all that?  What's this all for anyways?  First of all, if you need this you probably don't need to ask, you know who you are.  No, I'm not even trying to suggest using Spring for greenfield JRuby on Rails applications.  But if you need to do heavy Java integration or you have an existing Spring application you want to front end in Rails, this kind of thing could end up being quite handy.  This is my situation: I have a pretty large Spring/Hibernate/Tapestry app and I'd like to make moving to JRuby on Rails a viable option.  Rather than replace everything whole hog, I'd like to be able to leverage working Spring services easily from Rails.  As you can see, doing this should be a piece of cake.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/719065923860450374-1520192763386860917?l=mysterycoder.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mysterycoder.blogspot.com/feeds/1520192763386860917/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=719065923860450374&amp;postID=1520192763386860917' title='7 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/719065923860450374/posts/default/1520192763386860917'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/719065923860450374/posts/default/1520192763386860917'/><link rel='alternate' type='text/html' href='http://mysterycoder.blogspot.com/2007/06/include-spring.html' title='include Spring'/><author><name>MysteryCoder</name><uri>http://www.blogger.com/profile/12085440439301444384</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_cYfx1Pq0Irc/TOXJ5wxxOVI/AAAAAAAAABQ/bDRzQsFRG6E/S220/Photo%2B15.jpg'/></author><thr:total>7</thr:total></entry><entry><id>tag:blogger.com,1999:blog-719065923860450374.post-5535960421493293675</id><published>2007-06-18T00:12:00.000-07:00</published><updated>2007-06-17T21:32:53.404-07:00</updated><title type='text'>Spring + JRuby on Rails</title><content type='html'>I've only been threatening to do this for a year, but I finally added the necessary stuff to have JRuby on Rails talking to Spring.  There's a lot more to come here, but this controller code demonstrates being able to get ahold of a Spring WebApplicationContext in a Ruby on Rails controller.  &lt;br /&gt;&lt;pre class="code"&gt;&lt;br /&gt;&lt;span class="keyword"&gt;class &lt;/span&gt;&lt;span class="class"&gt;TestservletController&lt;/span&gt; &lt;span class="punct"&gt;&amp;lt;&lt;/span&gt; &lt;span class="constant"&gt;ApplicationController&lt;/span&gt;&lt;br /&gt;  &lt;span class="ident"&gt;include&lt;/span&gt; &lt;span class="constant"&gt;Java&lt;/span&gt;&lt;br /&gt;  &lt;span class="ident"&gt;import&lt;/span&gt; &lt;span class="ident"&gt;javax&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;servlet&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;ServletContext&lt;/span&gt;&lt;br /&gt;  &lt;span class="ident"&gt;import&lt;/span&gt; &lt;span class="ident"&gt;org&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;springframework&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;web&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;context&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;WebApplicationContext&lt;/span&gt;&lt;br /&gt;  &lt;span class="ident"&gt;import&lt;/span&gt; &lt;span class="ident"&gt;org&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;springframework&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;web&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;context&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;support&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;WebApplicationContextUtils&lt;/span&gt;&lt;br /&gt;  &lt;br /&gt;  &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;showcontext&lt;/span&gt;&lt;br /&gt;    &lt;span class="ident"&gt;app_context&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="constant"&gt;WebApplicationContextUtils&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;getWebApplicationContext&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="global"&gt;$servlet_context&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;&lt;br /&gt;    &lt;span class="ident"&gt;render_text&lt;/span&gt; &lt;span class="ident"&gt;app_context&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;display_name&lt;/span&gt;&lt;br /&gt;  &lt;span class="keyword"&gt;end&lt;/span&gt;&lt;br /&gt;&lt;span class="keyword"&gt;end&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;In order for this to work, you'll have to use the very latest goldspike-snapshot plugin from SVN trunk.  I just checked in the code to expose $servlet_context earlier today.  Obviously this code will only work using a servlet container, and you'll need to have Spring and necessary deps in WEB-INF/lib and have the Spring context loader listener in your web.xml.  From here, my next step is some metaprogramming to allow you to add spring bean accessors into your controllers.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/719065923860450374-5535960421493293675?l=mysterycoder.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mysterycoder.blogspot.com/feeds/5535960421493293675/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=719065923860450374&amp;postID=5535960421493293675' title='13 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/719065923860450374/posts/default/5535960421493293675'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/719065923860450374/posts/default/5535960421493293675'/><link rel='alternate' type='text/html' href='http://mysterycoder.blogspot.com/2007/06/spring-jruby.html' title='Spring + JRuby on Rails'/><author><name>MysteryCoder</name><uri>http://www.blogger.com/profile/12085440439301444384</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_cYfx1Pq0Irc/TOXJ5wxxOVI/AAAAAAAAABQ/bDRzQsFRG6E/S220/Photo%2B15.jpg'/></author><thr:total>13</thr:total></entry><entry><id>tag:blogger.com,1999:blog-719065923860450374.post-7432766248654814503</id><published>2007-04-22T23:30:00.000-07:00</published><updated>2007-04-22T20:32:51.044-07:00</updated><title type='text'>API unickifying with JRuby</title><content type='html'>&lt;style type="text/css"&gt;&lt;br /&gt;&lt;!-- body {color: #000000; background-color: #ffffff; font-family: Monospaced} table {color: #000000; background-color: #e9e8e2; font-family: Monospaced} .ST2 {font-family: Monospaced; font-style: italic} .ST0 {color: #737373} .ST1 {color: #99006b} .ST3 {color: #000099; font-family: Monospaced; font-weight: bold} .ST4 {color: #780000} --&gt;&lt;/style&gt;&lt;br /&gt;So I've been putting together some code examples for RubyCodeCamp in Columbus in a couple weeks.  Quite awhile back I ran into a situation where I wanted to read an Excel spreadsheet from Ruby.  At the time, there was no good way to do it in Ruby (MRI) and so I used Java and the nifty POI library.  I thought this might be make for a nice example in JRuby.  So I fired up jirb and started coding.  In a few minutes I was reading data from a spreadsheet:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&lt;br /&gt;require &lt;span class="ST1"&gt;'&lt;/span&gt;&lt;span class="ST1"&gt;java&lt;/span&gt;&lt;span class="ST1"&gt;'&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;require &lt;span class="ST1"&gt;'&lt;/span&gt;&lt;span class="ST1"&gt;/home/ccnelson/java/poi/poi-2.5.1-final-20040804.jar&lt;/span&gt;&lt;span class="ST1"&gt;'&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;include_class &lt;span class="ST1"&gt;'&lt;/span&gt;&lt;span class="ST1"&gt;org.apache.poi.poifs.filesystem.POIFSFileSystem&lt;/span&gt;&lt;span class="ST1"&gt;'&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;include_class &lt;span class="ST1"&gt;'&lt;/span&gt;&lt;span class="ST1"&gt;org.apache.poi.hssf.usermodel.HSSFWorkbook&lt;/span&gt;&lt;span class="ST1"&gt;'&lt;/span&gt;&lt;br /&gt;include_class &lt;span class="ST1"&gt;'&lt;/span&gt;&lt;span class="ST1"&gt;org.jruby.util.IOInputStream&lt;/span&gt;&lt;span class="ST1"&gt;'&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="ST2"&gt;File&lt;/span&gt;.open(&lt;span class="ST1"&gt;"&lt;/span&gt;&lt;span class="ST1"&gt;/home/ccnelson/documents/Invoice15.xls&lt;/span&gt;&lt;span class="ST1"&gt;"&lt;/span&gt;) &lt;span class="ST3"&gt;do&lt;/span&gt; |f|&lt;br /&gt;workbook = &lt;span class="ST2"&gt;HSSFWorkbook&lt;/span&gt;.new(&lt;span class="ST2"&gt;IOInputStream&lt;/span&gt;.new(f))&lt;br /&gt;puts &lt;span class="ST1"&gt;"&lt;/span&gt;&lt;span class="ST1"&gt;cell 0,0: &lt;/span&gt;&lt;span class="ST1"&gt;#{&lt;/span&gt;workbook.getSheetAt(&lt;span class="ST4"&gt;0&lt;/span&gt;).getRow(&lt;span class="ST4"&gt;0&lt;/span&gt;).getCell(&lt;span class="ST4"&gt;0&lt;/span&gt;).getStringCellValue&lt;span class="ST1"&gt;}&lt;/span&gt;&lt;span class="ST1"&gt;"&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="ST3"&gt;end&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;There's some nice stuff going on.  I really like being able to just include a jar and start using it.  Still, using the POI API in Ruby looks rather icky -- (actually, it started even worse than this, but Charles Nutter was on #jruby and was kind enough to tell me about IOInputStream).  After looking at this code for a minute I started thinking and it came to me: "Hey this is Ruby.  We can do anything we want!"&lt;br /&gt;&lt;br /&gt;I started with that ugly getStringCellValue at the end. It would be nice if we could give cell a to_s and do away with that.  Well, guess what, since this is Ruby, I can just open HSSFCell and do it:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&lt;br /&gt;require &lt;span class="ST0"&gt;'&lt;/span&gt;&lt;span class="ST0"&gt;java&lt;/span&gt;&lt;span class="ST0"&gt;'&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;require &lt;span class="ST0"&gt;'&lt;/span&gt;&lt;span class="ST0"&gt;/home/ccnelson/java/poi/poi-2.5.1-final-20040804.jar&lt;/span&gt;&lt;span class="ST0"&gt;'&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;include_class &lt;span class="ST0"&gt;'&lt;/span&gt;&lt;span class="ST0"&gt;org.apache.poi.poifs.filesystem.POIFSFileSystem&lt;/span&gt;&lt;span class="ST0"&gt;'&lt;/span&gt;&lt;br /&gt;include_class &lt;span class="ST0"&gt;'&lt;/span&gt;&lt;span class="ST0"&gt;org.apache.poi.hssf.usermodel.HSSFWorkbook&lt;/span&gt;&lt;span class="ST0"&gt;'&lt;/span&gt;&lt;br /&gt;include_class &lt;span class="ST0"&gt;'&lt;/span&gt;&lt;span class="ST0"&gt;org.jruby.util.IOInputStream&lt;/span&gt;&lt;span class="ST0"&gt;'&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;include_class &lt;span class="ST0"&gt;'&lt;/span&gt;&lt;span class="ST0"&gt;org.apache.poi.hssf.usermodel.HSSFCell&lt;/span&gt;&lt;span class="ST0"&gt;'&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="ST1"&gt;class&lt;/span&gt; &lt;span class="ST2"&gt;HSSFCell&lt;/span&gt;&lt;br /&gt;&lt;span class="ST1"&gt;def&lt;/span&gt; to_s&lt;br /&gt;getStringCellValue&lt;br /&gt;&lt;span class="ST1"&gt;end&lt;/span&gt;&lt;br /&gt;&lt;span class="ST1"&gt;end&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="ST2"&gt;File&lt;/span&gt;.open(&lt;span class="ST0"&gt;"&lt;/span&gt;&lt;span class="ST0"&gt;/home/ccnelson/documents/Invoice15.xls&lt;/span&gt;&lt;span class="ST0"&gt;"&lt;/span&gt;) &lt;span class="ST1"&gt;do&lt;/span&gt; |f|&lt;br /&gt;workbook = &lt;span class="ST2"&gt;HSSFWorkbook&lt;/span&gt;.new(&lt;span class="ST2"&gt;IOInputStream&lt;/span&gt;.new(f))&lt;br /&gt;puts &lt;span class="ST0"&gt;"&lt;/span&gt;&lt;span class="ST0"&gt;cell 0,0: &lt;/span&gt;&lt;span class="ST0"&gt;#{&lt;/span&gt;workbook.getSheetAt(&lt;span class="ST3"&gt;0&lt;/span&gt;).getRow(&lt;span class="ST3"&gt;0&lt;/span&gt;).getCell(&lt;span class="ST3"&gt;0&lt;/span&gt;)&lt;span class="ST0"&gt;}&lt;/span&gt;&lt;span class="ST0"&gt;"&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="ST1"&gt;end&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Cool!  Even though HSSFCell is a java class, because I am using it from JRuby I can open it up and stick methods on it.  This got me excited.  What do I really want this API to look like?  I think I'd really rather be able to access my spreadsheet cells using a simple 2 dimenional array.  I mean, that's really what they are for my purposes.  And guess what?  In Ruby, the [] operator, like everything else in Ruby, is just a method.  And if it's just a method, well I can abuse... err.. bend it to my own nefarious purposes.  Bwah ha ha hah ha hah ha ha..&lt;br /&gt;&lt;br /&gt;Oops, got a little carried away there.  Ruby coding will do that sometimes.  Back to the task at hand:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&lt;br /&gt;require &lt;span class="ST0"&gt;'&lt;/span&gt;&lt;span class="ST0"&gt;java&lt;/span&gt;&lt;span class="ST0"&gt;'&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;require &lt;span class="ST0"&gt;'&lt;/span&gt;&lt;span class="ST0"&gt;/home/ccnelson/java/poi/poi-2.5.1-final-20040804.jar&lt;/span&gt;&lt;span class="ST0"&gt;'&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;include_class &lt;span class="ST0"&gt;'&lt;/span&gt;&lt;span class="ST0"&gt;org.apache.poi.poifs.filesystem.POIFSFileSystem&lt;/span&gt;&lt;span class="ST0"&gt;'&lt;/span&gt;&lt;br /&gt;include_class &lt;span class="ST0"&gt;'&lt;/span&gt;&lt;span class="ST0"&gt;org.apache.poi.hssf.usermodel.HSSFWorkbook&lt;/span&gt;&lt;span class="ST0"&gt;'&lt;/span&gt;&lt;br /&gt;include_class &lt;span class="ST0"&gt;'&lt;/span&gt;&lt;span class="ST0"&gt;org.jruby.util.IOInputStream&lt;/span&gt;&lt;span class="ST0"&gt;'&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;include_class &lt;span class="ST0"&gt;'&lt;/span&gt;&lt;span class="ST0"&gt;org.apache.poi.hssf.usermodel.HSSFCell&lt;/span&gt;&lt;span class="ST0"&gt;'&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;include_class &lt;span class="ST0"&gt;'&lt;/span&gt;&lt;span class="ST0"&gt;org.apache.poi.hssf.usermodel.HSSFRow&lt;/span&gt;&lt;span class="ST0"&gt;'&lt;/span&gt;&lt;br /&gt;include_class &lt;span class="ST0"&gt;'&lt;/span&gt;&lt;span class="ST0"&gt;org.apache.poi.hssf.usermodel.HSSFSheet&lt;/span&gt;&lt;span class="ST0"&gt;'&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="ST1"&gt;class&lt;/span&gt; &lt;span class="ST2"&gt;HSSFCell&lt;/span&gt;&lt;br /&gt;&lt;span class="ST1"&gt;def&lt;/span&gt; to_s&lt;br /&gt;getStringCellValue&lt;br /&gt;&lt;span class="ST1"&gt;end&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="ST1"&gt;end&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="ST1"&gt;class&lt;/span&gt; &lt;span class="ST2"&gt;HSSFSheet&lt;/span&gt;&lt;br /&gt;&lt;span class="ST1"&gt;def&lt;/span&gt; [] (index)&lt;br /&gt;getRow index&lt;br /&gt;&lt;span class="ST1"&gt;end&lt;/span&gt;&lt;br /&gt;&lt;span class="ST1"&gt;end&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="ST1"&gt;class&lt;/span&gt; &lt;span class="ST2"&gt;HSSFRow&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="ST1"&gt;def&lt;/span&gt; [] (index)&lt;br /&gt;getCell index&lt;br /&gt;&lt;span class="ST1"&gt;end&lt;/span&gt;&lt;br /&gt;&lt;span class="ST1"&gt;end&lt;/span&gt;&lt;br /&gt;&lt;span class="ST2"&gt;File&lt;/span&gt;.open(&lt;span class="ST0"&gt;"&lt;/span&gt;&lt;span class="ST0"&gt;/home/ccnelson/documents/Invoice15.xls&lt;/span&gt;&lt;span class="ST0"&gt;"&lt;/span&gt;) &lt;span class="ST1"&gt;do&lt;/span&gt; |f|&lt;br /&gt;workbook = &lt;span class="ST2"&gt;HSSFWorkbook&lt;/span&gt;.new(&lt;span class="ST2"&gt;IOInputStream&lt;/span&gt;.new(f))&lt;br /&gt;spreadsheet = workbook.getSheetAt(&lt;span class="ST3"&gt;0&lt;/span&gt;)&lt;br /&gt;puts &lt;span class="ST0"&gt;"&lt;/span&gt;&lt;span class="ST0"&gt;cell 0,0: &lt;/span&gt;&lt;span class="ST0"&gt;#{&lt;/span&gt;spreadsheet[&lt;span class="ST3"&gt;0&lt;/span&gt;][&lt;span class="ST3"&gt;0&lt;/span&gt;]&lt;span class="ST0"&gt;}&lt;/span&gt;&lt;span class="ST0"&gt;"&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="ST1"&gt;end&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Nice!  This for me is one of the killer features of JRuby.  A lot of scripting languages will let you access the Java APIs in a more light weight language.  But because of the features of the Ruby language, it becomes so easy to modify APIs to suit your needs, desires, and insane urges.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/719065923860450374-7432766248654814503?l=mysterycoder.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mysterycoder.blogspot.com/feeds/7432766248654814503/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=719065923860450374&amp;postID=7432766248654814503' title='6 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/719065923860450374/posts/default/7432766248654814503'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/719065923860450374/posts/default/7432766248654814503'/><link rel='alternate' type='text/html' href='http://mysterycoder.blogspot.com/2007/04/api-unickifying-with-jruby.html' title='API unickifying with JRuby'/><author><name>MysteryCoder</name><uri>http://www.blogger.com/profile/12085440439301444384</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_cYfx1Pq0Irc/TOXJ5wxxOVI/AAAAAAAAABQ/bDRzQsFRG6E/S220/Photo%2B15.jpg'/></author><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-719065923860450374.post-8011405390296216873</id><published>2007-04-22T10:18:00.001-07:00</published><updated>2008-04-28T21:27:42.922-07:00</updated><title type='text'>Welcome to my new blog</title><content type='html'>I was getting kind of tired of JRoller, so I decided to move.  Welcome to my new digs!&lt;br /&gt;&lt;pre name="code" class="ruby"&gt;&lt;br /&gt;&lt;br /&gt;class InventoryController&lt;br /&gt;end&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/719065923860450374-8011405390296216873?l=mysterycoder.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mysterycoder.blogspot.com/feeds/8011405390296216873/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=719065923860450374&amp;postID=8011405390296216873' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/719065923860450374/posts/default/8011405390296216873'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/719065923860450374/posts/default/8011405390296216873'/><link rel='alternate' type='text/html' href='http://mysterycoder.blogspot.com/2007/04/welcome-to-my-new-blog.html' title='Welcome to my new blog'/><author><name>MysteryCoder</name><uri>http://www.blogger.com/profile/12085440439301444384</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_cYfx1Pq0Irc/TOXJ5wxxOVI/AAAAAAAAABQ/bDRzQsFRG6E/S220/Photo%2B15.jpg'/></author><thr:total>2</thr:total></entry></feed>
