Resources For Rails Development in Vim

While most programming languages seem to take steps toward big, full-featured graphical IDEs, Rails development seems to have gone the reverse: back to the command line, command line editors, and minimalist interfaces. Today, I’d like to share with you several resources that I’ve used to streamline my development process.

TextMate (€39) MacroMates.com — Considered the definitive text editor for OS X, TextMate is a worthwhile purchase for any developer using any language. It’s extensible, powerful, and, Rails-specifically, allows for easy navigation between your MVC layers with easy hotkeys. If you code on OS X, you owe it to yourself to buy this.

The Playbook (free/$15/$50) ThoughtBot.com — If you’re looking for tips on how to start a web design firm, set up your development environment, do proper project management, and more, consider picking up a copy of The Playbook, an eBook written by the geniuses at ThoughtBot. ThoughtBot is known for several of their Ruby gems that have been released into the public domain, including high_voltage, clearance, suspenders, and more. They are also known for some of their hugely popular applications, including Airbrake and Trajectory. They offer a few free snippets, a single user license, and a group license.

Rails.vim (free) GitHub.com — While Vim is an amazing editor on its own, it thankfully allows for plugins to be written to extend the functionality. Written by Tim Pope (Twitter/GitHub), Rails.vim is an amazing plugin that adds a whole host of commands to the editor, allowing for more fluid Rails development. Best of all, it’s free, open source, and readily available on our favourite source control repository, GitHub.

Vim for Rails Developers ($15/$50) ThoughtBot.com — Vim is considered one of the most powerful text editors out there, and it’s available on virtually every platform. That being said, it’s a dauntingly steep learning curve (although I wrote a guide on getting started with it), and every bit of help you can get is worth it. This 34 minute video gives you the rundown of using rails.vim along with your Vim install. As with The Playbook, a single user and group license is available.

RailsCasts (free/$9 per mo) RailsCasts.com — Probably the go-to for most Rails podcasts, Ryan Bates (Twitter/GitHub) has been churning out 2 podcasts about Ruby on Rails for years now. He explains topics clearly, pushes the limits of what gems can do, and always offers comparisons between similar gems. Most of his content is free, but Pro users ($9/month) get access to Pro episodes which cover more content and new gems.

Dynamic Named Routes for Semi-Static Pages in Rails

When I was designing the new UMSwing website, I had a few issues that, at the time, I didn’t have a clean method of implementing. One of those was the creation of semi-static pages. After watching this episode of Railscasts, I had a pretty good idea of how to implement them. The only issue with the solution offered was the lack of dynamically generated routes.

Semi-static pages are used everywhere on websites. They’re those pages like an “About” page, which has content on it that doesn’t really change that often. Typically, a controller would have to house these actions (/about, /faq, /contact, etc.), and  the routes specified manually. Railscasts came up with an ingenious idea to create a controller which was routed to /static/*, so that semi-static pages could be created on-the-fly and modified easily. It also allows for modifications to change without committing to a repository and going through the process of deploying all over again.

For those needing a quick Rails primer before going on, here’s the quick and dirty of what you need to know to understand this:

  • Rails is a MVC-based web application framework that runs on Ruby. In short, Ruby code is written to create webpages on-the-fly.
  • Every request in Rails is first put through the routes file in config/routes.rb. This file tells Rails which Controller and Action is run.

Okay, let’s get started. Let’s create our static pages scaffold (which includes model, views, and the controller). Obviously, there are sections of this that you would want to require authentication for (editing and deleting, for example), but that’s outside the scope of this tutorial.

script/generate scaffold pages title:string permalink:string content:text;
rake db:migrate

Now we need to modify our controller slightly. More specifically, our show action. Right now, it will respond to showing an element only when the ID is displayed. We want to modify it to handle a permalink as well (/about and /contact look better than /pages/135, don’t you think?). Here is your modified show action:

def show
  if params[:permalink]
    @page = Page.find_by_permalink(params[:permalink])
  else
    @page = Page.find(params[:id])
  end
end

Before we go any further, we need to create two custom methods in our model. These will format the permalink to remove any unwanted characters for the custom route name (replacing all unacceptable characters with an underscore) and for the URL (replacing all unacceptable characters with a forward slash to allow for nesting of pages). It’s also important to note here that previous validation should be done to ensure that the permalink does not have leading or tailing non-alphanumeric characters, but I removed that for simplicity’s sake.

class Page < ActiveRecord::Base
  def route_name
    p = self.permalink.gsub(/([^A-Za-z0-9])+/, '_').downcase # Change non-alphanumeric characters to an underscore
    "static_#{p}"
  end

  def uri
    self.permalink.gsub(/([^A-Za-z0-9])+/, '/').downcase # Change non-alphanumeric characters to a forward slash
  end
end

At this point, we can create and modify our pages as we would regularly expect from a new controller. All of our pages are accessible via /pages/1, /pages/2 etc. We now need to make our controller act as our catch-all (so that all requests that do not match any of the other controllers get routed to our Pages controller), and we also need to provide permalink support. Finally, we will dynamically generate customized, name routes for all of our semi-static pages. All of that gets accomplished with a few short lines of code. Add the following code to the top of your config/routes.rb file, starting at line 2 (inside the ActionController::Routing::Routes.draw section):

def map.static_page_actions
  pages = Page.find(:all)
  pages.each do |page|
    self.send("static_#{page.route_name}", "#{page.uri}", :controller => "Pages", :action => "show", :permalink => page.permalink)
  end
end

Finally, we need to call this method close to the bottom of the code, right before our default catch-all routes.

map.static_page_actions
map.connect ':controller/:action/:id'
map.connect ':controller/:action/:id.:format'

What this method does is retrieve all of the static pages in the database, then creates a customized, named route for each page, telling Rails what each URI should look like, and where to direct the request to.

Hopefully this helps some people out with their dynamic page creation. I’m pretty sure there’s a pitfall or two here, but I think it could be taken care of by doing some simple route housecleaning in the Pages CRUD controller. The perk of this option is that it allows the routes to be named, and hopefully that is of some benefit for others.