Rails 3 Deployment
I recently deployed a Rails 3 application to a Linode VPS (they’re awesome BTW). I chose Ubuntu 10.04 for my linux distro and 1.9.2 for my version of Ruby. I installed Ruby from source instead of using RVM. RVM was my first choice, but I couldn’t get Passenger working with RVM. I don’t know if it was RVM or passenger but instead of wasting a ton of time, I just started over from scratch. As for the rest of the stack, I used Nginx with Thin and Mongodb for the database.
In the process, I accumulated a few useful links. Most of which are generally applicable and certainly worth sharing. So even though I wasn’t able to find the one article that solved all my problems, I found more than enough helpful advice.
- Setting up Rails 3 on Rackspace Cloud Servers
- Setting Up Ubuntu Server for Ruby on Rails Deployment
- Deploy Rails application via Git and Capistrano
- Installing a monitored Mongodb, Ruby 1.9, Nginx stack with Passenger on Ubuntu Linux
- Get intimate with your load balancer tonight!
- Capistrano series - configuring Capistrano #1
Sinatra And Bundler
I’ve been working with Rails 3 a lot lately and that work has led to a healthy appreciation for bundler. So much so, I figured it would be a good idea to update this site (a sinatra app) to work with bundler. The changes were pretty trivial in contrast to all the control you get from using bundler.
Here’s a quick rundown of what you need to do to get sinatra and bundler working together.
First thing you need is a Gemfile.
# Gemfile
source 'http://rubygems.org'
gem 'haml', '3.0.12'
gem 'RedCloth', '4.2.3'
gem 'sinatra', '1.0', :require => false
group :test do
gem 'rack-test', '0.5.4'
gem 'rspec', '1.3.0'
end
Notice that the sinatra gem is set to :require => false. This is Important to keep your existing app functioning properly.
Next I added a bundler_helper.rb file to my lib directory to do all the auto require magic.
# Bundler Helper
require 'rubygems'
require 'bundler'
Bundler.setup unless File.exists?(File.expand_path('../.bundle/environment', __FILE__))
Bundler.require(:default)
Now you can remove all the require calls for external gems inside your app file. Well, everything but the line that requires sinatra. The first five lines of my sinatra app now looks like this:
# add lib dir to load path
$:.unshift File.join(File.expand_path(File.dirname(__FILE__)), 'lib')
require 'bundler_helper'
require 'sinatra'
After that, it’s pretty much bundler business as usual.
Speks for Node.js
It’s been a long time since I’ve been excited to write about a topic. It’s been even longer since I’ve been excited about JavaScript. In fact, I’ve spent most of my career despising JavaScript. It’s a real shame because JavaScript is a beautiful and expressive dynamic programming language. And it’s taking a lot of rehabilitation in order for me to say that. JavaScript owes its popularity and bad reputation to the Internet. Specifically, the bad reputation is directly related to poor browser implementations and the script-kiddies (myself included) who amassed large piles of unmaintainable code. But this is changing and JavaScript has a great community to thank for that.
Node.js is a good example of how things are changing for JavaScript. I spent the past month learning and using node and it’s been a lot of fun. I strongly urge you to read about node if you’re not already familiar with it … cue the Jeopardy music.
So, um yeah, Node is awesome. It’s given me an opportunity to sharpen my JavaScript skills and learn more about writing concurrent applications. Plus it’s all server-side; so there’s no DOM and no cross-browser BS to worry about. What’s not to like?
My first Node project of any significance is a testing framework. It’s a simple RSpec derivative for node-code cleverly titled Speks (I know, brilliant right?). Speks is only a spec runner and a DSL for specifying your code but I have plenty of ideas for future enhancements. The anatomy of a spec is basic. It consists of a describe block, at least one nested it block and optional beforeEach, afterEach blocks. Like so:
describe("Sephiroth", function () {
var s = require('../spec/examples/sephiroth');
beforeEach(function () {
sephiroth = new s.Sephiroth();
});
it("should be named 'Sephiroth'", function () {
sephiroth.getName().shouldEqual('Sephiroth');
});
});
I’ve augmented some of the built-in JavaScript types to improve the readability of the specification code. The prototyping only occurs during the execution of a spec-run. There’s currently a dozen or so of these should prototype methods and I’ll be adding more soon. I’ve listed the available methods below.
// Object
obj1.shouldEqual(obj2);
obj1.shouldNotEqual(obj2);
obj1.shouldBeSame(obj1);
obj1.shouldNotBeSame(obj2);
// Boolean
true.shouldBeTrue();
false.shouldBeFalse();
// String
"foo".shouldMatch(/foo/);
"foo".shouldNotMatch(/bar/);
// Number
(1).shouldBeGreaterThan(0);
(2).shouldBeLessThan(1);
Download the source and try it for yourself; I could use the feedback.
Sign in, Login, Sessions
I started a new Rails project last week and had a lot of new-project questions to answer. On every new project, I try to get the boring tasks out of the way as early as possible. Getting a new project started fast is one of the advantages in using Rails but it’s inevitable that you’ll face some problems or decisions that require a pilot. And depending on how often you start new projects or how long it’s been since you started one, you’ve probably forgotten a thing or two. I know I did, but that’s why we have Google.
I began work on the sign in/sign up features since most of my stories require a user. I used authlogic for authentication because it’s awesome (pragmatic, I know). But I couldn’t decide between the phrase “login” or “sign in” so I hit the wild-web to do some research. My research (quick and unscientific) revealed an alarming amount of inconsistency. So I decided to go with “sign in” and move on with life.
While working on the sign in page I stumbled over another problem. If authentication failed, then my nice /signup route was replaced with the ugly /user_session route. So I hit the web again in search of a definitive answer. What I found this time was even more alarming than what I found the first time. There are numerous popular sites that have the same problem. Some sites had sign up links pointing to /login routes and others weren’t even from the same planet. I was unhappy with all the inconsistency. It’s the kind of mess I lose sleep over.
If you want to see for yourself, just have a look at twitter’s sign in page. Twitter’s link reads “login” and as you would expect, it takes you to the /login route. The header and button on the page read “Sign in” and “Sign In” respectively. If you fail to correctly enter your username or password you are redirected to the /sessions route. Whaaaa? I’m not trying to pick on twitter; they weren’t the only offenders. Take a look at github or justin.tv or peepcode’s website. That’s just a small sampling.
I solved my issue with a simple change to the routes.rb file and a small tweak to my sign in form. I updated my sign in form to post to the signin_path and added the following lines to routes.rb:
map.signin 'signin', :controller => 'user_sessions',
:action => 'new', :conditions => { :method => :get }
map.signin 'signin', :controller => 'user_sessions',
:action => 'create', :conditions => { :method => :post }
Introducing MacVim
I hate VI. Well, I used to hate VI. Back in my Sys. Admin. days, I avoided VI like I owed it money. I was convinced my *nix savvy coworkers were hittin’ the pipe. They couldn’t persuade me with banter, intelligent conversation or free beer (yep, even free beer). I was a Windows guy; a right click wonder. In the age of GUIs, rodent peripherals and boy bands, why would I waste time cramming archaic commands into to an already overcrowded brain? Every time I encountered VI, I asked myself the same question. “How the hell does anyone use this sh*t?”
Sadly, I didn’t leave my comfort zone long enough to answer that question. I wasted years avoiding VI due to an irrational aversion to learning (the kind of behavior I so deeply despise). If you’re going to say nay to a tool, then you should be able to intelligently articulate the reason(s) why. That wasn’t the case with VI.
In an effort to change that, I installed MacVim. The first few minutes were intimidating but rather than run in terror, I took to Google. After skimming a few blog posts and tinkering with config files on GitHub, the intimidation was no more. My nerd-sense was tingling. It was clear I wasn’t dealing with the crusty command line VI that ate noobs for breakfast. Nope, MacVim was noob friendly. Several hours and a few commands later, I was easily moving though my code. Thanks to plugins, I was able to extend MacVim with most of the features that make TextMate such an amazing editor. I was also pleased that it looked like a mac app and not some hideous Linux port.
Conclusion
It’s to early to corroborate the stories of enhanced productivity but in the meantime, I’m having fun. I know vim’s not for everyone and you don’t have to drink the kool-aid. I simply wanted to share an experience and maybe inspire an open-mind. Besides, learning new things is good to fend off zee stasis.
My current MacVim configuration is on GitHub if you’re so inclined.