Skip to content

Instantly share code, notes, and snippets.

@ridiculous
Created October 4, 2018 23:52
Show Gist options
  • Save ridiculous/e2753fc217af19cab0a2f3edac6d5ce7 to your computer and use it in GitHub Desktop.
Save ridiculous/e2753fc217af19cab0a2f3edac6d5ce7 to your computer and use it in GitHub Desktop.
Find discrepancies between Rails schema.rb and the actual database
class FakeSchema
attr_reader :defs, :diff
def self.define(*, &block)
$schema = new
$schema.instance_eval(&block)
end
def initialize
@defs = {}
end
def create_table(name, options, &block)
@defs[name] = {}
yield table = FakeTable.new(options)
@defs[name][:columns] = table.columns
nil
end
def add_index(table_name, fields, options)
@defs[table_name][:indexes] ||= []
@defs[table_name][:indexes] << options.fetch(:name)
nil
end
def compare
@diff = Hash.new { |me, key| me[key] = HashArray.new }
@defs.each do |table, options|
db_cols = db.select_values("SHOW FIELDS FROM #{table}")
if db_cols.sort != options[:columns].sort
@diff[table][:columns] = db_cols - options[:columns]
@diff[table][:columns] |= options[:columns] - db_cols
end
Array(options[:indexes]).each do |index|
if db.select_values("SHOW KEYS FROM #{table} WHERE key_name = '#{index}'").blank?
@diff[table][:indexes] << index
end
end
end
@diff.empty?
end
def db
@db ||= ActiveRecord::Base.connection
end
class FakeTable
attr_reader :columns
def initialize(options)
@columns = []
@columns << 'id' if options[:id] != false
end
def method_missing(name, *args, &block)
@columns << args.first
end
end
end
ActiveRecord::Schema = FakeSchema
require Rails.root.join('db/schema')
$schema.compare
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment