I came across an interesting issue this morning using Rails 3 beta 4.
in my user.rb I have a scope:
scope :public, where(:private => false)
This was absolutely fine when I added the scope, since the "private" field was in the database.
I wanted to modify the migration, so I rolled back the database, but by doing so, I nuked the private field.
Now when I try to rollback or run any migrations, I get:
No attribute named `private` exists for table `users`
Full Trace:
This is happening (I think) because Rails is building the predicate for the scope at runtime ... when the field doesn't exist.
Whenever something like this happened in Rails 2, I'd normally put the class inside the migration, eg:
class AddUsernameToUser < ActiveRecord::Migration
class User < ActiveRecord::Base end
def self.up add_column :users, :username, :string add_column :users, :private, :boolean, :default => false end
def self.down remove_column :users, :private remove_column :users, :username end end
This doesn't work in this case, because it all happens before _any_ migration is run.
So basically, I have to remove the scope to run any migrations.
This is fine for now, as I can move on with development, but the implication is that if I start off with a clean database, and run rake db:migrate, it won't work.
Now, I know that best practice is to use rake db:schema:load, but I think that this is still a brittle case.
Basically, by adding a scope that depends on a field existing, all prior migrations break.
—Paul