aboutsummaryrefslogtreecommitdiffstats
path: root/activerecord/lib/active_record/schema_dumper.rb
blob: ec5e2f12d52435bc17e0f4fb17dd30164c402b86 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
module ActiveRecord
  # This class is used to dump the database schema for some connection to some
  # output format (i.e., ActiveRecord::Schema).
  class SchemaDumper
    private_class_method :new

    def self.dump(connection=ActiveRecord::Base.connection, stream=STDOUT)
      new(connection).dump(stream)
      stream
    end

    def dump(stream)
      header(stream)
      tables(stream)
      trailer(stream)
      stream
    end

    private

      def initialize(connection)
        @connection = connection
        @types = @connection.native_database_types
        @info = @connection.select_one("SELECT * FROM schema_info") rescue nil
      end

      def header(stream)
        define_params = @info ? ":version => #{@info['version']}" : ""

        stream.puts <<HEADER
# This file is autogenerated. Instead of editing this file, please use the
# migrations feature of ActiveRecord to incrementally modify your database, and
# then regenerate this schema definition.

ActiveRecord::Schema.define(#{define_params}) do
HEADER
      end

      def trailer(stream)
        stream.puts "end"
      end

      def tables(stream)
        @connection.tables.sort.each do |tbl|
          next if tbl == "schema_info"
          table(tbl, stream)
        end
      end

      def table(table, stream)
        columns = @connection.columns(table)

        stream.print "  create_table #{table.inspect}"
        stream.print ", :id => false" if !columns.detect { |c| c.name == "id" }
        stream.puts " do |t|"

        columns.each do |column|
          next if column.name == "id"
          stream.print "    t.column #{column.name.inspect}, #{column.type.inspect}"
          stream.print ", :limit => #{column.limit.inspect}" if column.limit != @types[column.type][:limit]
          stream.print ", :default => #{column.default.inspect}" if column.default
          stream.print ", :null => false" if !column.null
          stream.puts
        end

        stream.puts "  end"
        stream.puts

        indexes(table, stream)
      end

      def indexes(table, stream)
        indexes = @connection.indexes(table)
        indexes.each do |index|
          stream.print "  add_index #{index.table.inspect}, #{index.columns.inspect}, :name => #{index.name.inspect}"
          stream.print ", :unique => true" if index.unique
          stream.puts
        end
        stream.puts unless indexes.empty?
      end
  end
end