Class: DynamicMigrations::Postgres::Generator::Migration
- Inherits:
-
Object
- Object
- DynamicMigrations::Postgres::Generator::Migration
- Defined in:
- lib/dynamic_migrations/postgres/generator/migration.rb
Direct Known Subclasses
Defined Under Namespace
Classes: DuplicateStructureTemplateError, MissingRequiredSchemaName, MissingRequiredTableName, NoFragmentsError, SectionNotFoundError, UnexpectedMigrationMethodNameError, UnexpectedSchemaError, UnexpectedTableError
Instance Attribute Summary collapse
-
#fragments ⇒ Object
readonly
Returns the value of attribute fragments.
-
#schema_name ⇒ Object
readonly
Returns the value of attribute schema_name.
-
#table_name ⇒ Object
readonly
Returns the value of attribute table_name.
Class Method Summary collapse
-
.add_structure_template(method_names, header) ⇒ Object
Defines a new section in the migration file, this is used to group migration fragments of the provided method names together under the provided header.
-
.clear_structure_templates ⇒ Object
return the list of structure templates for use in this migration.
-
.structure_templates ⇒ Object
return the list of structure templates for use in this migration.
Instance Method Summary collapse
-
#add_fragment(fragment) ⇒ Object
Add a migration fragment to this migration, if the migration is not configured (via a structure template) to handle the method_name of the fragment, then am error is raised.
-
#content ⇒ Object
Combine the fragments, and build a string representation of the migration using the structure templates defined in this class.
-
#enum_dependencies ⇒ Object
Return an array of enum dependencies for this migration, this array comes from combining any enum dependencies from each fragment.
-
#extract_fragments_with_table_dependency(schema_name, table_name) ⇒ Object
removes and returns any fragments which have a dependency on the table with the provided schema_name and table_name, this is used for extracting fragments which cause circular dependencies so they can be placed into their own migrations.
-
#fragments_with_table_dependency_count(schema_name, table_name) ⇒ Object
returns the number of fragment within this migration which have the provided dependency.
-
#function_dependencies ⇒ Object
Return an array of function dependencies for this migration, this array comes from combining any function dependencies from each fragment.
-
#initialize(schema_name = nil, table_name = nil) ⇒ Migration
constructor
schema_name and table_name can be nil.
-
#name ⇒ Object
Using the migration fragments, generate a friendly/descriptive name for the migration.
-
#table_dependencies ⇒ Object
Return an array of table dependencies for this migration, this array comes from combining any table dependencies from each fragment.
- #to_s ⇒ Object
Constructor Details
#initialize(schema_name = nil, table_name = nil) ⇒ Migration
schema_name and table_name can be nil
34 35 36 37 38 |
# File 'lib/dynamic_migrations/postgres/generator/migration.rb', line 34 def initialize schema_name = nil, table_name = nil @schema_name = schema_name @table_name = table_name @fragments = [] end |
Instance Attribute Details
#fragments ⇒ Object (readonly)
Returns the value of attribute fragments.
31 32 33 |
# File 'lib/dynamic_migrations/postgres/generator/migration.rb', line 31 def fragments @fragments end |
#schema_name ⇒ Object (readonly)
Returns the value of attribute schema_name.
30 31 32 |
# File 'lib/dynamic_migrations/postgres/generator/migration.rb', line 30 def schema_name @schema_name end |
#table_name ⇒ Object (readonly)
Returns the value of attribute table_name.
29 30 31 |
# File 'lib/dynamic_migrations/postgres/generator/migration.rb', line 29 def table_name @table_name end |
Class Method Details
.add_structure_template(method_names, header) ⇒ Object
Defines a new section in the migration file, this is used to group migration fragments of the provided method names together under the provided header
43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 |
# File 'lib/dynamic_migrations/postgres/generator/migration.rb', line 43 def self.add_structure_template method_names, header @structure_templates ||= [] if (@structure_templates.map { |s| s[:methods] }.flatten & method_names).any? raise DuplicateStructureTemplateError, "Duplicate structure template for methods `#{method_names}`" end @structure_templates << { methods: method_names, header_comment: <<~COMMENT.strip # # #{header.strip} # COMMENT } end |
.clear_structure_templates ⇒ Object
return the list of structure templates for use in this migration
66 67 68 |
# File 'lib/dynamic_migrations/postgres/generator/migration.rb', line 66 def self.clear_structure_templates @structure_templates = [] end |
.structure_templates ⇒ Object
return the list of structure templates for use in this migration
61 62 63 |
# File 'lib/dynamic_migrations/postgres/generator/migration.rb', line 61 def self.structure_templates @structure_templates || [] end |
Instance Method Details
#add_fragment(fragment) ⇒ Object
Add a migration fragment to this migration, if the migration is not configured (via a structure template) to handle the method_name of the fragment, then am error is raised. An error will also be raised if the migration belongs to a different schema than the provided fragment.
107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 |
# File 'lib/dynamic_migrations/postgres/generator/migration.rb', line 107 def add_fragment fragment unless supported_migration_method? fragment.migration_method raise UnexpectedMigrationMethodNameError, "Expected method to be a valid migrator method, got `#{fragment.migration_method}`" end # confirm the fragment is for this schema (even if both # these values are nil/there is no schema) unless @schema_name == fragment.schema_name raise UnexpectedSchemaError, "Fragment is for schema `#{fragment.schema_name || "nil"}` but migration is for schema `#{@schema_name || "nil"}`" end # confirm this fragment is for this table, this works for database and schame # migrations to, as all values should be nil unless @table_name == fragment.table_name raise UnexpectedTableError, "Fragment is for table `#{fragment.table_name || "nil"}` but migration is for table `#{@table_name || "nil"}`" end @fragments << fragment fragment end |
#content ⇒ Object
Combine the fragments, and build a string representation of the migration using the structure templates defined in this class. Will raise an error if no fragments have been provided.
172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 |
# File 'lib/dynamic_migrations/postgres/generator/migration.rb', line 172 def content raise NoFragmentsError if fragments.empty? sections = [] self.class.structure_templates.each do |section| # add the header comment if we have a migration which matches one of the # methods in this section if (section[:methods] & @fragments.map(&:migration_method)).any? sections << section[:header_comment].strip end # iterate through this sections methods in order and look # for any that match the migrations we have section[:methods].each do |migration_method| # if we have any migration fragments for this method then add them @fragments.filter { |f| f.migration_method == migration_method }.each do |fragment| sections << fragment.to_s sections << "" end end end sections.join("\n").strip end |
#enum_dependencies ⇒ Object
Return an array of enum dependencies for this migration, this array comes from combining any enum dependencies from each fragment. Will raise an error if no fragments are available.
148 149 150 151 |
# File 'lib/dynamic_migrations/postgres/generator/migration.rb', line 148 def enum_dependencies raise NoFragmentsError if fragments.empty? @fragments.map(&:enum_dependency).compact.uniq end |
#extract_fragments_with_table_dependency(schema_name, table_name) ⇒ Object
removes and returns any fragments which have a dependency on the table with the provided schema_name and table_name, this is used for extracting fragments which cause circular dependencies so they can be placed into their own migrations
161 162 163 164 165 166 167 |
# File 'lib/dynamic_migrations/postgres/generator/migration.rb', line 161 def extract_fragments_with_table_dependency schema_name, table_name results = @fragments.filter { |f| f.is_dependent_on_table? schema_name, table_name } # remove any of these from the internal array of fragments @fragments.filter! { |f| !f.is_dependent_on_table?(schema_name, table_name) } # return the results results end |
#fragments_with_table_dependency_count(schema_name, table_name) ⇒ Object
returns the number of fragment within this migration which have the provided dependency
154 155 156 |
# File 'lib/dynamic_migrations/postgres/generator/migration.rb', line 154 def fragments_with_table_dependency_count schema_name, table_name @fragments.count { |f| f.is_dependent_on_table? schema_name, table_name } end |
#function_dependencies ⇒ Object
Return an array of function dependencies for this migration, this array comes from combining any function dependencies from each fragment. Will raise an error if no fragments are available.
140 141 142 143 |
# File 'lib/dynamic_migrations/postgres/generator/migration.rb', line 140 def function_dependencies raise NoFragmentsError if fragments.empty? @fragments.map(&:function_dependency).compact.uniq end |
#name ⇒ Object
Using the migration fragments, generate a friendly/descriptive name for the migration. Will raise an error if no fragments have been provided.
197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 |
# File 'lib/dynamic_migrations/postgres/generator/migration.rb', line 197 def name raise NoFragmentsError if fragments.empty? if fragments_for_method? :create_schema :"create_#{fragments.first&.object_name}_schema" elsif fragments_for_method? :drop_schema :"drop_#{fragments.first&.object_name}_schema" elsif fragments_for_method? :create_table :"create_#{first_fragment_using_migration_method(:create_table).table_name}" elsif fragments_for_method? :drop_table :"drop_#{first_fragment_using_migration_method(:drop_table).table_name}" elsif all_fragments_for_method? [:create_function] :"create_function_#{@fragments.find { |s| s.migration_method == :create_function }&.object_name}" elsif all_fragments_for_method? [:create_function, :update_function, :drop_function, :set_function_comment, :remove_function_comment] :schema_functions elsif all_fragments_for_method? [:create_enum, :add_enum_values, :drop_enum, :set_enum_comment, :remove_enum_comment] :enums elsif all_fragments_for_method? [:enable_extension] (@fragments.count > 1) ? :enable_extensions : :"enable_#{fragments.first&.object_name}_extension" elsif all_fragments_for_method? [:disable_extension] (@fragments.count > 1) ? :disable_extensions : :"disable_#{fragments.first&.object_name}_extension" elsif @fragments.first&.table_name :"changes_for_#{@fragments.first&.table_name}" else :changes end end |
#table_dependencies ⇒ Object
Return an array of table dependencies for this migration, this array comes from combining any table dependencies from each fragment. Will raise an error if no fragments are available.
132 133 134 135 |
# File 'lib/dynamic_migrations/postgres/generator/migration.rb', line 132 def table_dependencies raise NoFragmentsError if fragments.empty? @fragments.map(&:table_dependency).compact.uniq end |
#to_s ⇒ Object
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 |
# File 'lib/dynamic_migrations/postgres/generator/migration.rb', line 70 def to_s # because calling these methods will rise an error if there are no # fragments, and this method is primarily used for debugging if @fragments.any? tds = table_dependencies eds = enum_dependencies fds = function_dependencies else tds = [] eds = [] fds = [] end <<~PREVIEW.strip # Migration content preview # ------------------------- # Schema:#{@schema_name ? " #{@schema_name}" : ""} # Table:#{@table_name ? " #{@table_name}" : ""} # Table Dependencies (count: #{tds.count}): #{(tds.any? ? "# " : "") + tds.map { |d| "Schema: `#{d[:schema_name]}` Table: `#{d[:table_name]}`" }.join("\n# ")} # Enum Dependencies (count: #{eds.count}): #{(eds.any? ? "# " : "") + eds.map { |d| "Schema: `#{d[:schema_name]}` Enum: `#{d[:enum_name]}`" }.join("\n# ")} # Function Dependencies (count: #{fds.count}): #{(fds.any? ? "# " : "") + fds.map { |d| "Schema: `#{d[:schema_name]}` Function: `#{d[:function_name]}`" }.join("\n# ")} # Fragments (count: #{@fragments.count}): #{@fragments.map(&:to_s).join("\n\n")} PREVIEW end |