Class: ActiveRecord::SchemaDumper
This class is used to dump the database schema for some connection to some output format (i.e., ActiveRecord::Schema).
Public Class Methods
dump (connection=ActiveRecord::Base.connection, stream=STDOUT)
# File vendor/rails/activerecord/lib/active_record/schema_dumper.rb, line 16 16: def self.dump(connection=ActiveRecord::Base.connection, stream=STDOUT) 17: new(connection).dump(stream) 18: stream 19: end
new (connection)
# File vendor/rails/activerecord/lib/active_record/schema_dumper.rb, line 30 30: def initialize(connection) 31: @connection = connection 32: @types = @connection.native_database_types 33: @info = @connection.select_one("SELECT * FROM schema_info") rescue nil 34: end
Public Instance Methods
dump (stream)
# File vendor/rails/activerecord/lib/active_record/schema_dumper.rb, line 21 21: def dump(stream) 22: header(stream) 23: tables(stream) 24: trailer(stream) 25: stream 26: end
Private Instance Methods
default_string (value)
# File vendor/rails/activerecord/lib/active_record/schema_dumper.rb, line 151 151: def default_string(value) 152: case value 153: when BigDecimal 154: value.to_s 155: when Date, DateTime, Time 156: "'" + value.to_s(:db) + "'" 157: else 158: value.inspect 159: end 160: end
header (stream)
# File vendor/rails/activerecord/lib/active_record/schema_dumper.rb, line 36 36: def header(stream) 37: define_params = @info ? ":version => #{@info['version']}" : "" 38: 39: stream.puts "# This file is auto-generated from the current state of the database. Instead of editing this file, \n# please use the migrations feature of ActiveRecord to incrementally modify your database, and\n# then regenerate this schema definition.\n#\n# Note that this schema.rb definition is the authoritative source for your database schema. If you need\n# to create the application database on another system, you should be using db:schema:load, not running\n# all the migrations from scratch. The latter is a flawed and unsustainable approach (the more migrations\n# you'll amass, the slower it'll run and the greater likelihood for issues).\n#\n# It's strongly recommended to check this file into your version control system.\n\nActiveRecord::Schema.define(\#{define_params}) do\n\n" 40: end
indexes (table, stream)
# File vendor/rails/activerecord/lib/active_record/schema_dumper.rb, line 162 162: def indexes(table, stream) 163: indexes = @connection.indexes(table) 164: indexes.each do |index| 165: stream.print " add_index #{index.table.inspect}, #{index.columns.inspect}, :name => #{index.name.inspect}" 166: stream.print ", :unique => true" if index.unique 167: stream.puts 168: end 169: stream.puts unless indexes.empty? 170: end
table (table, stream)
# File vendor/rails/activerecord/lib/active_record/schema_dumper.rb, line 75 75: def table(table, stream) 76: columns = @connection.columns(table) 77: begin 78: tbl = StringIO.new 79: 80: if @connection.respond_to?(:pk_and_sequence_for) 81: pk, pk_seq = @connection.pk_and_sequence_for(table) 82: end 83: pk ||= 'id' 84: 85: tbl.print " create_table #{table.inspect}" 86: if columns.detect { |c| c.name == pk } 87: if pk != 'id' 88: tbl.print %Q(, :primary_key => "#{pk}") 89: end 90: else 91: tbl.print ", :id => false" 92: end 93: tbl.print ", :force => true" 94: tbl.puts " do |t|" 95: 96: column_specs = columns.map do |column| 97: raise StandardError, "Unknown type '#{column.sql_type}' for column '#{column.name}'" if @types[column.type].nil? 98: next if column.name == pk 99: spec = {} 100: spec[:name] = column.name.inspect 101: spec[:type] = column.type.to_s 102: spec[:limit] = column.limit.inspect if column.limit != @types[column.type][:limit] && column.type != :decimal 103: spec[:precision] = column.precision.inspect if !column.precision.nil? 104: spec[:scale] = column.scale.inspect if !column.scale.nil? 105: spec[:null] = 'false' if !column.null 106: spec[:default] = default_string(column.default) if !column.default.nil? 107: (spec.keys - [:name, :type]).each{ |k| spec[k].insert(0, "#{k.inspect} => ")} 108: spec 109: end.compact 110: 111: # find all migration keys used in this table 112: keys = [:name, :limit, :precision, :scale, :default, :null] & column_specs.map(&:keys).flatten 113: 114: # figure out the lengths for each column based on above keys 115: lengths = keys.map{ |key| column_specs.map{ |spec| spec[key] ? spec[key].length + 2 : 0 }.max } 116: 117: # the string we're going to sprintf our values against, with standardized column widths 118: format_string = lengths.map{ |len| "%-#{len}s" } 119: 120: # find the max length for the 'type' column, which is special 121: type_length = column_specs.map{ |column| column[:type].length }.max 122: 123: # add column type definition to our format string 124: format_string.unshift " t.%-#{type_length}s " 125: 126: format_string *= '' 127: 128: column_specs.each do |colspec| 129: values = keys.zip(lengths).map{ |key, len| colspec.key?(key) ? colspec[key] + ", " : " " * len } 130: values.unshift colspec[:type] 131: tbl.print((format_string % values).gsub(/,\s*$/, '')) 132: tbl.puts 133: end 134: 135: tbl.puts " end" 136: tbl.puts 137: 138: indexes(table, tbl) 139: 140: tbl.rewind 141: stream.print tbl.read 142: rescue => e 143: stream.puts "# Could not dump table #{table.inspect} because of following #{e.class}" 144: stream.puts "# #{e.message}" 145: stream.puts 146: end 147: 148: stream 149: end
tables (stream)
# File vendor/rails/activerecord/lib/active_record/schema_dumper.rb, line 61 61: def tables(stream) 62: @connection.tables.sort.each do |tbl| 63: next if ["schema_info", ignore_tables].flatten.any? do |ignored| 64: case ignored 65: when String; tbl == ignored 66: when Regexp; tbl =~ ignored 67: else 68: raise StandardError, 'ActiveRecord::SchemaDumper.ignore_tables accepts an array of String and / or Regexp values.' 69: end 70: end 71: table(tbl, stream) 72: end 73: end
trailer (stream)
# File vendor/rails/activerecord/lib/active_record/schema_dumper.rb, line 57 57: def trailer(stream) 58: stream.puts "end" 59: end