Back in December I blogged about how to access ActiveRecord & Migrations outside of Ruby on Rails. It was a little to scriptish for my liking so I've refactored it in a couple of classes instead.
Before you had to copy the code to a new file and add your database migration inside the Script.run method. I've now broken this up into a DatabaseScript class that extends ActiveRecord's Migration and has the guts of how and where to run any database commands and then any number of script classes that do the actual work.
The classes that you write on a day to day basis are now similar in style to the standard Rails Migrations:
Before you had to copy the code to a new file and add your database migration inside the Script.run method. I've now broken this up into a DatabaseScript class that extends ActiveRecord's Migration and has the guts of how and where to run any database commands and then any number of script classes that do the actual work.
The classes that you write on a day to day basis are now similar in style to the standard Rails Migrations:
require 'database_script'For example I want to update
class UniqueScriptName < DatabaseScript
def self.run
# your migration code goes here
end
end
my_table
and set all the updated
column for all rows to be true
:require 'database_script'If you want to use a specific database connection (rather than one of the standard Rails ones
class UpdateMyTable < DatabaseScript
def self.run
execute('update my_table set updated = true')
end
end
development, testing, production
) then add the following method in the above class:def self.database_connection_detailsThis is what the
<<-YAML
custom:
adapter: ????
database: ????
username: ????
password: ????
YAML
end
DatabaseScript
class looks like:require 'active_record'Technorati Tags: Ruby, Rails, Database, Migrations, Andrew Beacock
class DatabaseScript < ActiveRecord::Migration; end
def self.script_name(script_file)
return *script_file.scan(/(.*).rb/).first
end
def script_class(script_name)
script_name.camelize.constantize
end
script_name = script_name($0)
require script_name
script_class = script_class(script_name)
# to run this within the context of a Rails app then pass your environment on the command line:
# ruby <script name>.rb development
database_type = ARGV[0]
if database_type.nil?
database_yaml = script_class.database_connection_details
else
# if you have a Rails project then place your scripts in db/script
database_yaml = IO.read('../../config/database.yml')
end
databases = YAML::load(database_yaml)
database_type = databases.keys[0] if database_type.nil?
ActiveRecord::Base.establish_connection(databases[database_type])
script_class.run
Comments
All you need to do now is add 'Pre' and 'Post' condition checking and you're there...