Module: DbSchema::Changes
- Defined in:
- lib/db_schema/changes.rb
Defined Under Namespace
Classes: AddValueToEnum, AllowNull, AlterColumnDefault, AlterColumnType, AlterTable, ColumnOperation, CreateCheckConstraint, CreateColumn, CreateEnum, CreateExtension, CreateForeignKey, CreateIndex, CreatePrimaryKey, CreateTable, DisallowNull, DropCheckConstraint, DropColumn, DropEnum, DropExtension, DropForeignKey, DropIndex, DropPrimaryKey, DropTable, RenameColumn
Class Method Summary collapse
Class Method Details
.between(desired_schema, actual_schema) ⇒ Object
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 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 |
# File 'lib/db_schema/changes.rb', line 7 def between(desired_schema, actual_schema) desired_tables = extract_tables(desired_schema) actual_tables = extract_tables(actual_schema) table_names = [desired_tables, actual_tables].flatten.map(&:name).uniq table_changes = table_names.each.with_object([]) do |table_name, changes| desired = desired_tables.find { |table| table.name == table_name } actual = actual_tables.find { |table| table.name == table_name } if desired && !actual changes << CreateTable.new( table_name, fields: desired.fields, indices: desired.indices, checks: desired.checks ) fkey_operations = desired.foreign_keys.map do |fkey| CreateForeignKey.new(table_name, fkey) end changes.concat(fkey_operations) elsif actual && !desired changes << DropTable.new(table_name) actual.foreign_keys.each do |fkey| changes << DropForeignKey.new(table_name, fkey.name) end elsif actual != desired field_operations = field_changes(desired.fields, actual.fields) index_operations = index_changes(desired.indices, actual.indices) check_operations = check_changes(desired.checks, actual.checks) fkey_operations = foreign_key_changes(table_name, desired.foreign_keys, actual.foreign_keys) if field_operations.any? || index_operations.any? || check_operations.any? changes << AlterTable.new( table_name, fields: field_operations, indices: index_operations, checks: check_operations ) end changes.concat(fkey_operations) end end desired_enums = extract_enums(desired_schema) actual_enums = extract_enums(actual_schema) enum_names = [desired_enums, actual_enums].flatten.map(&:name).uniq enum_changes = enum_names.each_with_object([]) do |enum_name, changes| desired = desired_enums.find { |enum| enum.name == enum_name } actual = actual_enums.find { |enum| enum.name == enum_name } if desired && !actual changes << CreateEnum.new(enum_name, desired.values) elsif actual && !desired changes << DropEnum.new(enum_name) elsif actual != desired new_values = desired.values - actual.values dropped_values = actual.values - desired.values if dropped_values.any? raise UnsupportedOperation, "Enum #{enum_name.inspect} doesn't describe values #{dropped_values.inspect} that are present in the database; dropping values from enums is not supported." end if desired.values - new_values != actual.values raise UnsupportedOperation, "Enum #{enum_name.inspect} describes values #{(desired.values - new_values).inspect} that are present in the database in a different order (#{actual.values.inspect}); reordering values in enums is not supported." end new_values.reverse.each do |value| value_index = desired.values.index(value) if value_index == desired.values.count - 1 changes << AddValueToEnum.new(enum_name, value) else next_value = desired.values[value_index + 1] changes << AddValueToEnum.new(enum_name, value, before: next_value) end end end end desired_extensions = extract_extensions(desired_schema) actual_extensions = extract_extensions(actual_schema) extension_changes = (desired_extensions - actual_extensions).map do |extension| CreateExtension.new(extension.name) end + (actual_extensions - desired_extensions).map do |extension| DropExtension.new(extension.name) end table_changes + enum_changes + extension_changes end |