Created
June 20, 2012 14:34
-
-
Save kstevens715/2960182 to your computer and use it in GitHub Desktop.
A monkey patch for Rails to fix SchemaDumper to not include table_name_prefix. Will probably be fixed in Rails soon, but needed this now. Based on PR: https://github.com/kennyj/rails/commit/211dcdeaa922c74ac20d274308fb5d41ad490194
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# config/initializers/active_record.rb | |
# Loads the monkey patch. | |
require 'active_record' | |
require 'active_record/schema_dumper' | |
require 'schema_dumper' | |
ActiveRecord::SchemaDumper.class_eval do | |
include Nepco::SchemaDumper | |
end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# lib/schema_dumper.rb | |
module Nepco | |
module SchemaDumper | |
def self.included(base) | |
base.alias_method_chain :table, :prefix_removed | |
base.alias_method_chain :indexes, :prefix_removed | |
end | |
def table_with_prefix_removed(table, stream) | |
columns = @connection.columns(table) | |
begin | |
tbl = StringIO.new | |
# first dump primary key column | |
if @connection.respond_to?(:pk_and_sequence_for) | |
pk, _ = @connection.pk_and_sequence_for(table) | |
elsif @connection.respond_to?(:primary_key) | |
pk = @connection.primary_key(table) | |
end | |
tbl.print " create_table #{remove_prefix_and_suffix(table).inspect}" | |
if columns.detect { |c| c.name == pk } | |
if pk != 'id' | |
tbl.print %Q(, :primary_key => "#{pk}") | |
end | |
else | |
tbl.print ", :id => false" | |
end | |
tbl.print ", :force => true" | |
tbl.puts " do |t|" | |
# then dump all non-primary key columns | |
column_specs = columns.map do |column| | |
raise StandardError, "Unknown type '#{column.sql_type}' for column '#{column.name}'" if @types[column.type].nil? | |
next if column.name == pk | |
spec = {} | |
spec[:name] = column.name.inspect | |
# AR has an optimization which handles zero-scale decimals as integers. This | |
# code ensures that the dumper still dumps the column as a decimal. | |
spec[:type] = if column.type == :integer && /^(numeric|decimal)/ =~ column.sql_type | |
'decimal' | |
else | |
column.type.to_s | |
end | |
spec[:limit] = column.limit.inspect if column.limit != @types[column.type][:limit] && spec[:type] != 'decimal' | |
spec[:precision] = column.precision.inspect if column.precision | |
spec[:scale] = column.scale.inspect if column.scale | |
spec[:null] = 'false' unless column.null | |
spec[:default] = default_string(column.default) if column.has_default? | |
(spec.keys - [:name, :type]).each{ |k| spec[k].insert(0, "#{k.inspect} => ")} | |
spec | |
end.compact | |
# find all migration keys used in this table | |
keys = [:name, :limit, :precision, :scale, :default, :null] | |
# figure out the lengths for each column based on above keys | |
lengths = keys.map { |key| | |
column_specs.map { |spec| | |
spec[key] ? spec[key].length + 2 : 0 | |
}.max | |
} | |
# the string we're going to sprintf our values against, with standardized column widths | |
format_string = lengths.map{ |len| "%-#{len}s" } | |
# find the max length for the 'type' column, which is special | |
type_length = column_specs.map{ |column| column[:type].length }.max | |
# add column type definition to our format string | |
format_string.unshift " t.%-#{type_length}s " | |
format_string *= '' | |
column_specs.each do |colspec| | |
values = keys.zip(lengths).map{ |key, len| colspec.key?(key) ? colspec[key] + ", " : " " * len } | |
values.unshift colspec[:type] | |
tbl.print((format_string % values).gsub(/,\s*$/, '')) | |
tbl.puts | |
end | |
tbl.puts " end" | |
tbl.puts | |
indexes(table, tbl) | |
tbl.rewind | |
stream.print tbl.read | |
rescue => e | |
stream.puts "# Could not dump table #{table.inspect} because of following #{e.class}" | |
stream.puts "# #{e.message}" | |
stream.puts | |
end | |
stream | |
end | |
def indexes_with_prefix_removed(table, stream) | |
if (indexes = @connection.indexes(table)).any? | |
add_index_statements = indexes.map do |index| | |
statement_parts = [ | |
('add_index ' + remove_prefix_and_suffix(index.table).inspect), | |
index.columns.inspect, | |
(':name => ' + index.name.inspect), | |
] | |
statement_parts << ':unique => true' if index.unique | |
index_lengths = (index.lengths || []).compact | |
statement_parts << (':length => ' + Hash[index.columns.zip(index.lengths)].inspect) unless index_lengths.empty? | |
index_orders = (index.orders || {}) | |
statement_parts << (':order => ' + index.orders.inspect) unless index_orders.empty? | |
' ' + statement_parts.join(', ') | |
end | |
stream.puts add_index_statements.sort.join("\n") | |
stream.puts | |
end | |
end | |
def remove_prefix_and_suffix(table) | |
table.gsub(/^(#{ActiveRecord::Base.table_name_prefix})(.+)(#{ActiveRecord::Base.table_name_suffix})$/, "\\2") | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment