code in migration #5

0 views
Skip to first unread message

Thomas Blumenfeld

unread,
Oct 16, 2008, 10:10:44 AM10/16/08
to ins...@googlegroups.com
Hi!

I was looking into the code of the 005_create_forums.rb migration, it is
also present in the last stable release.

Here it is:
class CreateForums < ActiveRecord::Migration

class Forum < ActiveRecord::Base
end

def self.up
create_table :forums do |t|
t.string :name
t.text :description
t.integer :topics_count, :null => false, :default => 0

t.timestamps
end
Forum.create!(:name => "Discussion forum",
:description => "The main forum")
end

def self.down
drop_table :forums
end
end

What does those lines mean?

class Forum < ActiveRecord::Base
end

Thx

Thomas

Michael Hartl

unread,
Oct 16, 2008, 6:09:46 PM10/16/08
to ins...@googlegroups.com
The need for that code was discovered by Insoshi contributor Evan
Dorn, who found that changes in models (adding validations, for
example) could break the migration code. Declaring the model in the
migration solves this problem, though I admit it's a bit mysterious.

By the way, it's not as easy as bypassing the validations by writing
something like Forum.new(...).save(false). In migration 13, which
adds an admin user, we have code like this:

class Person < ActiveRecord::Base
end
.
.
.
def self.up
add_column :people, :admin, :boolean, :default => false, :null => false
.
.
.
person.admin = true

Without the "class Person < ActiveRecord::Base" part, the
"person.admin" step fails, because the Person model doesn't have an
admin column when the migration runs. Again, for somewhat opaque
reasons, the model declaration solves the problem.

I've added an explanatory comment to the first occurrence of this code
(the one you discovered) to allay confusion in the future.

Thanks,

Michael

--
Michael Hartl
Insoshi social software
http://insoshi.com/

Thomas Blumenfeld

unread,
Oct 17, 2008, 3:10:57 AM10/17/08
to ins...@googlegroups.com
Ok, thank you very much for these explainations. I've got my answer. Thanks!

Jorge Calás Lozano

unread,
Oct 17, 2008, 12:14:10 PM10/17/08
to ins...@googlegroups.com
I guess the opaque reasons are something like this:

commit 1

add app/model/person.rb
add db/migrate/001_create_people.rb

where xxxx_create_people have something like this inside

Person.create(:name => "Blah")

you run rake db:migrate and everything is ok

commit 2

delete app/model/person.rb

you run rake db:migrate (from a clean install) or rake db:migrate:reset

It fails, why, because you don't have a Person model

YOU SHOULD NEVER remove or edit a migration once other people are using
them since nothing will happen when you run db:migrate again.

result: Broken migrations

solution:

you create the class Person inside the migration. But the truth is you
don't create the Person, but CreatePeople::Person (the migration is a
class, in this case CreatePeople). But why you don't call
CreatePeople::Person? because you are calling it from inside the
CreatePeople class, ruby is smart enought to find the correct class.

Make sense? Am I right?

cheers,

Jorge

Reply all
Reply to author
Forward
0 new messages