We want to add a new column to mark users as admins. Since we want to avoid
having null
values for this boolean field, we need to backfill the value for
all existing users.
Are there any potential issues with the following migration?
class AddAdminFlagToUsers < ActiveRecord::Migration
def up
add_column :users, :admin, :boolean, default: false
User.update_all(admin: false)
change_column_null :users, :admin, false
end
def down
remove_column :users, :admin
end
end
We are referencing a User
constant which may not exist when this migration
is run in the future.
While migrations contain the full history of the database schema for a project, they are always run in the context of the current codebase. Referencing a model constant, while tempting, can lead to issues down the road.
Instead, you should use SQL directly to make the change since the table that the model wraps is guaranteed to be present when the migration is run, unlike the model itself.
class AddAdminFlagToUsers < ActiveRecord::Migration
def up
add_column :users, :admin, :boolean, default: false
connection.update(<<-SQL)
UPDATE users SET admin = 'f'
SQL
change_column_null :users, :admin, false
end
def down
remove_column :users, :admin
end
end
The updated version of the migration uses the connection
object to execute
a raw SQL statement directly against the database, additionally using a
[heredoc][] to define the SQL statement.
Note - we also need to create the column in two steps since it can't be
created with null: false
as the existing rows will not pass this constraint.
[heredoc]: http://ruby-doc.org/core-2.2.0/doc/syntax/literals_rdoc.html#label-Here+Documents
Return to Flashcard Results