Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to avoid crashing Rails app after removing column from table?

The problem

I just learned that our current practice for removing a column in an ActiveRecord migration is to hide the column from Rails before actually removing it (via an ugly hack, see below for details).

This is due to the fact that Rails caches the SHOW FULL FIELDS query. If we don't work around that, the (long-running) migration will remove the column and by that time, Rails will have already cached the fields. Once the migration is done and the column is gone, the app will subsequently crash because INSERTs will provide values for a non-existing column because of the cache.

Using things like clear_table_cache! within the migration are of no use because we deploy to N servers and run the migration on just one of them. This would clear the cache on one of the servers but not all.

Our current solution (a.k.a. ugly hack)

What we're currently doing is overriding ActiveRecord::ConnectionAdapters::AbstractMysqlAdapter#columns in an initializer and deploy that before running the migration.

After the migration is done, we remove the overriding initializer and deploy again.

At this point, I cannot believe we're the only ones who encounter this problem and have to work around it. Are there any other solution to this problem?

like image 311
awendt Avatar asked Sep 15 '15 08:09

awendt


1 Answers

Rails 5 has added ignored_columns to the ActiveRecord::Base class:

Since some columns will appear or disappear at any moment, you want to make those columns invisible to AR for a while. Otherwise you could have some processes knowing about the columns and others who don't.

Here's some sample code:

class User < ApplicationRecord
  self.ignored_columns = %w(employee_email)
end
like image 172
awendt Avatar answered Oct 19 '22 22:10

awendt