Poor man's migrations
In case you have read PJ’s post on Automatic migrations you might like this.
PoorMansMigrations is a very simple Active Record extension that allows you to create/update/delete DB columns without using migrations directly.
Playing with your models can be as easy as :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
require 'rubygems' require 'activerecord' require 'poor_mans_migrations' ActiveRecord::Base.establish_connection :adapter => "mysql", :host => "localhost", :username => "root", :database => "property_db" ActiveRecord::Base.logger = Logger.new($stdout) class User < ActiveRecord::Base column :age, :string column :name, :string column :admin, :integer, :default => 0 end User.migrate u = User.create :age => '1000', :name => 'whatever' |
Doing Model.migrate will automatically sync the database table with the columns you define inside your models. That is, if you add new column :what, :ever statements, those columns will be created in the table. Similarly, if you remove any column statements, respective columns will be removed from the table.
But hey, thats just stupid. Age is integer silly! Changing the column is a little tricky. As I didn’t want the library to be super smart in figuring out what changed when, I just used a simple/stupid/verbose solution. If you supply :force => true option to column definition, the column will be dropped and recreated when you do Model.migrate
So the following will fix the age column :
1 2 3 4 5 |
class User < ActiveRecord::Base column :age, :integer, :force => true end User.migrate |
And if you royally screw up, and just want to start everything from scratch :
|
|
User.migrate! |
Migrate with a !
Here’s the code for PoorMansMigrations :
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 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 |
# Released under WTFPL - http://sam.zoy.org/wtfpl/ module PoorMansMigrations def self.extended(base) base.class_inheritable_accessor :migration_columns base.migration_columns = [] end def column(name, type, options = {}) self.migration_columns << {:column_name => name, :column_type => type, :options => options} end def realize!(force_drop = false) # Force drop if needed connection.drop_table(table_name) if force_drop && table_exists? # Create table connection.create_table(table_name) {|t| } unless table_exists? self.migration_columns.each do |p| #haxhaxhax - Force reload reading column names. Whatever. reset_column_information column_exists = column_names.include?(p[:column_name].to_s) # Delete the columns if forced to if p[:options].delete(:force) && column_exists connection.remove_columns(table_name, p[:column_name]) column_exists = false end connection.add_column(table_name, p[:column_name], p[:column_type], p[:options]) unless column_exists end end def clean_leftover_columns! return unless table_exists? reset_column_information left_overs = column_names - self.migration_columns.map {|m| m[:column_name].to_s} - Array(primary_key) connection.remove_columns(table_name, left_overs) reset_column_information end # Force recreation for everything def migrate! realize!(true) clean_leftover_columns! end # Take it easy. Only force if specified in column definition def migrate realize! clean_leftover_columns! end end ActiveRecord::Base.send :extend, PoorMansMigrations |
Main purpose of PoorMansMigrations is to make it very simple to play around with Active Record, independent of Rails. In stand alone scripts, etc. It should be very simple for anyone to write the needed plugin in order to use it in regular Rails apps. PDI.
Please note that you would never want to use this code/method in any production application. Destructive migrations can cost you your job.
UPDATE 1 : I had made a schoolboy error in the initial version of the code, by not using class inheritable attributes. It’s been fixed now.


Recent comments
1 year 23 weeks ago
1 year 23 weeks ago
1 year 25 weeks ago
1 year 27 weeks ago
1 year 42 weeks ago
1 year 45 weeks ago
1 year 45 weeks ago
1 year 45 weeks ago
1 year 46 weeks ago
1 year 48 weeks ago