It’s possible to use ActiveRecord is a standalone ORM library in a non-Rails Ruby project. It can be tricky to figure out, though, so this article aims to help.
As of this writing, the latest version of ActiveRecord is 4.2.0, so that is what I will be targeting. I can’t guarantee that everything will still work the same for any other version. You can browse the source code here:
There are two steps to getting ActiveRecord set up. The first is configuring it to connect to your existing database, which is fairly easy. The second step is to get Rake tasks (including migrations) set up, which I found to be rather tricky.
I’ve created a simple Ruby project as a demo of what’s written here. Check it out here.
For this step, I’ll follow Rails’ lead and make a file called
config/database.yml, which will define settings for several different environments. Note that the settings in my project are specific to my personal computer, so you’ll need to adjust them.
Then I’ll make a file called
lib/ar_without_rails/database.rb, which, when loaded, will read the configuration file, and connect ActiveRecord to the database based on the
DB_ENV environment variable.
Here's the simplest possible model. Now you’re all done, as long as you’re okay with creating your database and tables manually.
Maybe if we just load the ActiveRecord
databases.rake file, things will work. Here’s what that would look like:
include ActiveRecord::Tasks DatabaseTasks.database_configuration = YAML.load_file('config/database.yml') load 'active_record/railties/databases.rake'
When we try to run
bundle exec rake db:create, we get an error, and we can see from the stack trace we can see that Ruby ran in to a mysterious undefined constant called
Rails. I looked in to this, and found that a lot of the tasks defined in
databases.rake could be run successfully outside of Rails, but the few that won’t work are critical. Furthermore, I don’t know of any way to “inherit” from this file and override just some of the tasks, so we’re stuck with basically copy-and-pasting it all in to our own project.
Here is an annotated version of a Rakefile that will work:
# Initialize bundler require 'bundler/setup' Bundler.require :default, :test # Load project files $: << File.dirname(__FILE__) + '/lib' require 'ar_without_rails' # ActiveRecord rake tasks include ActiveRecord::Tasks namespace :db do task :load_config do DatabaseTasks.database_configuration = YAML.load_file('config/database.yml') DatabaseTasks.env = ENV['DB_ENV'] || 'development' ActiveRecord::Base.configurations = DatabaseTasks.database_configuration end desc 'Create database for given DB_ENV (default development)' task create: :load_config do # ActiveRecord depends on this environment variable ENV['RAILS_ENV'] = DatabaseTasks.env DatabaseTasks.create_current DatabaseTasks.env end
drop task reveals a bit of odd behavior. If the
RAILS_ENV environment variable is not set, then the
create_current method will create both test and development databases, regardless of what arguments we pass to it.
desc 'Migrate database for given DB_ENV (default development)' task migrate: :load_config do config = DatabaseTasks.database_configuration env = DatabaseTasks.env ActiveRecord::Base.establish_connection config[env] DatabaseTasks.migrate end desc 'Drop, create, and migrate database for a given DB_ENV (default development)' task :reset => [:drop, :create, :migrate] end
There we have it. You might notice that this Rakefile is incomplete. I only added the tasks I needed, but it should not be too difficult to adapt other tasks from
databases.rake if you need them.