Standalone console app

So, let’s get this party started with a simple console app that uses ActiveRecord. You can grab the following example from http://brycekerley.net/svn/ar-console/1-simple.rb .

The first things to do are to include rubygems and the activerecord gem (hopefully the machine you’re running the app on has these installed). Once that’s done, go ahead and establish_connection to the database, sqlite3 in this case.

require 'rubygems'
require 'active_record'

ActiveRecord::Base.establish_connection(
  :adapter => 'sqlite3',
  :dbfile => 'ar-console.db')

Now, I’m going to detour to directly interacting with the database in this case – in Rails, you use migrations to handle working with the data definition SQL (creating, altering, &c. tables). In the absence of that, you can do it by hand.

~/ar-console> sqlite3 ar-console.db
SQLite version 3.3.6
Enter ".help" for instructions
sqlite> create table names (id integer primary key, firstname varchar(20), lastname varchar(20));
sqlite> .schema
CREATE TABLE names (id integer primary key, firstname varchar(20), lastname varchar(20));
sqlite> ^D
~/ar-console>

Now that we have a table to interface with, we have to define a class that aligns with the table and inherits from the ActiveRecord::Base class. You can require this inline defintion from an external file, or even Dir.glob('some_rails_app/app/models/*.rb').each { |m| require m } to load all the models for some_rails_app in one fell swoop. Stay away from this way of integrating with a rails app for now – there’s a much better way.

class Name < ActiveRecord::Base
end

x = Name.new(:firstname=>"Hans", :lastname=>"Gruber")
x.save

y = Name.new(:firstname=>"John", :lastname=>"McClane")
y.save

Name.find_all.each { |n| puts n.inspect }

Finally, just for grins, we add some movie characters to the database, save them, and show who’s going to be running around Nakatomi Plaza today.

Flexible configuration

What if you want to move the configuration out into a .yml file just like rails? Turns out this isn’t terribly hard - Ruby comes with YAML support, so we can trivially use the same yaml file that Rails does. Adding database.yml support is nigh-trivial; our only caveat is that if you’re using SQLite you have to remember the path to the database is evaluated from where you execute the Ruby with this setup, seen in http://brycekerley.net/svn/ar-console/2-yamlized.rb.

require 'yaml'
require 'rubygems'
require 'active_record'

ActiveRecord::Base.establish_connection(YAML::load_file('database.yml')['development'])

Leeching Off Rails

Sometimes you want a console app to hook right in to Rails, but not serve web pages. As it turns out, we can do this quite cleverly, by loading the Rails environment the same way dispatch.cgi or script/console does. As an added bonus, we get to use Rails migrations, models are loaded for us, and so on. You do get to break all your business logic that you implemented as controllers, but you should be using a fat model and a skinny controller for this very reason.

The files we actually care about are boot.rb and environment.rb, in your app’s config directory. Assuming you want your app to live in a subdirectory off of your app’s / (i.e. next to public, app, and vendor), the incantation you need to establish the connection is as in http://brycekerley.net/svn/ar-console/3-railed.rb:

require File.dirname(__FILE__) + '/../config/boot' 
require File.dirname(__FILE__) + '/../config/environment' 
ActiveRecord::Base.establish_connection 

Coda

To snap up all the examples from this in one fell swoop, svn co http://brycekerley.net/svn/ar-console/ ar-console . If you’ve got any questions, fire away in the comments.