Using ActiveRecord outside Rails

There may come a time when you want to use ActiveRecord outside Rails. For example, writing a script to import data from an external source. For the RSS agregator, trawlr.com, I needed to do just this to crawl each of the RSS feeds every x minutes to retrieve the latest items.

Firstly, create a new file in the script directory (I used script/trawlr/runner.rb):

#!/usr/bin/env ruby

# Ensure the environment was specified
if ARGV.length != 1
  puts "usage: ruby runner.rb <rails_env>"
  exit 1
end

$LOAD_PATH << File.expand_path(File.dirname(__FILE__))

require 'rubygems'

ENV['RAILS_ENV'] = ARGV.first || ENV['RAILS_ENV']

require File.dirname(__FILE__) + '/../../config/boot'
require "#{RAILS_ROOT}/config/environment"

def connect(environment)
  conf = YAML::load(File.open(File.dirname(__FILE__) + '/../../config/database.yml'))
  ActiveRecord::Base.establish_connection(conf[environment])
end

# Open ActiveRecord connection
connect(ARGV.first)

You can now use all of the ActiveRecord functionality, including full access to the application’s models (and all associated validations, relationships). The script can be run via “ruby script/trawlr/runner.rb development” (and could also be run via cron for a scheduled task).

To add logging support simply add the following (specifying the log file appropriately):

require 'logger'

@@logger = nil

  def log
    if @@logger.nil?
      log_file = File.expand_path(File.dirname(__FILE__) + '/../../log/crawl.log')
      @@logger = Logger.new(log_file, 10, 100*1024)
      @@logger.level = Logger::INFO
    end
    @@logger
  end

If you want have timestamped log entries:

class Logger
    alias format_message old_format_message

    def format_message(severity, timestamp, progname, msg)
      "#{timestamp.to_s(:log_format)} [#{severity}] - #{msg}\n"
    end
end

References

More fun with Ruby reporting

Update

Before using this technique I’d recommend reading the following which details an improved method:

Using ActiveRecord outside Rails Part II


About this entry