Turns out it was a slight difference in the database table itself that was causing a change in behavior for ActiveRecord. The test database had no default value for the type
column, whereas in development, the default value was 'User'
. Apparently ActiveRecord uses the default value when inserting data for an object of the primary class type (the class that inherits from ActiveRecord::Base - in this case, User
). Why it doesn't just use the class name is beyond my understanding!
My real confusion came when I updated my dev database to have a default for the type column, which I actually knew it needed, because somehow the production database already had one, so clearly my dev database was just out of sync. So I did this:
mysql> ALTER TABLE users MODIFY COLUMN type varchar(50) NOT NULL DEFAULT 'User';
...[ok]
mysql> exit
Bye
$> bundle exec rake db:test:prepare # <-- My Mistake
...[ok]
I thought this was all I had to do, but it turns out running db:test:prepare
just matches your test database to your schema.rb
file, and my schema.rb
file hadn't been updated, so then User.create
worked in development, but broke in testing :D
Eventually, I came to understand all of the above, in addition to the fact that I needed to run db:migrate
in order to update my schema.rb
file BEFORE running db:test:prepare
. Once I did that: voila! User.create
actually used the default value of the type
column to insert new User objects.
Moral of the story:
- NEVER let your development database get out of sync with production. If it is: blow it away with a
db:schema:load
and start over with new dev data! (Or get a production dump or something)
- Choose your ORM wisely. R.I.P. DataMapper - I'll miss your elegant abstractions... but not your bugs.