Module: Reins::Schema

Included in:
Model::Base
Defined in:
lib/reins/schema.rb

Constant Summary collapse

SKIP_TABLES =
%w[sqlite_sequence schema_migrations].freeze

Class Method Summary collapse

Class Method Details

.current_versionObject



51
52
53
54
55
56
57
58
59
60
# File 'lib/reins/schema.rb', line 51

def self.current_version
  row = Reins::Database.connection.execute(
    "SELECT MAX(version) AS v FROM schema_migrations"
  ).first
  return nil if row.nil?

  row.is_a?(Hash) ? row["v"] : row[0]
rescue StandardError
  nil
end

.define(version: nil, &block) ⇒ Object



7
8
9
10
11
12
# File 'lib/reins/schema.rb', line 7

def self.define(version: nil, &block)
  klass = Class.new(Reins::Migration)
  klass.define_method(:change, &block) if block
  klass.new.run_up
  record_version(version) if version
end

.dump(path: "db/schema.rb") ⇒ Object



14
15
16
17
# File 'lib/reins/schema.rb', line 14

def self.dump(path: "db/schema.rb")
  FileUtils.mkdir_p(File.dirname(path))
  File.write(path, dump_string)
end

.dump_stringObject



19
20
21
22
23
24
25
26
27
28
29
30
# File 'lib/reins/schema.rb', line 19

def self.dump_string
  tables = list_tables.reject { |t| SKIP_TABLES.include?(t) }
  version = current_version
  lines = []
  lines << "Reins::Schema.define(#{"version: #{version.to_s.inspect}" if version}) do"
  tables.each do |table|
    lines.concat(table_definition_lines(table))
    lines << ""
  end
  lines << "end"
  "#{lines.join("\n")}\n"
end

.list_columns(table) ⇒ Object



38
39
40
# File 'lib/reins/schema.rb', line 38

def self.list_columns(table)
  Reins::Database.connection.execute("PRAGMA table_info(#{table})")
end

.list_tablesObject



32
33
34
35
36
# File 'lib/reins/schema.rb', line 32

def self.list_tables
  Reins::Database.connection
                 .execute("SELECT name FROM sqlite_master WHERE type='table' ORDER BY name")
                 .map { |row| row.is_a?(Hash) ? row["name"] : row[0] }
end

.record_version(version) ⇒ Object



42
43
44
45
46
47
48
49
# File 'lib/reins/schema.rb', line 42

def self.record_version(version)
  Reins::Database.connection.execute(
    "CREATE TABLE IF NOT EXISTS schema_migrations (version VARCHAR PRIMARY KEY)"
  )
  Reins::Database.connection.execute(
    "INSERT OR IGNORE INTO schema_migrations (version) VALUES (?)", [version.to_s]
  )
end

.sql_type_to_dsl(type) ⇒ Object



76
77
78
79
80
81
82
83
84
85
# File 'lib/reins/schema.rb', line 76

def self.sql_type_to_dsl(type)
  case type.to_s.upcase
  when /TEXT/ then :text
  when /INT/ then :integer
  when /FLOAT/, /REAL/, /NUMERIC/ then :float
  when /BOOL/ then :boolean
  when /DATETIME/ then :datetime
  else :string # VARCHAR, CHAR, and any unknown type
  end
end

.table_definition_lines(table) ⇒ Object



62
63
64
65
66
67
68
69
70
71
72
73
74
# File 'lib/reins/schema.rb', line 62

def self.table_definition_lines(table)
  cols = list_columns(table)
  lines = ["  create_table \"#{table}\" do |t|"]
  cols.each do |row|
    name = row.is_a?(Hash) ? row["name"] : row[1]
    type = row.is_a?(Hash) ? row["type"] : row[2]
    next if name == "id"

    lines << "    t.#{sql_type_to_dsl(type)} \"#{name}\""
  end
  lines << "  end"
  lines
end