A delicious blend of Ruby and Rails…

named_scope with acts_as_tree

June 25th, 2008 benhughes

I fairly often use the acts_as_tree plugin in my applications.  While acts_as_nested_set (and superior variants..) is more powerful, often times a simple two-level deep hierarchy is all I need and acts_as_tree is simple.  I’ve found the new named_scope functionality in Rails 2.1 to be very helpful when dealing with tree data structures.

Firstly, it’s somewhat rare that I have one single root node in the tree structure (which is apparently how it’s meant to be used).  Instead I’ll have multiple “parent” nodes designated with a NULL parent_id and children beneath.  In the past I’ve always done something like: find(:all, :conditions => {:parent_id => nil}) to grab the top entries.  Instead with nested set you can do this:

named_scope :top, :conditions => {:parent_id => nil}

#Then:
Category.top

Another common task when dealing with hierarchical categories is to query on the base object (products for example) for members that are “part of” that category. Specifically, part of in a 2-level heirarchy simply means “where id = ? or parent_id = ?” on the joined categories table. Because this involves a join it was somewhat clunky to do before. Now with nested set, on the product model I can declare this:

named_scope :in_category, lambda {|c| {:include => [:category], :conditions => ["categories.id = ? OR categories.parent_id = ?", c, c]} }

# Then:
Product.in_category(3)

I would also highly encourage you all to check out RailsCasts Episode 112 “Anonymous Scopes” by Ryan Bates where he outlines a pattern for handling conditions elegantly with searches using named_scopes in Rails 2.1, something I’ve always found to be lacking from Rails core and always resorted to using plugins like criteria_query.

Configuring Passenger (mod_rails) on SliceHost with Ubuntu 7.10

April 12th, 2008 benhughes

I had an opportunity to play around with Phusion Passenger (mod_rails) which was just released yesterday. Before yesterday all that was available was an introductory video showing Passenger being configured, and I was quite impressed by it’s ease. Clearly one of the problems with Rails as a major platform right now is it’s hosting situation. Currently the best solution is to proxy HTTP requests from Apache or Nginx to a cluster of mongrels, which is tricky to set up and somewhat tedious - certainly not as as easy as a mod_php in Apache where things “just work”. Phusion set out to overcome this problem and release a module for Apache that hosts Rails applications easily. Here is what took me from a clean Ubuntu 7.10 slice from SliceHost to a working server with Passenger:Starting OutTo start out, I used the following *excellent* SliceHost articles to get some of the basic packages installed such as Ruby and MySQL:Ubuntu Setup - Part 1Ubuntu Setup - Part 2MySQL and RailsApache and PHPApache Virtual HostsVirtual Hosts & PermissionsNote my permissions gotcha below - you may not want to strictly follow their permissions advice (where the global does not have read permission).I also installed sqlite3 as this is now the default database package used in Rails 2.0:

$ sudo aptitude install sqlite3$ sudo gem install sqlite3-ruby

Installing the Passenger Apache ModuleUsing the simple instructions on the Passenger website, I ran:

$ sudo gem install passenger$ passenger-install-apache2-module

The passenger-install-apache2-module binary walks you through the installation of the Passenger. On the first run, it told me I didn’t have some software that was required:

* GNU C++ compiler... found* Ruby development headers... found* OpenSSL support for Ruby... found* RubyGems... found* Rake... found at /usr/bin/rake* Apache 2... found at /usr/sbin/apache2* Apache 2 development headers... not found* Apache Portable Runtime (APR) development headers... not found* fastthread... foundSome required software is not installed.But don't worry, this installer will tell you how to install them....* To install Apache 2 development headers:Please run apt-get install apache2-prefork-dev as root.* To install Apache Portable Runtime (APR) development headers:Please run apt-get install libapr1-dev as root.

Clearly the installer detected I was running Debian-based Linux and told me exactly what to do. No compile errors or nasty dependency issues, just simple and clear instructions. After installing the requisite software the installer compiled the Apache module and spit out this:

The Apache 2 module was successfully installed.Please edit your Apache configuration file, and add these lines:LoadModule passenger_module /usr/lib/ruby/gems/1.8/gems/passenger-1.0.1/ext/apache2/mod_passenger.soRailsSpawnServer /usr/lib/ruby/gems/1.8/gems/passenger-1.0.1/bin/passenger-spawn-serverRailsRuby /usr/bin/ruby1.8After you restart Apache, you are ready to deploy any numberof Ruby on Rails applications on Apache, without any furtherRuby on Rails-specific configuration!

Note that it didn’t find or attempt to find where apache modules are installed as the actual compiled modules is kept within the Ruby gems directory, it just told me what lines to include in my Apache configuration file. The last part of the installation says:

Deploying a Ruby on Rails application: an example.Suppose you have a Ruby on Rails application in /somewhere.Add a virtual host to your Apache configuration file,and set its DocumentRoot to /somewhere/public, like this:<VirtualHost>      ServerName www.yourhost.com      DocumentRoot /somewhere/public</VirtualHost>And that's it!

Now this is pretty cool… Passenger doesn’t even require virtual hosts to configure themselves as Rails applications. It will automatically detect a Rails application (I’m unsure of the actual criteria here) based on the DocumentRoot that you provide.So I added the necessary lines specified above to /etc/apache2/apache2.conf to load the module. Note that some deployments of Apache have their own way of managing modules; in Ubuntu there is a mods-available directory with individual configuration files for each module. You could split up the above commands to follow the convention for your system of choice, but for my purposes I just dumped the three lines into apache2.conf.Then I created a new Rails application and pointed DocumentRoot to the Rails public directory. Restart apache, and the site should then immediately work with no further configuration.Permissions Gotcha - Important!If you get:

RAILS_ROOT is not a directory.

The first time I got to this point I was running into an extremely obscure problem - Rails was reporting that RAILS_ROOT wasn’t a directory. After some debugging which involved hacking up the gem source code of both Rails and Passenger, I realized it was a permissions issue (what do you know). Passenger reports that it will run your Rails application as whatever user owns environment.rb. However, it will set the effective group to that user’s primary UNIX group, NOT the group that environment.rb is owned by. In my case, I set the group of all of the web files to www-data and no read or execute permissions whatsoever for other. I figured this would be sufficient since Apache runs as www-data. But in my case when Passenger got spawned, it got spawned running as bhughes:bhughes NOT bhughes:www-data, so it effectively couldn’t find the RAILS_ROOT directory and didn’t think it existed. You can design your permissions scheme however you want, but make sure you keep this in mind. I have an enhancement in Passenger’s ticketing system for fixing this and allowing you to manually set the effective group (you already can explicitly set the effective user through the RailsUser option).More Passenger ConfigurationThe Passenger User’s Guide is pretty good and includes some more specific configuration options you can choose, but the default appears to work fine. The Rails environment is by default set to “production” though this can be changed (sadly, only server-wide, not on a virtual-host basis - but there is an enhancement in the issue tracker for this feature).Restarting Your AppRestarting a Rails app hosted by Passenger is easy - simply touch a file called tmp/restart.txt within the Rails application root:

$ touch tmp/restart.txt

CapistranoBrian Ketelsen pointed out this Capistrano configuration which uses the touch tmp/restart.txt approach to restart and removes the .htaccess file which can cause issues:

namespace :deploy do  task :start, :roles => :app do  end  task :stop, :roles => :app do  end  task :restart, :roles => :app do    run "touch #{release_path}/tmp/restart.txt"  end  task :after_update_code, :roles => :app do    run "rm -rf #{release_path}/public/.htaccess"  endend

Diagnosing ProblemsOne of the absolutely wonderful things about Passenger is that problem diagnostics (regarding starting your Rails app) is fairly easy because Passenger includes its own nice error pages:Database Error ExampleFramework Initialization ExampleMemory ManagementOne of the issues with mongrel or thin is that they are constantly running and sucking up memory, even for sites that get very little traffic. This leads to a situation where hosting very low-traffic sites is very inefficient from a system resources perspective. This isn’t the case with PHP where memory usage spikes during traffic but is otherwise unused, allowing multiple sites to leverage the on and offs and maintain a pretty efficient hosting platform as far as memory is concerned. One of the great feature of Passenger is that you can configure it to automatically shut down your Rails application if it is idle for a certain period of time. Doing this obviously exerts a cost then on the next hit, but this may be an acceptable tradeoff for a server hosting many low-traffic sites. The configuration option is RailsPoolIdleTime and there is more information on this in the user guide.ConclusionObviously my introduction here doesn’t go in-depth into performance and ability of Passenger to scale. Time will tell as people begin using this whether it is a viable solution for Rails hosting, but for me installing this and getting it to work was dirt simple, at least compared to the mod_proxy_balancer setup with mongrel clusters I have used in the past. I’m not quite ready to actually host my sites using this but I’ll definitely be keeping my eye on this - it could be a major step forward in the proliferation of Rails hosting.

Book Review: Advanced Rails Recipes

January 6th, 2008 benhughes

I’ve owned the original “Rails Recipes” book by Chad Fowler for a while now and it’s packed full of interesting information, but little of it I would consider “advanced”. When I heard a new book by The Pragmatic Programmers called “Advanced Rails Recipes”, meant to be similar in form to the previous book but explaining more advanced techniques, I was very interested. Unfortunately it seems the publish date of this book has been pushed back a few times and it is now mid-March. Luckily it is available in beta PDF form online so last night I took the plunge and decided to buy it. It’s quick to read through and several of the recipes I skipped over because I wasn’t particularly interested, but suffice it to say that there is a lot of good stuff in this book. Some of the content isn’t very original, but some recipes really exceeded my expectations in originality and usefulness.

I won’t give an outline of the book since that’s available online, but let me point out a few very interesting recipes:

  • Using IRB_RC to define useful shortcuts for yourself when navigating around your application with script/console.
  • Efficiently storing model-backed data in constants using class-level ActiveRecord find’s. Example: load all of your states into an Array when the application starts rather than loading them each time a form is displayed that needs to use them.
  • Capistrano multi-environment deployments which allow you to do things like “cap staging deploy” and “cap production deploy”. I’ve been doing this for a while with capistrano-ext but really capistrano-ext isn’t even needed. Every developer using capistrano should be making use of this and a staging environment.
  • Keeping database.yml and other files out of Subversion using a Capistrano after filter when deploying apps.
  • Keeping certain data outside the multiple-release capistrano paradigm by symbolic linking folders within public to subdirectories in shared. This is perfect for establishing a place to upload via FTP without requiring someone to go through the SVN commit and capistrano deploy route. I’ve also used this before but the mechanism described in the book is more elegant.
  • SQL query tracing – finding out where queries are being run and what is going on behind the scenes. Could come in useful when debugging a nasty situation.
  • Using a master/slave database configuration for large applications with Rick Olsen’s masochism plugin.
  • My favorite: Handling complex forms spanning multiple models each with possible one-to-many or many-to-many relationships using the “presenter” pattern. Essentially this allows you to have a layer of design abstraction between the controller and the models whereby you can design a “presenter” which acts as as “manager” of multiple model objects meant to be displayed using the same form. Difficult to explain in full here (buy the book!) but this sounds like a very elegant solution for more data-complex applications. I may do some refactoring with Rarenewspapers.com’s back-end to use this pattern.

The book is still in beta form and there are definitely errors. Hopefully some more recipes will also be added (I’m hungry for more!) before the book is released, but ultimately the knowledge presented in Advanced Rails recipes will be very insightful for professional Rails developers.

Nested URL Parameters

December 20th, 2007 benhughes

One of the great things about Rails is the ability to wire together form logic with extreme ease through Rails’ support of essentially representing hashes through the “object[name]” syntax of URL parameters. Arrays are also supported in a similar manner, making things like many-to-many relationship management cake.

In Rails 1.2 one issue I ran into is that this hash-based access logic cannot be nested when using helpers such as url_for (which is in turned used by helpers such as link_to, etc.) This type of functionality is rather useful when you are trying to encapsulate a set of name-value pairs within one “thing”, such as a “search” which is many criteria => value pairs. For a particularly project of mine I established a pretty nice design pattern for working with searches and results in a very abstract manner, an area of Rails that I generally find underdeveloped with no standard practice.

I was lucky to stumble on a Rails plugin that monkey-patches Rails to support this: nested_params_patch. Information about this plugin is quite sparse but this article does a good job of better-explaining what the plugin does. Essentially it allows you to do things like this:

person_url(:name => {0 => 'Ryan', 1 => 'Kinderman})

Pretty cool stuff! I am always amazed and the kind of plugins and extensions that are possible, all resulting from Ruby’s dynamicism and Rails’ heavily extensible architecture.

User Alert Management with flash and ActiveRecord::Errors

December 11th, 2007 benhughes

A very common paradigm in web application development is presenting the user with some sort of alert or flash message at the top of a page. These alerts are often styled with a background and some sort of icon to the left to indicate what type of error it is. Typically there are a few different types of messages such as “error”, “warning”, “confirmation”, etc., perhaps each type styled differently. Furthermore, such a block typically should support showing a set of messages within one type; not just one string. In Rails the two sources of these messages are usually either the flash object (such as flash[:error]) or ActiveRecord validations errors.

Here is an example of what I mean:

I’ve created a helper method that makes working with these types of messages a breeze.

Essentially it allows you to use the flash object with any of the following keys to specify messages: error, confirm, back, info, and warn (though you can modify it to suit any group of message types). You can either assign a string directly to this which is common, or create it as an array with multiple string messages. The helper will then read these flash objects and display it as a message block that can be styled with CSS, supporting multiple messages per type, separated by type, as well as dynamically grabbing ActiveRecord validation errors off of model object(s) of your choosing and showing those also. The usage of the helper method in your views is as follows

# In Controller:
flash[:confirm] = "Thank you for your input."
flash[:error] = []
flash[:error] << "Wrong Address"
flash[:error] << "Wrong Name"

# In View:
<%= message_block %>

# Or if you want to display errors on @customer
# as well as the flash messages,
<%= message_block :on => :customer %>

# You can even have it watch multiple model
# objects for errors:
<%= message_block :on => [:customer, :order] %>
Here is the helper method that makes this happen:

# Outputs the error messages block.
# The first argument specifies a hash options:
# * :on => :products   Also includes AR validation errors for @products
# * :clear => true     Clears messages after displaying
# * :keep => true      Keeps around messages for next response cycle
#
def message_block(options = {})
  out = ""

  [:back, :confirm, :error, :info, :warn].each do |type|
    next if flash[type].nil? or flash[type].empty?
    flash[type] = [flash[type]] unless flash[type].is_a?(Array)

    out << "<div class=\"container #{type}\"><ul>\n"
    flash[type].each {|msg| out << "<li>#{h(msg.to_s)}</li>\n"}
    out << "</ul></div>\n"

    flash[type] = nil if options[:clear]
    flash.keep[type] if options[:keep]
  end

  if options[:on]
    options[:on] = [options[:on]] unless options[:on].kind_of?(Array)
    models = options[:on].map {|m| instance_variable_get("@" + m.to_s)}.select {|m| !m.nil?}
    errors = models.inject([]) {|b,m| b += m.errors.full_messages}

    if errors.size > 0
      out << "<div class=\"container error\"><ul>\n"
      errors.each {|msg| out << "<li>#{h(msg.to_s)}</li>\n"}
      out << "</ul></div>\n"
    end
  end

  content_tag(:div, out, :id => 'message_block', :class => 'flash')
end

And the CSS code that works with it:

/*** Flash Messages ***/
.flash {

}

.flash ul {
    padding-left: 0pt;
    margin-bottom: 0pt;
    list-style-type: none;
    margin-left: 0pt;
}

.flash ul li {
    background: transparent url(../images/icons/bullets/gt.gif) no-repeat scroll left center;
    margin-bottom: 0.6em;
    padding-left: 1em;
    vertical-align: top;
}

.flash .container {
    padding: 1em;
    padding-left: 5em;
    margin-bottom: 1.5em;
}

.flash .error {
    background: #fcf6d0 url(../images/icons/flashes/error.gif) 1.5em 1em no-repeat;
    border-top: 1px solid #ecd757;
    border-bottom: 1px solid #ecd757;
}
.flash .back {
    background: #e9f3dc url(../images/icons/flashes/back.gif) 1.5em 1em no-repeat;
    border-top: 1px solid #bfcbb0;
    border-bottom: 1px solid #bfcbb0;
}

.flash .confirm {
    background: #e9f3dc url(../images/icons/flashes/confirm.gif) 1.5em 1em no-repeat;
    border-top: 1px solid #bfcbb0;
    border-bottom: 1px solid #bfcbb0;
}

.flash .info {
    background: #dee9f4 url(../images/icons/flashes/info.gif) 1.5em 1em no-repeat;
    border-top: 1px solid #b4c5d5;
    border-bottom: 1px solid #b4c5d5;
}

.flash .warn {
    background: #fcf6d0 url(../images/icons/flashes/warn.gif) 1.5em 1em no-repeat;
    border-top: 1px solid #ecd757;
    border-bottom: 1px solid #ecd757;
}

You may even want to consider writing a before_filter in your application controller that sets the flash types to arrays so you can just add messages to them with the << operator:

class ApplicationController < ActionController::Base
  before_filter :initialize_flash_types

  def initialize_flash_types
    [:back, :confirm, :error, :info, :warn].each {|type| flash[type] = []}
  end
end

Don’t use symbols for route parameters!

December 10th, 2007 benhughes

I’ve ran into this issue more than once: Be sure that you are using strings and not symbols when specifying parameters for routes. Particularly, if you specify a symbol for :action, Rails will fail to see your controller action yet still show your Rails view! This can sometimes be very difficult to diagnose. So, don’t do this:

map.connect '/pages/:slug',
:controller => 'pages',
:action => :show

Do this:

map.connect '/pages/:slug',
:controller => 'pages',
:action => 'show'

HTML-Aware Truncate Text

December 9th, 2007 benhughes

When building a large custom PHP CMS system for DigitalPeach, I ran into a very difficult issue: truncating text but maintaining HTML nested tags correctly. Specifically, we were looking to breaking up large articles composed using FCKEditor into separate pages after a certain character threshold. Once can easily see the problem:

<p>This is a test <strong>with some bold in here</strong>.</p>

Now imaging having to truncate this text to 30 characters, and you end up with this:

This is a test <strong>with

While this example isn’t quite so severe and at worst would only make the rest of the text within the block-level element bold, clearly if we do a truncation that is blind to HTML some serious problems can arise. Furthermore, even if it doesn’t have much practical significance, you are breaking XHTML.

I was lucky to stumble across an excellent article by Mike Burns who describes a Ruby method using REXML’s pull parser that can accomplish this. His example extended the String class, so I modified it to work as a Rails helper all in one method:

def truncate_html(input, len = 30, extension = "...")
  def attrs_to_s(attrs)
    return '' if attrs.empty?
    attrs.to_a.map { |attr| %{#{attr[0]}="#{attr[1]}"} }.join(' ')
  end

  p = REXML::Parsers::PullParser.new(input)
    tags = []
    new_len = len
    results = ''
    while p.has_next? && new_len > 0
      p_e = p.pull
      case p_e.event_type
    when :start_element
      tags.push p_e[0]
      results << "<#{tags.last} #{attrs_to_s(p_e[1])}>"
    when :end_element
      results << "</#{tags.pop}>"
    when :text
      results << p_e[0].first(new_len)
      new_len -= p_e[0].length
    else
      results << "<!-- #{p_e.inspect} -->"
    end
  end

  tags.reverse.each do |tag|
    results << "</#{tag}>"
  end

  results.to_s + (input.length > len ? extension : '')
end

Note that the nested method above is a completely valid use of Ruby, though not widely used.

And now look at what it can do:

truncate_html("<p>Test <strong>bold</strong> done.</p>", 30)
# => "<p>Test <strong>bold</strong></p>..."

Book Review: The Rails Way

December 8th, 2007 benhughes

Whenever I go to a bookstore I am sure to check out the Rails/Ruby section (constantly increasing in size!) for any new titles I may not be aware of. I was pleasantly surprised to find a new large Rails book that almost went unnoticed: The Rails Way by Obie Fernandez. I say almost went unnoticed because the book cover looks almost identical to The Ruby Way, so it’s easy to gloss over if you don’t look carefully.

It is easy to see by the sheer size that this book, weighing in at 850 pages, that it is very in-depth. The author explicitly states in the introduction that this is not a book for Ruby on Rails beginners. It was intended on being primarily an information-packed reference book for professional developers working with Ruby on Rails. The most appealing characteristic of the book is that it covers Rails 2.0, the first book to my knowledge that does.

After reading the book (it’s a long read!) I can definately say that this is a very valuable book for Rails developers. Typically after reading the Agile book, Rails developers end up craving knowledge of more advanced Rails techniques and plugins, and this book certainly delivers in this respect. Sprinkled throughout the detailed description of the Rails API are useful plugins, tips, and techniques that the author has come across in his development experience. Also included are many snippets of code from the Rails source code that help explain how key things work in Rails.

A full chapter outline is available online so I won’t bother duplicating that work, but let me point out a few areas of Rails that this book covers:

  • Rails Environment and Configuration – explains the Rails boot process and the automatic class loader, as well as other things behind the scenes that make Rails tick – very interesting.
  • New Rails 2.0 RESTful Routes – Covers some changes and enhancements to the RESTful routing features of Rails 2.0.
  • Advanced ActiveRecord – Really gives detailed information about ActiveRecord, even briefly explaining the AssociationProxy class that masquerades as an Array for those has_many associations.
  • Prototype Reference
  • Selenium Testing
  • RSpec
  • Using subversion with Rails and piston
  • Rails deployment with Capistrano
  • Common production configuration setups
  • Background processing with BackgrounDRb
  • ActiveSupport Reference

The last few topics in particularly were mostly until now the realm of random blog posts online with no solid resource in print.

In short, The Rails Way is a must-have for any developer working professionally with Ruby on Rails. Far from being a programming resource only, it helps you become an all-around better developer by arming you with techniques, new plugins, and tools to improve your productivity. Targeted towards the advanced user, this book is packed full of information that will greatly improve your facility with Rails. Buy it today!

Rails 2.0 Released!

December 7th, 2007 benhughes

So today Rails 2.0 was finally released; it seems as though the Rails core team has been polishing this up for ages. I don’t think there’s a whole lot to get excited about. In short, Rails 2.0 gives you better opportunity to make use of best practices, such as using the will_paginate plugin instead of build-in pagination (Rails 2.0 drops pagination support from core). Support for RESTful development is much improved, allowing more flexible route declarations and finally dropping the annoying semicolon separator for the edit action: projects/1;edit.

One very cool feature that should better allow developers to present meaningful error messages to users upon exceptions is the new rescue_from class method in ActionController::Base, which allows you to specify an exception class to rescue and an action to call to handle the error.

A few of my dissapointments of Rails 2.0 is that my two most pressing present concerns with Rails were not addressed:

A cohesive way of managing “fixture-like” data in an application. While simple Rails applications can rely on fixtures just fine, real production applications are not quite this simple and may rely on different sets of data that distinguish between semi-permanent “application” data and true test data. Multiple this by the dimension of multiple deployment environments (staging, production) which each may require different sets of data. I typically end up writing my own rake tasks and duplicate the fixtures data for specialized uses. It would be nice to see Rails provide an effective and standardized mechanism for being more flexible with “fixture-like” data rather than forcing us to use one inflexible “fixtures” directory.
Using the :include class in ActiveRecord finders creates severe limitations on the type of data you can get back. There have been numerous situations where I’ve wanted to use :include to get an object tree populated from one query yet still return an aggregation result in the select clause. A perfect example is listing forum threads, showing the number of comments but also including the user data who posted the thread. This is currently impossible with ActiveRecord because the select clause cannot be used with the include clause.
I plan on talking more about these two main issues for me in future posts, hopefully soliciting some responses. I haven’t found anything that adequately addresses my concerns.

Ultimately Rails 2.0 is sprinkled with various small changes rather than a fundamental architectural shift. As a result, it should be fairly easy to upgrade existing applications to Rails 2.0 and would probably be a good idea to do so, especially to force yourself to abandon bad practices that Rails 2.0 is less tolerant of.

One piece of reading that I would highly recommend if you already are familiar with Rails 1.2 and want to get up to speed on Rails 2.0 is the Peepcode PDF available here. I’ve found some of the Peepcode screencasts to be annoying slow an drawn-out, but this PDF is a must-have, packed full with the information you want to know, and quick to read.

Welcome!

December 2nd, 2007 benhughes

I’ve been wanting to start a Ruby on Rails blog for a while to document my experiences using the framework and engage with the community, but always felt I wouldn’t have enough time to maintain it. Today I decided to give in and begin RailsGarden.com.

So just about every developer working with Rails professionally has a life story culminating in total infatuation with the Ruby language and Rails framework; here’s mine:

Having starting programming at an early age with a continual and early interest in computers in general, I quickly latched onto web programming because of the relative ease and the potential to create something decent without a whole lot of work. I first dabbled in Perl and at one point developed a small data-driven e-commerce application that powered a very early version of www.rarenewspapers.com. Looking forward to the newer web technologies of the time, I began learning PHP and MySQL. Relational databases and techniques to structure and store data well has always intrigued me. To this day, modeling databases and advanced database structures are my specialty. I began doing some basic projects for a few clients online while still in high school. The projects I took on increased in complexity as I gained better design patterns and my own personal coding stuff. Most of these projects were for a company I am still deeply involved with, Digital Peach Interactive, based out of Georgia. I also dabbled a bit in Adobe ColdFusion and ASP.NET with SQL Server

My use of PHP to architect web applications culminated in the design and implementation of a large internal content management system used at Digital Peach, implementing advanced features such as a very sophisticated hierarchical category system for permissions and a workflow engine. Building this application with my boss was quite an experience and the data model ended up consisting of over 130 tables, including tables for some of our main modules.

Having done quite a bit with PHP and become pretty proficient in using it and MySQL to build data-driven applications, I wasn’t particularly “happy” with what I did and didn’t derive a lot of intellectual satisfaction out of building software in PHP. This all changed when I began to look at Ruby on Rails, a technology I very ignorantly ignored for so long. My first experience with RoR was viewing the standard make a blog screen cast and a few of the online slide shows. Though initially skeptical of the framework due to scalability and extensibility concerns (due to my superficial understanding), I decided to purchase the standard Agile Development with Ruby on Rails book. Reading this book was like a constant barrage of “aha!” moments, page after page. It would be difficult to find another tech book that had such a high ratio of information to pages; every page is packed full of useful information, ready for immediate application.

Already very excited about the prospects of using Rails as a framework, I still felt inadequate in my understanding of the framework and how it worked under the hood. Everything in Rails to me seemed like magic and it was insufficient for me to know that “has_many” established as one-to-many relationship with another model - I had to know why this was possible. This lead me to pick up the Programming Ruby pickaxe book which is an essential resource for really understanding the Ruby language.

I still am a strong believer in the Ruby language itself. The Rails framework is excellent, but ultimately what allows Rails to be so well-constructed is the extremely dynamic nature of the Ruby language. Engineering software components in Ruby is extremely enjoyable. Sometimes I think that Rails developers put too much emphasis on the Rails side and not enough on the Ruby side. I find that such emphasis also leads a lot of newcomers to Rails with an insufficient understanding of the Ruby language to dismiss the framework for this or that reason. Ultimately a complete and thorough understanding of the Ruby language is essential for appreciating many capabilities of using Rails as a framework for sufficiently large applications.

After these two books which have changed my life, I began reading other Rails/Ruby books to acquire more knowledge and gain better insight into the techniques used my professional Rails developers. Rails blogs were also an essential resource.

The rest, they say, is history! I’ve been using Ruby on Rails ever since, from small to large projects (such as Timothy Hughes Rare & Early Newspapers, which I’ll discuss in the future with this blog), and i’m learning something new every day. Working on the larger projects has really pushed me into new directions with Rails and helped me to establish a much better picture of the tools, plugins, and resources available to me when building software.

And so it is my goal with Rails Garden to document some of the tools and techniques I use in my professional use of Ruby on Rails. Enjoy!