Thursday, May 10, 2012

Rails Rumble 2010

In my long absence from posting, I see I totally skipped 2010.
For the 2010 Rails Rumble we created Commendable Kids.

Here are the results for our entry
  • Finished 4th place out of 180 teams
  • Winners of the Appearance Category
  • Runners Up from Chargify as Most Potential to Monetize
    Read More
  • #1 team from the U.S.
  • Tech Crunch Top 5
    Read the Review

St. Francis Society Animal Rescue

One of my side-projects is the development of the St. Francis Society Animal Rescue web site.  My friend Brian Burridge and I originally converted the site from a static web site to a Ruby on Rails site several years ago (2008 timeframe).  I believe it was initially a Rails 1.2 project.  Besides the public site, it includes a fairly involved back-end administration component that beyond just allowing content management of the web site, performs all the animal rescue administration functions (detailed animal information with health records, adoption records, etc.).  At the time we were both fairly new to Ruby on Rails and we decided to use ActiveScaffold to build this administration component.

At some point we upgraded to Rails 2.1 and then in 2010, Brian left the project to be able to better focus on his other numerous projects and I further upgraded it to Rails 2.3.x.  These Rails version upgrades were more effort than a typical Rails upgrades may be due to various gem dependencies, most specifically ActiveScaffold.  ActiveScaffold is really a pretty nice framework for admin sites, but it had limitations that required work-arounds and those work-arounds often didn't work when upgrading.

During the end of 2011 to the beginning of 2012, I did a more drastic upgrade.  I migrated to Rails 3.1.x.  However, this wasn't just a simple migration, I decided to re-write the entire application.  The most involved part of this re-write is what most people will never see, the administration area.  I decided to totally abandon ActiveScaffold.  Brian told me about ActiveAdmin that he was using on some of his other projects, but after fighting with ActiveScaffold for long, I opted to stay clear of such a major framework dependency and just wrote the entire admin from scratch with straight Rails.

Comparisons of the old and new administration pages.

Here's a comparison of the listing of the cats.  I reduced the amount of information displayed on the list to reduce some clutter, and I've made some of the frequently changed values available to be changed directly on the list (save instantly via Ajax) to eliminate the need to open the edit form just to change a status.

Filtering the list required an extension to ActiveScaffold that was problematic to upgrade, and it resulted in a very large area added to the top of the list.  Now it uses a jQuery UI dialog.

ActiveScaffold constructed its forms very vertically which didn't utilize the space well.  I now have full control of the layout allowing me to organize things better.

Responsive Web Design

Last summer at the 2011 front-end design conference I had the privilege of having Ethan Marcotte introduce me to the idea of responsive web design.  So, I took that to heart and designed both the public site and the admin area to be responsive.  So, if we look at the cat listing page again and compare it between a browser and an iPhone, you can see that the navigation menu has collapsed and the table has dropped several columns.

There are also intermediate changes for tablets, but it's time I wrap this up.

I'm only touching on a very few of the page layouts and features.  Beyond a new look and feel, the re-write of the application also brought performance improvements.  Here is a New Relic report on the week I switched it over from the old to the new.

Note: Thursday was the transition day, so it should be ignored.  The jump in CPU percentage is due to also switching from a shared hosting environment on DreamHost to a Linode slice since DreamHost doesn't support Rails 3.1 at this time -- at least not on my server)

I encourage you to take a look at the St. Francis Society Animal Rescue public site, particularly if you're in the Tampa Bay area and are interested in a new pet.  Be sure to try it out in different sizes to see how the responsive layout works, and please let me know what you think of it.

Adding and removing multiple associated sub-models dynamically on a single form in Rails

The last couple blog posts have been about PeepNote ... its beginning and its ending.  Now I thought I'd share a snippet of code that I developed for it the form of a simple contact manager.

One of the things Brian pointed out in his concluding remarks about PeepNote that I referred to in my last post was,

As I began interacting more with potential customers I realized that my target audience was not what I thought it was. It wasn’t people like me who were heavily using Twitter for career networking and wanted to keep track of how I met people and what I knew about them. Instead, the only people that would pay for the service were companies. Companies that wanted to use it to track potential customers; a CRM.
Part of the CRM functionality that we had incorporated into PeepNote was to add contact information about your peeps.  The idea of a contact manager is well understood by most audiences and are thus commonly used as a demonstration application.  So, what's special about this one and why I'm I writing about it?

This particular contact manager demonstrates (and improves upon) Ryan Bates “Handle Multiple Models in One Form” recipe (#13) from the Advanced Rails Recipes book.  In Ryan’s original recipe, he added discrete field values (individual tasks on a to-do list) to the form. Any tasks that did not have an identifier associated with it was a new task, and any missing task identifiers from those currently in the database were assumed to be deleted.  This is great when you're essentially adding single values to a list, but what about adding multiple pieces of information that need to stay together as a single entity (like the parts of a contact information - street address, city, state, phone, etc)?

The solution is to use a JavaScript variable to assign temporary unique identifiers to newly added nested models (addresses, phone numbers, urls, etc). These newly added models are assigned a negative value in order for the contact controller to distinguish between new and existing records.  So, new records with a negative id are added, existing records are updated as necessary, and any records with ids that are no longer in the submitted list are removed.

This is one of the problems I solved for PeepNote and have extracted into a simple stand-alone Rails application.   Rather than provide a lengthy description here, I placed the source code on GitHub and have a running demo on Heroku.

PeepNote conclusion

I realize it's been a very long time since my last post, but I am still around.

In regards to that last post, I thought I'd share a blog entry by my RailsRumble teammate discussing the status of PeepNote:

PeepNote: The Rumble, the Startup, and now…the Conclusion