Err Free – Ruby on Rails Podcast

A conversation with Chris Wanstrath and PJ Hyett of Err Free consulting in San Francisco. We talk about starting a profitable side project, sending and receiving email, git source code control, using JQuery, and code interfaces to databases.
Also mentioned:

Err Free – Ruby on Rails Podcast

A conversation with Chris Wanstrath and PJ Hyett of Err Free consulting in San Francisco. We talk about starting a profitable side project, sending and receiving email, git source code control, using JQuery, and code interfaces to databases.
Also mentioned:

Adapting Ambitiously

It’s funny, really. All these people walking around, talking about Ambition. “Oh, Ambition? Yeah, pretty cool.” “Ambition? Impedance mismatch.” “I’m happy with SQL-92 the way it is, thank you very much.” Outrageous!

I know, I know. We’ve said some crazy things ourselves. Like how we wanted Ambition to be a Rack for databases. Or, far fetched as it sounds, how we hoped Ambition could evolve into something akin to LINQ. But we’re done talking.

Today we want to show you some plain jane Ruby and how Ambition empowers it to leverage its inherent synergy. Er, I mean, we want to show you something kickass.

New School

This is what we’re used to:

>> SQL::User.select { |m| m.name == 'jon' && m.age == 21 }.to_s
=> "SELECT * FROM users WHERE users.name = 'jon' AND users.age = 21" 

This is what’s new:

>> LDAP::User.select { |m| m.name == 'jon' && m.age == 21 }.to_s
=> "(&(name=jon)(age=21))" 

Adapter School

As of 0.5, Ambition is no longer a SQL wrapper. Rather, it is an API for writing your own adapters. If you’d like to continue using the ActiveRecord version of Ambition, please install the ambitious-activerecord gem:

$ gem install ambitious-activerecord

Then, of course, use it:

require 'rubygems'
require 'ambition/adapters/active_record'

You can, too, install and use the older 0.3 series:

$ gem install ambition -v 0.3.2

Anyway, you heard right: Ambition now supports arbitrary data stores. Anything. Ambition adapters are just gems which depend on ambition and use its amazing API powers for the greater good.

What other adapters are underway? Oh, I dunno. How about ActiveLDAP, CouchDB, Facebook FQL, XPath, and DataMapper, to name a few. Why, just the other night the Boston.rb guys started working on a Sphinx adapter. Check it out with git:

$ git clone git://technicalpickles.com/ambitious_sphinx.git

We’ve also got two example gems: ambitious-activeldap and ambitious-activerecord.

There’s basic documentation for Ambition’s API over at ambition.rubyforge.org, which you are free to peruse as well.

We’re just starting out, but it’s not a bad start. Got an idea? Something crazy? We’re all about it. Jump on the mailing list or join #ambition on irc.freenode.net then chime in.

Dream School

Let’s take the youtube-g gem, as an example. There’s no finished adapter for it yet so we’re going to pretend.

Using the new Ambition, we could (behind the scenes) turn a query like this:

Videos.select { |video| video.user == 'liz' }

Into this:

YouTubeG::Client.new.videos_by(:user => 'liz')

We could turn a query like this:

Videos.select { |video| video.tags.include? 'apple' }

Into this:

YouTubeG::Client.new.videos_by(:tags => 'apple')

And we could even turn a query like this:

Videos.select do |video| 
  video.tags.include?('football') && !video.tags.include?('soccer')
end

Into this:

YouTubeG::Client.new.videos_by :tags => { 
    :include => ['football'], 
    :exclude => ['soccer'] 
  }

Not bad. It even comes with a generator, courtesy of Dr Nic, for spitting out an adapter scaffold:

$ ambition_adapter ambitious_youtube

Future School

Got an idea for an adapter, or some code to show? Throw it in the comments. You better believe we’ll keep the rest of you abreast of cool adapters, fancy tricks, and new features.

Want to get involved? Like I said, there’s always the list and the GitHub repo. Bugs can go to Lighthouse and you can clone my repo thisaways:

$ git clone git://github.com/defunkt/ambition.git

Ah, how far we’ve come. And how far we’ll go! Here’s to it.

RailsConf registration opens today. Be ready!

May 29-June 1, 2008 in Portland, Oregon,

UPDATE: registration is now open.

UPDATE2: I’ll be presenting with Tony a 3 hour tutorial on Powering AIR Applications with Rails. See you all there!

JRuby on Rails Rewrite of mediacast.sun.com Launched

A few days ago, we finally released Mediacast 2.0 – a complete rewrite of the old Mediacast application.

The original application was based on a few servlets, filters, and a lot of JSPs. It was all put together in hurry a few of years ago, when one of those fire-drill requests came to provide Sun employees with a site where they could publish files. The old code was hard to maintain and extend, and that’s why we decided to EOL the old code base and write something better from scratch.

I’m a fan of Rails and for the past year I’ve been amazed by the great progress of the JRuby project. This was one of the reasons why I suggested that we could try to rewrite the app in Rails and deploy it in a regular Java web container, thanks to JRuby and Goldspike. It took some time for Rama to give us a go-ahead, but finally in late September, two other colleagues (with no Rails or JRuby experience) and I started to work on the rewrite alongside our other projects (forums.sun.com and wikis.sun.com).

Many people asked us why JRuby on Rails was picked for this project. Here is an incomplete list of reasons:

  • we were starting from scratch, so we were not tied to any legacy code, and could pick any web framework that runs on Java
  • proof of concept project to evaluate the technology for other uses across our organization
  • verify that Rails really delivers the rapid development promise
  • something new/fun for the team to help balance out the not-so-fun stuff 🙂

Here is my experience:

Rails and JRuby Learning Curve

I worked on my first Rails project in the summer of 2006 and since then I worked on a few other (internal) Rails projects. But having to teach others and deploy an application externally using JRuby was a new experience for me.

As far as teaching goes, I can’t critique myself, but what I can say is that I had a lot of good help thanks to some Rails, Ruby and JRuby books, and many websites and blogs that have sprung up on the Internet in the last couple of years.

Learning JRuby (with previous Ruby and Java experience) is easy, because most of the time “it just works” and very rarely is the developer aware that the C-based MRI Ruby interpreter is not being used. The ability to access and seamlessly integrate with existing or new Java code is a huge plus without which we would not have been able to launch this project successfully (more on this later).

The deployment part was a different story. The Ruby on Rails application can be deployed in many different ways and JRuby offers a new alternative approach to all of them. Instead of e.g. having Apache webserver reverse-proxy requests to an army of Mongrels, JRuby and Goldspike make it possible to deploy Rails applications in a JavaEE web container. IMO this is much cleaner than anything else that is available in the non-JRuby Rails world. The downside is that this deployment method is quite new and there isn’t a lot of documentation and community knowledge about it.

Application Architecture

Our app is a simple database-driven Rails application consisting of a handful of models, 4 controllers, and a bunch of view templates. The only piece of data that is not stored in the database are the actual files, which are stored on the file system.

To be on the safe side when it comes to performance, we employed quite a lot of fragment caching, which sped up our application quite a bit.

Development Environment

Our development environment is based on a self-contained1 JRuby (1.0.3) on Rails (1.2.6) application stored in a Mercurial repository. The IDE we use is NetBeans 6 with Ruby support and Mercurial plugin. The DB of our choice is MySQL and servers we use during development are WEBrick and Glassfish v2ur1.

NetBeans makes it super easy to write the Ruby code and offers a lot of neat features for Rails application development. I have to say that Tor and the gang did a great job. In fact I switched from Eclipse to NetBeans thanks to its great Ruby support.

Because the application runs in the JVM we can use JConsole to monitor the app while load testing which comes in really handy!

So all is good here, except for one thing. I got used to using the amazing ruby-debug debugger for debugging my Ruby on Rails applications. This debugger is not yet available for JRuby on Rails application (unless you hack your way through). I read somewhere that jruby-debug should be available with NetBeans 6.1. Once that is done, the JRoR dev environment will be on par with RoR (in fact thanks to tools like JConsole it will be superior).

Production Environment

We use a pair of load-balanced T2000 with Solaris 10, JDK6 and SJSAS 9.1u1. These two servers share a nfs NAS drive used for file storage and fragment cache storage. The DB backend is a MySQL database server, which we access through a connection pool set up in the app server.

All of this was fairly easy to set up. As you can see there were no special requirements when comparing this environment to a usual JavaEE production environment.

The Good

Once my colleagues grasped some RoR basics, we got the core of the application up and running fairly fast. Sometimes it still amazes even me how much one can do with Rails in a short amount of time. Thanks to a small amount of code one needs to write, the code review process is fast as well, and fixing a bug often means changing only a few lines of code.

The Bad

Since most of the C-based gems are not compatible out-of-box with JRuby (at the moment), the jruby-extras project aims to deliver JRuby compatible versions of these libraries. One of these libraries – JRuby-OpenSSL – was needed for me to integrate our app with our authentication webservice. I soon found out that JRuby-OpenSSL was not completely implemented yet and parts of functionality that I needed were missing. I’m sure that it is just a matter of time when problems like this will go away (if it hasn’t happened already) as these libraries will mature.

The Ugly

The Goldspike project provides a bridge between the JavaEE and RoR world. It does this by dispatching the incoming HTTP requests into Rails running in a JRuby runtime.

This works great for all requests that take little time to process, but if you have long-running requests like large file uploads or downloads, these requests will occupy your JRuby runtimes and you soon realize that you are running out of runtimes in your small pool, at which point your application becomes unresponsive for any new requests.

This was the biggest problem we hit, but thanks to the possibility to seamlessly integrate Java code into our JRoR app and a great idea that my colleague Peter had, we solved this issue quite elegantly.

JRuby and Java Come to the Rescue

The two main issues we faced and that consumed most of my time on this project were related to the immaturity of the libraries around JRuby and application characteristics specific to JRoR deployment. Both of these issues can be resolved thanks to years of long Java and JavaEE history, and their libraries.

The problem with reliable connection to our SOAP-over-HTTPS based authentication webservice was resolved by generating a client Java webservice stub and using that instead of SOAP4R which didn’t work properly because of the problems with JRuby-OpenSSL.

The second problem with the long-running processes occupying our precious JRuby runtimes, we solved by using a servlet filter and a fake HttpServletResponse (that we sent to Goldspike instead of the original one) and streaming the data from the filter instead from the runtime. I’ll write a separate blog entry on this.

Overall Impression

This project was/is fun to work on. We experimented with quite a few new (for us) technologies and learned a lot along the way. To be honest, I expected to deploy the app much sooner but at that time I was not aware of the two above mentioned issues which consumed a lot of my time.

I was a bit worried about the performance of the application, but that turned out to be a non issue once we had the download servlet filter in place, and with the performance improvements in JRuby 1.1 things will be even better in the future.

Overall I’m happy with the outcome of our project and I look forward to adding more functionality to the application.

Our Future Plans

From the infrastructure perspective:

  • upgrade to JRuby 1.1 and Rails 2.0
  • start using Warbler, which looks to be superior to Goldspike’s Rails plugin, for building the war file
  • experiment with in-memory session state replication in Glassfish

From the feature perspective:

  • better categorization of media items
  • search functionality via integration with search.sun.com
  • previews of media items
  • new UI design
  • and the toughest one – audio and video streaming

JRuby/Goldspike/Glassfish Things I Would Like to See Improved

  • I’m not sure if it is us and our (mis)configuration, Goldspike, JRuby or Glassfish, but right now we need quite a big JVM heap to keep things running. With 8 JRuby instances in the pool and Http thread count set to 512, we need -Xmx set to 2-2.5GB. This is a bit too much I think. We’ll have to look into this and find the culprit.
  • The application startup is quite slow, especially on a machine like T2000, which doesn’t perform well for heavy-weighted single-threaded operations. I don’t see a reason, why Goldspike couldn’t initialize the JRuby runtime pool concurrently cutting down the startup time significantly.
  • Offload JRuby runtimes as much as possible. Currently operations like file upload or file download (via Rails’ send_file) are handled by JRuby runtimes. I think that it should be possible to take care of these operations outside of the runtime, allowing the runtime to process other rails requests in the meantime.

1 – Rails and all the other gems and jars are frozen into the project

#90 Fragment Caching

Sometimes you only want to cache a section of a page instead of the entire page. Fragment caching is the answer as shown in this episode.

I Always Knew IE Was Shifty

While working on a Rails project, I stumbled upon a (probably) obscure positioning bug in IE, triggered by the ubiquitous “Yellow Fade Technique”, of all things. The symptom, as reported by the user, was that form elements on a page were “jumping around” when items were added to the cart. I’ve distilled the issue down to what I believe is the smallest reproduction of the issue, which I present to you now, in glorious validated HTML 4.01 strict:

<!DOCTYPE html PUBLIC “-//W3C//DTD HTML 4.01//EN”>


IE Shifting Bug


some hidden content





If you view this page in IE (I’m using version 7), when you apply the background color to the container div, the two form elements jump to the left, overlapping the label element. Interestingly enough, this seems to require the convergence of many things, including the floated outer div, the hidden content above, the relative position on all the divs, etc. If you remove any of them from the equation, things work as expected. In an even more bizarre twist, the length of the label seems to come into play as well — if you add even one more character to the label text, things return to “normal”.

In the extremely unlikely event that anyone else has run across this issue, hopefully I can save you a couple of hours of frustration. I worked around the issue by overriding the position of the “container” div (to “static”), although given the fragility of the trigger, any number of small changes should work as well.

#90 Fragment Caching

Sometimes you only want to cache a section of a page instead of the entire page. Fragment caching is the answer as shown in this episode.

Feeds for Free

And money for nothing. Or something like that? Sorry, Mark Knopfler. I’ll pay more attention next time.

Anyways, let us be painfully aware that we can get Atom feeds for free. Not as in beer or speech, but as in ‘zero lines of code.’ How? Microformats.

You and meFormats

Almost a year has past since we last spoke of microformats, and way more than a year since our first encounter. Seems like only yesterday.

Remember hAtom? It’s like Atom, only embedded into your existing content’s HTML pages. The mofo site references the following example:

A normal, typical blog post:

<div class="post">
  <h3>Megadeth Show Last Night</h3>
  <span class="subtitle">Posted by Chris on June 4th</span>
  <div class="content">
    Went to a show last night. Megadeth. 
    It was alright.
  </div>
</div>

The same post with hAtom superpowers:

<div class="post hentry">
  <h3 class="entry-title">Megadeth Show Last Night</h3>
  <span class="subtitle">Posted by 
    <span class="author vcard fn">Chris</span> 
    on 
    <abbr class="updated" title="2006-06-04T10:32:10Z">June 4th</abbr>
  </span>
  <div class="content entry-content">
    Went to a show last night. Megadeth. It was alright.
  </div>
</div>

To you and I, eagerly searching for a review of last summer’s Megadeth show, there is no difference between the two. Our browsers render them the same. To a machine, however, the second post is chock full of semantic goodness.

This semantic goodness represents, in our HTML, the same information an Atom feed would provide. This leaves us with two paths of action for gettin’ our feed on: we can wait for feed readers to start speaking hAtom fluently, or we can have someone translate hAtom to Atom for us.

Subtlely Free Feeds

One year ago today Subtlety was released. Today it is re-released with a new feature: it can convert a page containing hAtom entries into an Atom feed. This means your feeds are now officially free.

We’ve actually been doing this for a while right here on Err. Our Feedburner feed points to this url: http://subtlety.errtheblog.com/O_o/29f.xml. It’s an Atom feed generated by Subtlety after parsing the hAtom elements on this site. On Err the Blog.

My ozmm blog is a static blog with no special RSS code. Instead, I point the Feedburner URL at a Subtlety Atom feed which is generated from the hAtom in the posts. Our Dynamite blog uses the same trick. See the pattern?

There’s no reason to ever write your own Atom feeds anymore. Sorry.

But what if I don’t want you hosting my feeds?

That’s fine, and acceptable. How about I just hand you the technology to do this on your own?

It goes like this:

$ gem install mofo
$ cd rails_app/vendor/plugins
$ gem unpack mofo

Then, here’s your controller:

class PostsController < ApplicationController
  def index
    @posts = Post.find(:all)
  end

  def atom
    target = url_for(:action => :index)
    render :xml => hEntry.find(target).to_atom(:title => 'whatever')
  end
end

You can use this trick for dynamically generated feeds (changelogs or activity feeds, perhaps) or whatever else. Thanks, mofo.

Last Step: Cut the Code

Now go through your app and remove all the Atom code. Drop those extra plugins, remove those xml templates, cut out all the special logic, and enjoy simple Subtlety or profound mofo.

Have fun.

Ezra Zygmuntowicz – Ruby on Rails Podcast

The co-founder of Engine Yard and author of the upcoming book on Rails Deployment talks about Engine Yard’s recent $3.5 million funding for open source Ruby projects such as Rubinius.
From San Francisco.

Ezra Zygmuntowicz – Ruby on Rails Podcast

The co-founder of Engine Yard and author of the upcoming book on Rails Deployment talks about Engine Yard’s recent $3.5 million funding for open source Ruby projects such as Rubinius.
From San Francisco.

On the Move (Away from Blogger)

Today was a big day for my blog. I started a “big” move that was hanging over my mind for a few months.

I got my own domain igorminar.com and changed the blogger.com settings so that the domain name blog.igorminar.com is being used instead of net3x.blogspot.com.

Except for a small hick-up with DNS cache and a weird 404 Server not Found error (described in this blog post) everything went smoothly. My plan is to keep on using Blogger’s custom domain feature for a few weeks and then migrate all the content over to my own blogging engine. I’ll most likely end up using Mephisto, JRuby, Glassfish and MySQL, but things can still change.

The reason why I’m moving in two phases is to keep all the referring links that point to the old urls as well as most of the search engine ranking. The Blogger’s custom domain feature now redirects everything to the new urls via 301 Permanent Redirect, so hopefully the transition will be close to painless. I’m not SEO expert, but this for sure is an interesting experiment.

And for those SEO “experts” that were claiming that getting Blogger to do proper redirects after a blog move was impossible here is a little proof:


$ wget --spider net3x.blogspot.com
--16:34:30-- http://net3x.blogspot.com/
=> `index.html.2'
Resolving net3x.blogspot.com... 72.14.207.191
Connecting to net3x.blogspot.com|72.14.207.191|:80... connected.
HTTP request sent, awaiting response... 301 Moved Permanently
Location: http://blog.igorminar.com/ [following]
--16:34:30-- http://blog.igorminar.com/
=> `index.html.2'
Resolving blog.igorminar.com... 66.249.81.121
Connecting to blog.igorminar.com|66.249.81.121|:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 0 [text/html]
200 OK

My Custom Prompt for Leopard’s Terminal

As I mentioned in my previous post, even though it is not perfect, I settled on using Terminal as my terminal application.

The default prompt that comes with MacOS is not very useful, so I configured my own by adding this line to my .bashrc file:

export PS1="\[\033]0;\u@\h:\w\007\]\u@\h:\W\\$ "

This results in a prompt that looks like this:

This prompt displays the prompt as username@hostname:currentdir$ and in addition to that it sets the window title to username@hostname:pwd.

Leopard’s Terminal Tabs

As I shared yesterday, I love tabs. One of the few good things that MacOS 10.5 Leopard brought, was enhanced Terminal application. A basic feature – Tab support – that was missing in Terminal for way too long, was finally added, and Terminal app became finally usable for anyone who spends a great time of the day working on the command line.

Before Leopard, I used iTerm, but there was just something about it that I didn’t like, but the availability of tabs made me get over it. Now with Leopard there is no need for iTerm any more.

Just to point out that Apple seems to be unable to get anything 100% right these days, there are two flaws in the Terminal’s tab implementation.

The first flaw is that you can’t easily switch between tabs using keyboard shortcut. All you can do is to use cmd+{ and cmd+} to switch to previous or next tab respectively. What a “wonderful” choice of keys that require use of right hand or both hands. Most importantly, one can’t use the handy cmd+1, cmd+2, …, cmd+9 shortcuts (or anything similar) to switch to one of the first nine tabs. Maybe Apple doesn’t want to overload us with new features and is planning to add this to Terminal in MacOS 10.6. 🙂 Fortunately, the cmd+{ and cmd+} shortcuts can be remapped via System Preferences.

The second flaw is that Terminal doesn’t let you name the tabs or configure how the tabs should be named. This is a useful feature that many other terminal applications have, but Apple decided that using the name of the program of the currently running process is good enough. Well, this is what it looks like:

People are doing all kinds of crazy things to work around this issue. Including using hardlinks to change names of programs or creating dummy processes that carry the tab name.

I would be very happy if Apple did something similar to what xterm does – using an environmental variable to set name of the tab dynamically. But I have a feeling that we’ll see MacOSX Trash go 3D sooner than properly working Terminal tabs. 🙁

Mac Applications That I Use

I’ve been meaning to write this entry on applications installed on my computer for a few months now, but never found time to do it. Hopefully none of those new Mac users that I told to check out my blog “in a few days”, several months ago, got angry at me. If nothing else, my promise helped me to get more regular readers :).

Anyway, here is the list of apps installed on my Mac (all these apps work with Leopard, unless I noted otherwise):

Essentials

A Mac without these apps would never be the same:

  • Quicksilver – an app that helps you find things on your computer and execute actions on these things. I use it to launch apps, pause iTunes, find contacts in the AddressBook, and many many many other things. Most of the cool functionality is added via plugins, so don’t forget to checkout the plugin section of preferences. This app is a must have. Here are Some docs and a good video.
  • Adium – a really handy IM client that can handle all the popular IM protocols. Definitely a must have. (it’s much better than iChat when it comes to IM-ing).
  • Growl – Growl is a notification system for Mac OS X: it allows applications that support Growl to send you notifications. Notifications include Adium or Skype messages, network up/down events, volume mount/unmount events, currently played iTunes song and many others. More info – One extension that I found to be incompatible with Leopard is GrowlMail for Mail.app notifications, when I received many new messages at once this extension would cause the Mail.app to crash.
  • MacPorts – This is a geeky one: The MacPorts Project is an open-source community initiative to design an easy-to-use system for compiling, installing, and upgrading either command-line, X11 or Aqua based open-source software on the Mac OS X operating system.
  • Firefox – no description needed 🙂

Nice to Have

  • iStat menus – a nifty app that displays stats about cpu load, cpu temperature, memory and network utilization, and a lot of other interesting data about your Mac. I use it as a replacement of MenuMeters which I couldn’t get to run reliably on Leopard.
  • Perian – Perian is a free, open source QuickTime component that adds native support for many popular video formats.
  • Camino – yeah, as if the fact that I’m obsessed with tabs was not enough, I usually run 2 or 3 browsers at the same time to be able to take advantage of their unique features, or more often, while developing webapps, I need to be able to have more than one session open.
  • Chicken of the VNC – A handy VNC client
  • MacFUSE + sshfs – MacOS X implementation of FUSE, which makes it possible to painlessly mount all kinds of different filesystems e.g. sshfs.
  • MacFusion – GUI frontend for MacFUSE
  • VLC – alternative to QuickTime video player with build-in support for all kinds of video and audio codes, subtitle support and many other features
  • Vine Server (OSXvnc) – a good VNC server in case you need a bit more control than the Leopard’s built-in server offers
  • Skype – I have a love-hate relationship with Skype. As soon as I find an alternative crossplatform communication tool with audio and video support and cheap calls to Slovakia, I’ll switch. Maybe Gizmo will become that tool one day
  • NeoOffice – don’t forget to install the latest Patch. I have big hopes for OpenOffice Aqua to be released soon. My initial experiments revealed some very good performance results.
  • iShowU – a cool app for creating screencasts. This is the only paid-for app on my list. But it’s well worth it.
  • Caffeine – Caffeine is a tiny program that prevents your Mac from automatically going to sleep, dimming the screen or starting screen savers. Very useful during video calls, while reading PDFs or watching movies.
  • Twitterrific – a Twitter client
  • Azureus – Java BitTorrent client
  • SkeyCalc – An OTP (S/Key) calculator
  • Cisco VPN Client

Development

  • NetBeans – there is a lot of controversy in the community when it comes to the Eclipse vs NetBeans question. I used Eclipse for a really long time, but ever since I tried NB6 Milestone 8 or so, I started liking NB more than Eclipse. I’ll give Eclipse another shot in a few weeks, but for now NetBeans is my default IDE. And as far as Ruby/JRuby development is concerned, I don’t think that this is going to change for a long time.
  • JRuby – a pure Java-based Ruby interpreter
  • GlassFish – JavaEE 5.0 compliant application server

Other Stuff

Other Lists

Rama and Martin composed similar lists some time ago, so you might want to check those out as well.

I’m Obsessed with Tabs

This is a screenshot I took during a regular development/research day:

What is your average number of browser tabs opened at once?

#89 Page Caching

Page caching is an efficient way to cache stateless content. In this episode I will show you how to cache the dynamic javascript we created last week.

#89 Page Caching

Page caching is an efficient way to cache stateless content. In this episode I will show you how to cache the dynamic javascript we created last week.

MultiSudokuSolver – A fun project I worked on during the Xmas break

While I was visiting my family in Slovakia during the winter 2005/2006 I found a sudoku magazine in my dad’s apartment. I like this kind of stuff, so I mediately started solving one puzzle after another, until I got to a “Speciality MultiSudoku” puzzle:

This puzzle is composed of five regular 9×9 puzzles that are interconnected and you can’t solve either of them alone, meaning that you need to be solving all five of them at the same time and use intermediate results from one puzzle to get an intermediate result for another puzzle that this puzzle is connected with. It sounded like a good challenge so I started working on it. After two or three nights I realized that I made a mistake!! Ughhh. I erased everything I had solved and started from scratch. After another few nights I found another problem, got turned off by this puzzle and put it away.

I came across the puzzle once again when my wife and I returned to Slovakia this winter. I found the puzzle in the apartment and, being a person who likes challenges and doesn’t get turned off my failures for too long, I decided to erase everything and this time be very careful and solve the puzzle once and for all.

After about two evenings I found something I didn’t want to see. An error!!! It was hard to believe it, but there it was. I tried to fix it, but if you don’t spot an error in a sudoku puzzle early enough, you’ll spend more time fixing it than if you started from scratch.

Do you think I felt like starting from scratch? No! But I couldn’t let this be. So since I had 10 or so days off during the Christmas break (thanks Sun!!!), I decided to use my brain in a more productive way and to write a small program that would solve the puzzle for me.

Given my interest in Ruby and JRuby and the type of problem I was about to solve, the language choice was an easy one to make.

A few days later I had a script that solved the puzzle for me within 1.07 seconds. Ya! You heard right! Solved not in a few evenings but in just a little more than one second.


Top Left:
718|956|324
452|387|619
936|142|587
-----------
341|528|796
695|713|842
287|694|153
-----------
523|461|978
869|275|431
174|839|265

Top Right:
635|428|971
214|679|853
897|531|426
-----------
976|382|514
152|764|389
348|915|267
-----------
463|857|192
529|146|738
781|293|645

Bottom Left:
728|154|396
194|836|752
653|279|184
-----------
519|368|427
346|725|918
872|491|563
-----------
231|987|645
467|512|839
985|643|271

Bottom Right:
215|849|637
348|627|591
976|153|824
-----------
869|431|752
154|972|368
732|568|149
-----------
521|796|483
483|215|976
697|384|215

Center:
978|215|463
431|678|529
265|439|781
-----------
813|754|692
649|382|157
527|961|834
-----------
396|847|215
752|196|348
184|523|976

Lessons learned: “automate automate automate!” and “Don’t work hard, but work smart!” 🙂

The algorithm is very simple. The model is based on the simplest unit – a cell which is part of a row, column and a square. Each puzzle consists of 9 columns, 9 rows and 9 squares. Cells are flexible enough to be part of more than one square, row or a column at a time, so I can have cells that are present in more than one puzzle at a time. With a flexible model like this, all that the program needs to do is to use some basic rules to eliminate candidates and determine cell values. This type of solver is often referred to as human-style solver, because it uses the same techniques used by humans.

If anyone is interested in having a look at the source code it can be downloaded from here: multi_sudoku_solver.rb. A word of warning – the code is not cleaned up nor documented. This was just a fun project that I worked on, and the fact that I achieved what I set out to achieve was a good enough milestone to call this project done.

After this experience I don’t feel like solving sudoku puzzles any more. They are just a repetitious problems that are well suited for automated solution. Most importantly – I actually had more fun writing the program than I had with solving the puzzle :).

#88 Dynamic Select Menus

See how to dynamically change a select menu based on another select menu using Javascript. In this episode everything is kept client side which leads to a more responsive user interface.