Skip to content

Instantly share code, notes, and snippets.

@carllerche
Created July 26, 2008 02:04
Show Gist options
  • Save carllerche/2576 to your computer and use it in GitHub Desktop.
Save carllerche/2576 to your computer and use it in GitHub Desktop.
# NOTE, all names, syntax, etc... are just off the top of my head to illustrate
# the general idea. Don't take anything too literally.
# I just started a blank project with DataMapper. DM Migrations knows
# that the current production database is empty because no schema has been "committed".
#
# I then created a new model:
class User
include DataMapper::Resource
property :id, Serial
end
# DataMapper.auto_migrate! can run and creates a new table users with the ID property.
# A new migration file is also created named work_in_progress.rb with the following
# content:
migrate(
:from => table(:users).missing,
:to => table(:users).with(:id => Serial)
) do
create_table(:users) do |u|
u.column :id, Serial
end
end
# I now decided that I want a username property and change the file:
class User
include DataMapper::Resource
property :id, Serial
property :username, String
end
# I run DataMapper.auto_migrate and the new column is created in development mode.
# DM still knows that I haven't committed so it goes ahead and modifies the current
# workign migration file to:
migrate(
:from => table(:users).missing,
:to => table(:users).with(:id => Serial, :username => String)
) do
create_table(:users) do |u|
u.column :id, Serial
u.column :username, String
end
end
# So, I decide I want to deploy my awesome application and type a command rake dm:commit
# and datamapper "freezes" the current work_in_progress.rb migration file for deployment.
# So, I deploy my app and decide that it sucks and I need to improve it. I also get John
# to help me. So, now there are two developers working on this awesome app.
# Ok, I decided that I needed to add a password field:
class User
include DataMapper::Resource
property :id, Serial
property :username, String
property :password, String
end
# I run auto_migrate. The old committed migration file is stashed somewhere and a new
# work_in_progress.rb migration is created with the following:
migrate(
# As you can see, this migration only requires a users table (with anything in it)
# as long as it can successfully add the password column
:from => table(:users),
:to => table(:users).with(:password => String)
) do
add_column :users, :password, String
end
# Ok, now John decides that he wants to remove :username (wtf??):
class User
include DataMapper::Resource
property :id, Serial
property :password, String
end
# And he commits and gets the following migrate file:
migrate(
# As you can see, this migration only requires a users table (with anything in it)
# as long as it can successfully add the password column
:from => table(:users).with(:username => String),
:to => table(:users)
) do
remove_column :users, :username
end
# Now here's a cool bit. What if I decide to change :password to an Integer and John
# decides to change :password to a Boolean? My migrate file would look like:
migrate(
:from => table(:users).with(:password => String),
:to => table(:users).with(:password => Integer)
) do
create_column :users, :new_password, Integer
execute "update users set new_password = integer(password);"
remove_column :users, :password
rename_column :users, :new_password, :password
end
# And John's migration file would look like:
migrate(
:from => table(:users).with(:password => String),
:to => table(:users).with(:password => Boolean)
) do
remove_column :users, :password
create_column :users, :password, Boolean
end
# DM Migrator would know that there is a conflict here and something would happen.
# CONCLUSION:
# The whole point is to make development easy with auto_migrate and then being able
# to safely get changes to production with some kind of smart migration files. This
# is still a really rough and crazy idea.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment