This decouples a deployment from completed migrations. Give us control of the data manipulation proccess by encapsulatin it in on place. need to remember to:
- Run it in one of the ways bellow: a. Add this rake task the deployment script or; b. Run it mannually after the deployment.
- Need to clean up after the end of the data manipulation;
- Need to remove the rake task after the deployment is implemented; Example of rake task:
# lib/tasks/temporary/users.rake
namespace :users do
desc "Update confirmed users to receive newsletter"
task set_newsletter: :environment do
users = User.confirmed
puts "Going to update #{users.count} users"
ActiveRecord::Base.transaction do
users.each do |user|
user.mark_newsletter_received!
print "."
end
end
puts " All done now!"
end
end
If you don't need to save the model, then make it read-only with:
class Role < ActiveRecord::Base
def readonly?
true
end
end
This way the model can be modified without concerns.
If you need to remove a column, first deploy an update so the ActiveRecord cache ignore it like this:
class User
def self.columns
super.reject { |c| c.name == "notes" }
end
end
Then you may safelly remove the column in the next deploy.
Do it i three steps:
- Add the new column (first_name) and read/write from/to both columns (first_name failling back to fname). Don't change any queries yet!
def first_name
super || attributes["fname"]
end
- Populate the new column with data from the old column and update the queries.
- Delete the old column.
- Make sure you are writing to the columnn that will receive the constraint
before_save :assign_defaults
def assign_defaults
self.admin ||= false
end
- Update all existing records that have the column as null.
- Add the constraint.
- Rails don't create indexes concurrently and, if the table receives lots os writes, you need it. the only way is to use raw SQL.
class IndexUsersEmails < ActiveRecord::Migration
def ddl_transaction(&block)
block.call # do not start a transaction
end
def self.up
execute "CREATE INDEX CONCURRENTLY index_users_on_email ON users(email)"
end
end
Rails will dump the index to a Ruby schema normally.
– Safe for readonly models – Safe when there are no constraints on the column
– Safe for readonly models – Tell AR to ignore the column first
– Not safe – First add a new column, then remove the old one – When the column is used on SQL queries you’ll need to split this in three steps
– Safe
– Safe
– Safe only for readonly models – Otherwise make sure you create indexes concurrently
– Safe