Currently working on a merb project using datamapper - nice framework, but the auto-migrate feature is fairly limited - So I decided to hook up ActiveRecord’s migrations into the app. This code could be equally as easily adapted in to anything else.
First, I created a folder for the migrations to live in:
1
| mkdir -p db/ar_migrations |
I then appended a few tasks ripped out of Rails and slightly tweaked to the Rakefile:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
| APP_BASE = File.dirname(File.expand_path(__FILE__))
namespace :db do
task :ar_init do
# Load the database config
require 'active_record'
database_yml = YAML::load(File.open(APP_BASE + "/config/database.yml"))
init_env == "rake" ? current_env = "development".to_sym : current_env = init_env.to_sym # Default to dev env, symbolize
ActiveRecord::Base.establish_connection(database_yml[current_env])
# set a logger for STDOUT
ActiveRecord::Base.logger = Logger.new(STDOUT)
end
desc "Migrate the database through scripts in db/migrate. Target specific version with VERSION=x. Turn off output with VERBOSE=false."
task :migrate => :ar_init do
ActiveRecord::Migration.verbose = ENV["VERBOSE"] ? ENV["VERBOSE"] == "true" : true
ActiveRecord::Migrator.migrate(APP_BASE + "/db/ar_migrations/", ENV["VERSION"] ? ENV["VERSION"].to_i : nil)
Rake::Task["db:schema:dump"].invoke if ActiveRecord::Base.schema_format == :ruby
end
namespace :schema do
desc "Create a db/ar_schema.rb file that can be portably used against any DB supported by AR"
task :dump => :ar_init do
require 'active_record/schema_dumper'
File.open(ENV['SCHEMA'] || APP_BASE + "/db/ar_schema.rb", "w") do |file|
ActiveRecord::SchemaDumper.dump(ActiveRecord::Base.connection, file)
end
end
desc "Load a ar_schema.rb file into the database"
task :load => :ar_init do
file = ENV['SCHEMA'] || APP_BASE + "/db/ar_schema.rb"
load(file)
end
end
end |
These will read from database.yml in config/ , so make sure you’ve got datamapper set up.
Lastly, Let’s create an example migration to create the datamapper sessions table in db/ar_migrations/001_create_dm_session_table.rb:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
| class CreateDmSessionTable < ActiveRecord::Migration
def self.up
create_table(:sessions, :id => false) do |t|
t.string :session_id, :null => false
t.text :data
t.timestamp :updated_at
end
# Need this because ar in unhappy with a varchar primary key
sql = "ALTER TABLE sessions ADD CONSTRAINT sessions_pkey PRIMARY KEY ( session_id )"
execute(sql)
add_index :sessions, :session_id
add_index :sessions, :updated_at
end
def self.down
drop_table :sessions
end
end |
Once this is done, you can run rake db:migrate , and the DB will get the sessions table added. The db:schema:load task is also there, so you should use this when you first deploy your app to a new server. The naming is also consistent with rails, so capistrano should interact with it out of the box, with the exception that the environment to load/migrate needs to be called MERB_ENV instead of RAILS_ENV
When creating additional migrations you will need to follow the ‘proper’ naming scheme: the filename should start with an incrementing three digit number, and the rest should be a ‘flattened’ version of the class name. (i.e migration class AddPostTable becomes add_post_table).