declare_schema 2.1.0 → 2.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +11 -0
- data/Gemfile.lock +2 -4
- data/lib/declare_schema/model/index_definition.rb +5 -5
- data/lib/declare_schema/model.rb +6 -6
- data/lib/declare_schema/version.rb +1 -1
- data/lib/generators/declare_schema/migration/migrator.rb +24 -14
- data/spec/fixtures/migrations/sqlite3/will_generate_unique_constraint_names_rails_6.txt +0 -2
- data/spec/lib/declare_schema/migration_generator_spec.rb +89 -38
- data/spec/lib/declare_schema/model/index_definition_spec.rb +3 -9
- data/spec/lib/generators/declare_schema/migration/migrator_spec.rb +2 -2
- metadata +3 -3
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA256:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: 9e92a56ac2a51694dbdea156f3ac05dc7336f524b13fb46351bc186494935d4e
         | 
| 4 | 
            +
              data.tar.gz: 50c34eb09ef428f685ad487de9f98b11751c6b2c1d2ff68e51af2ebae51fb6da
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: '079ba4d0d7bdfa362c6bcfa7fc7a6b0db10dee0684b787fc93cf56cbda2909e238e968ab610673563f8159961345b9e2e0565ff82b69105242346f4c4e8d196e'
         | 
| 7 | 
            +
              data.tar.gz: 3a8f164861f95287252fcedf22ff045e692043764ba1701b12e1c2c25db46612af1c273aded8c1e23823aaa3d3123d40e46a3813a7ca75032ced5d409a023a4c
         | 
    
        data/CHANGELOG.md
    CHANGED
    
    | @@ -4,6 +4,17 @@ Inspired by [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). | |
| 4 4 |  | 
| 5 5 | 
             
            Note: this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
         | 
| 6 6 |  | 
| 7 | 
            +
            ## [2.2.1] - 2024-10-11
         | 
| 8 | 
            +
            ### Changed
         | 
| 9 | 
            +
            - Re-release after yanking 2.2.0
         | 
| 10 | 
            +
             | 
| 11 | 
            +
            ## [2.2.0] - 2024-10-09
         | 
| 12 | 
            +
            ### Changed
         | 
| 13 | 
            +
            - Drop/add index if its settings change (`unique:`, `length:`, etc.)
         | 
| 14 | 
            +
            - Drop/add index if order of columns changes
         | 
| 15 | 
            +
            - Drop indexes before adding, in case any have identical names
         | 
| 16 | 
            +
            - Drop foreign keys before adding, in case any have identical names
         | 
| 17 | 
            +
             | 
| 7 18 | 
             
            ## [2.1.0] - 2024-08-20
         | 
| 8 19 | 
             
            ### Added
         | 
| 9 20 | 
             
            - Added support for Rails 7.2
         | 
    
        data/Gemfile.lock
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            PATH
         | 
| 2 2 | 
             
              remote: .
         | 
| 3 3 | 
             
              specs:
         | 
| 4 | 
            -
                declare_schema (2.1 | 
| 4 | 
            +
                declare_schema (2.2.1)
         | 
| 5 5 | 
             
                  rails (>= 6.0)
         | 
| 6 6 |  | 
| 7 7 | 
             
            GEM
         | 
| @@ -172,8 +172,7 @@ GEM | |
| 172 172 | 
             
                responders (3.1.1)
         | 
| 173 173 | 
             
                  actionpack (>= 5.2)
         | 
| 174 174 | 
             
                  railties (>= 5.2)
         | 
| 175 | 
            -
                rexml (3.3. | 
| 176 | 
            -
                  strscan
         | 
| 175 | 
            +
                rexml (3.3.8)
         | 
| 177 176 | 
             
                rspec (3.13.0)
         | 
| 178 177 | 
             
                  rspec-core (~> 3.13.0)
         | 
| 179 178 | 
             
                  rspec-expectations (~> 3.13.0)
         | 
| @@ -213,7 +212,6 @@ GEM | |
| 213 212 | 
             
                  sprockets (>= 3.0.0)
         | 
| 214 213 | 
             
                sqlite3 (1.7.3)
         | 
| 215 214 | 
             
                  mini_portile2 (~> 2.8.0)
         | 
| 216 | 
            -
                strscan (3.1.0)
         | 
| 217 215 | 
             
                thor (1.3.1)
         | 
| 218 216 | 
             
                timeout (0.4.1)
         | 
| 219 217 | 
             
                tzinfo (2.0.6)
         | 
| @@ -8,7 +8,7 @@ module DeclareSchema | |
| 8 8 | 
             
                  include Comparable
         | 
| 9 9 |  | 
| 10 10 | 
             
                  OPTIONS = [:name, :unique, :where, :length].freeze
         | 
| 11 | 
            -
                  attr_reader :columns, : | 
| 11 | 
            +
                  attr_reader :columns, :allow_equivalent, :table_name, *OPTIONS
         | 
| 12 12 |  | 
| 13 13 | 
             
                  alias fields columns # TODO: change callers to use columns. -Colin
         | 
| 14 14 |  | 
| @@ -16,11 +16,11 @@ module DeclareSchema | |
| 16 16 |  | 
| 17 17 | 
             
                  PRIMARY_KEY_NAME = "PRIMARY"
         | 
| 18 18 |  | 
| 19 | 
            -
                  def initialize(columns, table_name:, name: nil, allow_equivalent:  | 
| 19 | 
            +
                  def initialize(columns, table_name:, name: nil, allow_equivalent: true, unique: false, where: nil, length: nil)
         | 
| 20 20 | 
             
                    @table_name = table_name
         | 
| 21 | 
            -
                    @name =  | 
| 21 | 
            +
                    @name = name&.to_s || self.class.default_index_name(table_name, columns)
         | 
| 22 22 | 
             
                    @columns = Array.wrap(columns).map(&:to_s)
         | 
| 23 | 
            -
                    @ | 
| 23 | 
            +
                    @allow_equivalent = allow_equivalent
         | 
| 24 24 | 
             
                    unique.in?([false, true]) or raise ArgumentError, "unique must be true or false: got #{unique.inspect}"
         | 
| 25 25 | 
             
                    if @name == PRIMARY_KEY_NAME
         | 
| 26 26 | 
             
                      unique or raise ArgumentError, "primary key index must be unique"
         | 
| @@ -165,7 +165,7 @@ module DeclareSchema | |
| 165 165 | 
             
                  end
         | 
| 166 166 |  | 
| 167 167 | 
             
                  def with_name(new_name)
         | 
| 168 | 
            -
                    self.class.new(@columns, name: new_name, table_name: @table_name, unique: @unique, allow_equivalent: @ | 
| 168 | 
            +
                    self.class.new(@columns, name: new_name, table_name: @table_name, unique: @unique, allow_equivalent: @allow_equivalent, where: @where, length: @length)
         | 
| 169 169 | 
             
                  end
         | 
| 170 170 |  | 
| 171 171 | 
             
                  alias eql? ==
         | 
    
        data/lib/declare_schema/model.rb
    CHANGED
    
    | @@ -49,7 +49,7 @@ module DeclareSchema | |
| 49 49 | 
             
                end
         | 
| 50 50 |  | 
| 51 51 | 
             
                module ClassMethods
         | 
| 52 | 
            -
                  def index(columns, name: nil, allow_equivalent: false, unique: false, where: nil, length: nil)
         | 
| 52 | 
            +
                  def index(columns, name: nil, allow_equivalent: true, ignore_equivalent_definitions: false, unique: false, where: nil, length: nil)
         | 
| 53 53 | 
             
                    index_definition = ::DeclareSchema::Model::IndexDefinition.new(
         | 
| 54 54 | 
             
                      columns,
         | 
| 55 55 | 
             
                      name: name, table_name: table_name, allow_equivalent: allow_equivalent, unique: unique, where: where, length: length
         | 
| @@ -59,9 +59,9 @@ module DeclareSchema | |
| 59 59 | 
             
                      if equivalent == index_definition
         | 
| 60 60 | 
             
                        # identical is always idempotent
         | 
| 61 61 | 
             
                      else
         | 
| 62 | 
            -
                        # equivalent is idempotent iff  | 
| 63 | 
            -
                         | 
| 64 | 
            -
                          raise ArgumentError, "equivalent index definition found (pass  | 
| 62 | 
            +
                        # equivalent is idempotent iff ignore_equivalent_definitions: true passed
         | 
| 63 | 
            +
                        ignore_equivalent_definitions or
         | 
| 64 | 
            +
                          raise ArgumentError, "equivalent index definition found (pass ignore_equivalent_definitions: true to ignore):\n" \
         | 
| 65 65 | 
             
                                               "#{index_definition.inspect}\n#{equivalent.inspect}"
         | 
| 66 66 | 
             
                      end
         | 
| 67 67 | 
             
                    else
         | 
| @@ -156,8 +156,8 @@ module DeclareSchema | |
| 156 156 | 
             
                                            end || false
         | 
| 157 157 | 
             
                    column_options[:default] = options.delete(:default) if options.has_key?(:default)
         | 
| 158 158 | 
             
                    if options.has_key?(:limit)
         | 
| 159 | 
            -
                      options.delete(:limit)
         | 
| 160 | 
            -
                      DeclareSchema.deprecator.warn("belongs_to #{name.inspect}, limit: is deprecated since it is now inferred")
         | 
| 159 | 
            +
                      limit = options.delete(:limit)
         | 
| 160 | 
            +
                      DeclareSchema.deprecator.warn("belongs_to #{name.inspect}, limit: #{limit} is deprecated since it is now inferred")
         | 
| 161 161 | 
             
                    end
         | 
| 162 162 |  | 
| 163 163 | 
             
                    # index: true means create an index on the foreign key
         | 
| @@ -285,10 +285,10 @@ module Generators | |
| 285 285 | 
             
                                            ColumnRename
         | 
| 286 286 | 
             
                                            ColumnChange
         | 
| 287 287 | 
             
                                              PrimaryKeyChange
         | 
| 288 | 
            -
                                               | 
| 289 | 
            -
                                                 | 
| 290 | 
            -
                                                 | 
| 291 | 
            -
                                               | 
| 288 | 
            +
                                              ForeignKeyRemove
         | 
| 289 | 
            +
                                                IndexRemove
         | 
| 290 | 
            +
                                                IndexAdd
         | 
| 291 | 
            +
                                              ForeignKeyAdd
         | 
| 292 292 | 
             
                                            ColumnRemove
         | 
| 293 293 | 
             
                                          TableRemove ]
         | 
| 294 294 |  | 
| @@ -437,12 +437,14 @@ module Generators | |
| 437 437 | 
             
                      new_table_name = model.table_name
         | 
| 438 438 | 
             
                      existing_indexes = ::DeclareSchema::Model::IndexDefinition.for_table(old_table_name || new_table_name, model.ignore_indexes, model.connection)
         | 
| 439 439 | 
             
                      model_indexes_with_equivalents = model.index_definitions_with_primary_key.to_a
         | 
| 440 | 
            -
                      model_indexes = model_indexes_with_equivalents.map do | | 
| 441 | 
            -
                        if  | 
| 442 | 
            -
                          if (existing = existing_indexes.find { | | 
| 443 | 
            -
             | 
| 440 | 
            +
                      model_indexes = model_indexes_with_equivalents.map do |index|
         | 
| 441 | 
            +
                        if index.allow_equivalent
         | 
| 442 | 
            +
                          if (existing = existing_indexes.find { |existing_index| index != existing_index && existing_index.equivalent?(index) }) &&
         | 
| 443 | 
            +
                              # TODO: push this logic into IndexDefinition so that it knows about column renames and includes the (renamed) columns in the settings it compares. -Colin
         | 
| 444 | 
            +
                              existing.columns.map { |col_name| to_rename[col_name] || col_name } == index.columns
         | 
| 445 | 
            +
                            index.with_name(existing.name)
         | 
| 444 446 | 
             
                          end
         | 
| 445 | 
            -
                        end ||  | 
| 447 | 
            +
                        end || index
         | 
| 446 448 | 
             
                      end
         | 
| 447 449 | 
             
                      existing_primary_keys, existing_indexes_without_primary_key = existing_indexes.partition { |i| i.primary_key? }
         | 
| 448 450 | 
             
                      defined_primary_keys, model_indexes_without_primary_key = model_indexes.partition { |i| i.primary_key? }
         | 
| @@ -464,7 +466,7 @@ module Generators | |
| 464 466 | 
             
                      indexes_to_drop = existing_indexes_without_primary_key - model_indexes_without_primary_key
         | 
| 465 467 | 
             
                      indexes_to_add = model_indexes_without_primary_key - existing_indexes_without_primary_key
         | 
| 466 468 |  | 
| 467 | 
            -
                      renamed_indexes_to_drop, renamed_indexes_to_add =  | 
| 469 | 
            +
                      renamed_indexes_to_drop, renamed_indexes_to_add = index_changes_solely_due_to_column_renames(indexes_to_drop, indexes_to_add, to_rename)
         | 
| 468 470 |  | 
| 469 471 | 
             
                      drop_indexes = (indexes_to_drop - renamed_indexes_to_drop).map do |i|
         | 
| 470 472 | 
             
                        ::DeclareSchema::SchemaChange::IndexRemove.new(new_table_name, i.columns, **i.options)
         | 
| @@ -478,17 +480,25 @@ module Generators | |
| 478 480 | 
             
                      [Array(change_primary_key) + drop_indexes + add_indexes]
         | 
| 479 481 | 
             
                    end
         | 
| 480 482 |  | 
| 481 | 
            -
                     | 
| 482 | 
            -
             | 
| 483 | 
            +
                    # @return [Array<Array<IndexDefinition>>] pair of arrays of indexes that changed solely due to column renames...not any settings changes.
         | 
| 484 | 
            +
                    # Note: if the column order changed, that is considered a change of settings--not solely a column rename--so it will not be returned
         | 
| 485 | 
            +
                    def index_changes_solely_due_to_column_renames(indexes_to_drop, indexes_to_add, to_rename)
         | 
| 486 | 
            +
                      renamed_indexes_to_drop = []
         | 
| 487 | 
            +
                      renamed_indexes_to_add = []
         | 
| 488 | 
            +
             | 
| 489 | 
            +
                      indexes_to_drop.each do |index_to_drop|
         | 
| 483 490 | 
             
                        renamed_columns = index_to_drop.columns.map do |column|
         | 
| 484 491 | 
             
                          to_rename.fetch(column, column)
         | 
| 485 | 
            -
                        end | 
| 492 | 
            +
                        end
         | 
| 486 493 |  | 
| 487 | 
            -
                        if (index_to_add = indexes_to_add.find { |index_to_add| renamed_columns == index_to_add.columns | 
| 494 | 
            +
                        if (index_to_add = indexes_to_add.find { |index_to_add| renamed_columns == index_to_add.columns }) &&
         | 
| 495 | 
            +
                            index_to_add.settings == index_to_drop.settings
         | 
| 488 496 | 
             
                          renamed_indexes_to_drop << index_to_drop
         | 
| 489 497 | 
             
                          renamed_indexes_to_add << index_to_add
         | 
| 490 498 | 
             
                        end
         | 
| 491 499 | 
             
                      end
         | 
| 500 | 
            +
             | 
| 501 | 
            +
                      [renamed_indexes_to_drop, renamed_indexes_to_add]
         | 
| 492 502 | 
             
                    end
         | 
| 493 503 |  | 
| 494 504 | 
             
                    def change_foreign_key_constraints(model, old_table_name, to_rename)
         | 
| @@ -9,7 +9,5 @@ create_table :affiliates, id: :bigint, options: "CHARACTER SET utf8mb4 COLLATE u | |
| 9 9 | 
             
              t.string  :name, limit: 250, null: true, charset: "utf8mb4", collation: "utf8mb4_bin"
         | 
| 10 10 | 
             
              t.integer :category_id, limit: 8, null: false
         | 
| 11 11 | 
             
            end
         | 
| 12 | 
            -
            add_index :advertisers, [:category_id], name: :index_advertisers_on_category_id
         | 
| 13 | 
            -
            add_index :affiliates, [:category_id], name: :index_affiliates_on_category_id
         | 
| 14 12 | 
             
            add_foreign_key :advertisers, :categories, column: :category_id, name: :index_advertisers_on_category_id
         | 
| 15 13 | 
             
            add_foreign_key :affiliates, :categories, column: :category_id, name: :index_affiliates_on_category_id
         | 
| @@ -365,7 +365,7 @@ RSpec.describe 'DeclareSchema Migration Generator' do | |
| 365 365 | 
             
                  )
         | 
| 366 366 |  | 
| 367 367 | 
             
                  Advert.field_specs.delete(:category_id)
         | 
| 368 | 
            -
                  Advert.index_definitions. | 
| 368 | 
            +
                  Advert.index_definitions.clear
         | 
| 369 369 |  | 
| 370 370 | 
             
                  # If you specify a custom foreign key, the migration generator observes that:
         | 
| 371 371 |  | 
| @@ -388,8 +388,8 @@ RSpec.describe 'DeclareSchema Migration Generator' do | |
| 388 388 | 
             
                  )
         | 
| 389 389 |  | 
| 390 390 | 
             
                  Advert.field_specs.delete(:c_id)
         | 
| 391 | 
            -
                  Advert.index_definitions. | 
| 392 | 
            -
                  Advert.constraint_definitions. | 
| 391 | 
            +
                  Advert.index_definitions.clear
         | 
| 392 | 
            +
                  Advert.constraint_definitions.clear
         | 
| 393 393 |  | 
| 394 394 | 
             
                  # You can avoid generating the index by specifying `index: false`
         | 
| 395 395 |  | 
| @@ -408,8 +408,8 @@ RSpec.describe 'DeclareSchema Migration Generator' do | |
| 408 408 | 
             
                  )
         | 
| 409 409 |  | 
| 410 410 | 
             
                  Advert.field_specs.delete(:category_id)
         | 
| 411 | 
            -
                  Advert.index_definitions. | 
| 412 | 
            -
                  Advert.constraint_definitions. | 
| 411 | 
            +
                  Advert.index_definitions.clear
         | 
| 412 | 
            +
                  Advert.constraint_definitions.clear
         | 
| 413 413 |  | 
| 414 414 | 
             
                  # You can specify the index name with index: 'name' [deprecated]
         | 
| 415 415 |  | 
| @@ -433,10 +433,10 @@ RSpec.describe 'DeclareSchema Migration Generator' do | |
| 433 433 | 
             
                  )
         | 
| 434 434 |  | 
| 435 435 | 
             
                  Advert.field_specs.delete(:category_id)
         | 
| 436 | 
            -
                  Advert.index_definitions. | 
| 437 | 
            -
                  Advert.constraint_definitions. | 
| 436 | 
            +
                  Advert.index_definitions.clear
         | 
| 437 | 
            +
                  Advert.constraint_definitions.clear
         | 
| 438 438 |  | 
| 439 | 
            -
                  # You can specify the index name with index: { name:  | 
| 439 | 
            +
                  # You can specify the index name with index: { name: 'name', unique: true|false }
         | 
| 440 440 |  | 
| 441 441 | 
             
                  class Category < ActiveRecord::Base; end # rubocop:disable Lint/ConstantDefinitionInBlock
         | 
| 442 442 |  | 
| @@ -454,8 +454,8 @@ RSpec.describe 'DeclareSchema Migration Generator' do | |
| 454 454 | 
             
                  )
         | 
| 455 455 |  | 
| 456 456 | 
             
                  Advert.field_specs.delete(:category_id)
         | 
| 457 | 
            -
                  Advert.index_definitions. | 
| 458 | 
            -
                  Advert.constraint_definitions. | 
| 457 | 
            +
                  Advert.index_definitions.clear
         | 
| 458 | 
            +
                  Advert.constraint_definitions.clear
         | 
| 459 459 |  | 
| 460 460 | 
             
                  ### Timestamps and Optimimistic Locking
         | 
| 461 461 |  | 
| @@ -515,8 +515,8 @@ RSpec.describe 'DeclareSchema Migration Generator' do | |
| 515 515 | 
             
                  )
         | 
| 516 516 |  | 
| 517 517 | 
             
                  Advert.field_specs.delete(:category_id)
         | 
| 518 | 
            -
                  Advert.index_definitions. | 
| 519 | 
            -
                  Advert.constraint_definitions. | 
| 518 | 
            +
                  Advert.index_definitions.clear
         | 
| 519 | 
            +
                  Advert.constraint_definitions.clear
         | 
| 520 520 |  | 
| 521 521 | 
             
                  # You can ask for a unique index (deprecated syntax; use index: { unique: true } instead).
         | 
| 522 522 |  | 
| @@ -533,7 +533,7 @@ RSpec.describe 'DeclareSchema Migration Generator' do | |
| 533 533 | 
             
                    EOS
         | 
| 534 534 | 
             
                  )
         | 
| 535 535 |  | 
| 536 | 
            -
                  Advert.index_definitions. | 
| 536 | 
            +
                  Advert.index_definitions.clear
         | 
| 537 537 |  | 
| 538 538 | 
             
                  # You can specify the name for the index
         | 
| 539 539 |  | 
| @@ -550,7 +550,7 @@ RSpec.describe 'DeclareSchema Migration Generator' do | |
| 550 550 | 
             
                    EOS
         | 
| 551 551 | 
             
                  )
         | 
| 552 552 |  | 
| 553 | 
            -
                  Advert.index_definitions. | 
| 553 | 
            +
                  Advert.index_definitions.clear
         | 
| 554 554 |  | 
| 555 555 | 
             
                  # You can ask for an index outside of the fields block
         | 
| 556 556 |  | 
| @@ -568,37 +568,91 @@ RSpec.describe 'DeclareSchema Migration Generator' do | |
| 568 568 | 
             
                    EOS
         | 
| 569 569 | 
             
                  )
         | 
| 570 570 |  | 
| 571 | 
            -
                  Advert.index_definitions. | 
| 571 | 
            +
                  Advert.index_definitions.clear
         | 
| 572 572 |  | 
| 573 | 
            -
                  # The available options for the index function are :unique, :name, :where, and :length.
         | 
| 573 | 
            +
                  # The available options for the index function are :unique, :name, :where, and :length (as well as :allow_equivalent, :ignore_equivalent_definitions).
         | 
| 574 574 |  | 
| 575 575 | 
             
                  class Advert < ActiveRecord::Base # rubocop:disable Lint/ConstantDefinitionInBlock
         | 
| 576 576 | 
             
                    index :title, unique: false, name: 'my_index', length: 10
         | 
| 577 577 | 
             
                  end
         | 
| 578 578 |  | 
| 579 | 
            -
                   | 
| 579 | 
            +
                  up, down = Generators::DeclareSchema::Migration::Migrator.run
         | 
| 580 | 
            +
                  expect([up, down]).to(
         | 
| 580 581 | 
             
                    migrate_up(<<~EOS.strip)
         | 
| 581 582 | 
             
                      add_column :adverts, :title, :string, limit: 250, null: true#{charset_and_collation}
         | 
| 582 583 | 
             
                      add_index :adverts, [:title], name: :my_index, length: { title: 10 }
         | 
| 583 584 | 
             
                    EOS
         | 
| 584 585 | 
             
                  )
         | 
| 585 586 |  | 
| 586 | 
            -
                  Advert.index_definitions. | 
| 587 | 
            +
                  Advert.index_definitions.clear
         | 
| 588 | 
            +
             | 
| 589 | 
            +
                  ActiveRecord::Migration.class_eval(up)
         | 
| 590 | 
            +
             | 
| 591 | 
            +
                  # You can migrate an index to have slightly different settings
         | 
| 592 | 
            +
             | 
| 593 | 
            +
                  class Advert < ActiveRecord::Base # rubocop:disable Lint/ConstantDefinitionInBlock
         | 
| 594 | 
            +
                    declare_schema do
         | 
| 595 | 
            +
                      string :title, limit: 250, null: true, index: { unique: true, name: 'my_index', length: 5 }
         | 
| 596 | 
            +
                    end
         | 
| 597 | 
            +
                  end
         | 
| 598 | 
            +
             | 
| 599 | 
            +
                  # Note: the index is removed first, then re-added so that we don't get an error about the index already existing.
         | 
| 600 | 
            +
                  expect(Generators::DeclareSchema::Migration::Migrator.run).to(
         | 
| 601 | 
            +
                    migrate_up(<<~EOS.strip)
         | 
| 602 | 
            +
                      remove_index :adverts, name: :my_index
         | 
| 603 | 
            +
                      add_index :adverts, [:title], name: :my_index, unique: true, length: { title: 5 }
         | 
| 604 | 
            +
                    EOS
         | 
| 605 | 
            +
                  )
         | 
| 606 | 
            +
             | 
| 607 | 
            +
                  ActiveRecord::Migration.class_eval(down)
         | 
| 608 | 
            +
                  Advert.index_definitions.clear
         | 
| 587 609 |  | 
| 588 610 | 
             
                  # You can create an index on more than one field
         | 
| 589 611 |  | 
| 590 612 | 
             
                  class Advert < ActiveRecord::Base # rubocop:disable Lint/ConstantDefinitionInBlock
         | 
| 613 | 
            +
                    declare_schema do
         | 
| 614 | 
            +
                      string :title, limit: 250, null: true, index: { unique: true, name: 'my_index' }
         | 
| 615 | 
            +
                      integer :category_id, limit: 8
         | 
| 616 | 
            +
                    end
         | 
| 591 617 | 
             
                    index [:title, :category_id]
         | 
| 592 618 | 
             
                  end
         | 
| 593 619 |  | 
| 594 | 
            -
                   | 
| 620 | 
            +
                  up, down = Generators::DeclareSchema::Migration::Migrator.run
         | 
| 621 | 
            +
                  expect([up, down]).to(
         | 
| 595 622 | 
             
                    migrate_up(<<~EOS.strip)
         | 
| 596 623 | 
             
                      add_column :adverts, :title, :string, limit: 250, null: true#{charset_and_collation}
         | 
| 624 | 
            +
                      add_column :adverts, :category_id, :integer, limit: 8, null: false
         | 
| 625 | 
            +
                      add_index :adverts, [:title], name: :my_index, unique: true
         | 
| 597 626 | 
             
                      add_index :adverts, [:title, :category_id], name: :index_adverts_on_title_and_category_id
         | 
| 598 627 | 
             
                    EOS
         | 
| 599 628 | 
             
                  )
         | 
| 600 629 |  | 
| 601 | 
            -
                   | 
| 630 | 
            +
                  ActiveRecord::Migration.class_eval(up)
         | 
| 631 | 
            +
             | 
| 632 | 
            +
                  Advert.connection.schema_cache.clear!
         | 
| 633 | 
            +
                  Advert.reset_column_information
         | 
| 634 | 
            +
                  Advert.index_definitions.clear
         | 
| 635 | 
            +
                  nuke_model_class(Advert)
         | 
| 636 | 
            +
             | 
| 637 | 
            +
                  # You can change the column order of an index
         | 
| 638 | 
            +
             | 
| 639 | 
            +
                  class Advert < ActiveRecord::Base # rubocop:disable Lint/ConstantDefinitionInBlock
         | 
| 640 | 
            +
                    declare_schema do
         | 
| 641 | 
            +
                      string :title, limit: 250, null: true, index: { unique: true, name: 'my_index' }
         | 
| 642 | 
            +
                      integer :category_id, limit: 8
         | 
| 643 | 
            +
                    end
         | 
| 644 | 
            +
                    index [:category_id, :title], name: :index_adverts_on_title_and_category_id
         | 
| 645 | 
            +
                  end
         | 
| 646 | 
            +
             | 
| 647 | 
            +
                  up, down = Generators::DeclareSchema::Migration::Migrator.run
         | 
| 648 | 
            +
                  puts "!!!!up: #{up}\n\ndown: #{down}\n"
         | 
| 649 | 
            +
                  expect(Generators::DeclareSchema::Migration::Migrator.run).to(
         | 
| 650 | 
            +
                    migrate_up(<<~EOS.strip)
         | 
| 651 | 
            +
                      remove_index :adverts, name: :index_adverts_on_title_and_category_id
         | 
| 652 | 
            +
                      add_index :adverts, [:category_id, :title], name: :index_adverts_on_title_and_category_id
         | 
| 653 | 
            +
                      remove_column :adverts, :name
         | 
| 654 | 
            +
                    EOS
         | 
| 655 | 
            +
                  )
         | 
| 602 656 |  | 
| 603 657 | 
             
                  # Finally, you can specify that the migration generator should completely ignore an
         | 
| 604 658 | 
             
                  # index by passing its name to ignore_index in the model.
         | 
| @@ -608,26 +662,28 @@ RSpec.describe 'DeclareSchema Migration Generator' do | |
| 608 662 |  | 
| 609 663 | 
             
                  # The migration generator respects the `set_table_name` declaration, although as before, we need to explicitly tell the generator that we want a rename rather than a create and a drop.
         | 
| 610 664 |  | 
| 665 | 
            +
                  Advert.connection.schema_cache.clear!
         | 
| 666 | 
            +
                  Advert.reset_column_information
         | 
| 667 | 
            +
                  Advert.index_definitions.clear
         | 
| 668 | 
            +
                  nuke_model_class(Advert)
         | 
| 669 | 
            +
             | 
| 611 670 | 
             
                  class Advert < ActiveRecord::Base # rubocop:disable Lint/ConstantDefinitionInBlock
         | 
| 612 | 
            -
                    self.table_name = "ads"
         | 
| 613 671 | 
             
                    declare_schema do
         | 
| 614 672 | 
             
                      string :title, limit: 250, null: true
         | 
| 615 673 | 
             
                      text :body, null: true
         | 
| 616 674 | 
             
                    end
         | 
| 617 675 | 
             
                  end
         | 
| 618 676 |  | 
| 619 | 
            -
                   | 
| 620 | 
            -
                   | 
| 677 | 
            +
                  up, _down = Generators::DeclareSchema::Migration::Migrator.run
         | 
| 678 | 
            +
                  ActiveRecord::Migration.class_eval(up)
         | 
| 679 | 
            +
             | 
| 680 | 
            +
                  Advert.table_name = "ads"
         | 
| 621 681 |  | 
| 622 682 | 
             
                  expect(Generators::DeclareSchema::Migration::Migrator.run(adverts: "ads")).to(
         | 
| 623 683 | 
             
                    migrate_up(<<~EOS.strip)
         | 
| 624 684 | 
             
                      rename_table :adverts, :ads
         | 
| 625 | 
            -
                      add_column :ads, :title, :string, limit: 250, null: true#{charset_and_collation}
         | 
| 626 | 
            -
                      add_column :ads, :body, :text#{', limit: 4294967295' if current_adapter == 'mysql2'}, null: true#{charset_and_collation}
         | 
| 627 685 | 
             
                    EOS
         | 
| 628 686 | 
             
                    .and(migrate_down(<<~EOS.strip))
         | 
| 629 | 
            -
                      remove_column :ads, :body
         | 
| 630 | 
            -
                      remove_column :ads, :title
         | 
| 631 687 | 
             
                      rename_table :ads, :adverts
         | 
| 632 688 | 
             
                    EOS
         | 
| 633 689 | 
             
                  )
         | 
| @@ -658,14 +714,8 @@ RSpec.describe 'DeclareSchema Migration Generator' do | |
| 658 714 | 
             
                  expect(Generators::DeclareSchema::Migration::Migrator.run(adverts: "advertisements")).to(
         | 
| 659 715 | 
             
                    migrate_up(<<~EOS.strip)
         | 
| 660 716 | 
             
                      rename_table :adverts, :advertisements
         | 
| 661 | 
            -
                      add_column :advertisements, :title, :string, limit: 250, null: true#{charset_and_collation}
         | 
| 662 | 
            -
                      add_column :advertisements, :body, :text#{', limit: 4294967295' if current_adapter == 'mysql2'}, null: true#{charset_and_collation}
         | 
| 663 | 
            -
                      remove_column :advertisements, :name
         | 
| 664 717 | 
             
                    EOS
         | 
| 665 718 | 
             
                    .and(migrate_down(<<~EOS.strip))
         | 
| 666 | 
            -
                      add_column :advertisements, :name, :string, limit: 250, null: true#{charset_and_collation}
         | 
| 667 | 
            -
                      remove_column :advertisements, :body
         | 
| 668 | 
            -
                      remove_column :advertisements, :title
         | 
| 669 719 | 
             
                      rename_table :advertisements, :adverts
         | 
| 670 720 | 
             
                    EOS
         | 
| 671 721 | 
             
                  )
         | 
| @@ -684,7 +734,8 @@ RSpec.describe 'DeclareSchema Migration Generator' do | |
| 684 734 | 
             
                    EOS
         | 
| 685 735 | 
             
                    .and(migrate_down(<<~EOS.strip))
         | 
| 686 736 | 
             
                      create_table "adverts"#{table_options}, force: :cascade do |t|
         | 
| 687 | 
            -
                        t.string " | 
| 737 | 
            +
                        t.string "title", limit: 250#{charset_and_collation}
         | 
| 738 | 
            +
                        t.text "body"#{text_limit}#{charset_and_collation}
         | 
| 688 739 | 
             
                      end
         | 
| 689 740 | 
             
                    EOS
         | 
| 690 741 | 
             
                  )
         | 
| @@ -728,7 +779,7 @@ RSpec.describe 'DeclareSchema Migration Generator' do | |
| 728 779 | 
             
                  Advert.field_specs.delete(:type)
         | 
| 729 780 | 
             
                  nuke_model_class(SuperFancyAdvert)
         | 
| 730 781 | 
             
                  nuke_model_class(FancyAdvert)
         | 
| 731 | 
            -
                  Advert.index_definitions. | 
| 782 | 
            +
                  Advert.index_definitions.clear
         | 
| 732 783 |  | 
| 733 784 | 
             
                  ## Coping with multiple changes
         | 
| 734 785 |  | 
| @@ -944,7 +995,7 @@ RSpec.describe 'DeclareSchema Migration Generator' do | |
| 944 995 | 
             
                  end
         | 
| 945 996 |  | 
| 946 997 | 
             
                  it 'will generate unique constraint names' do
         | 
| 947 | 
            -
                    expect(Generators::DeclareSchema::Migration::Migrator.run).to(migrate_up(File.read(File.expand_path(fixture_file_path, __dir__)).chomp))
         | 
| 998 | 
            +
                    expect(Generators::DeclareSchema::Migration::Migrator.run).to(migrate_up(File.read(File.expand_path(fixture_file_path, __dir__)).chomp), fixture_file_path)
         | 
| 948 999 |  | 
| 949 1000 | 
             
                    migrate
         | 
| 950 1001 |  | 
| @@ -1223,7 +1274,7 @@ RSpec.describe 'DeclareSchema Migration Generator' do | |
| 1223 1274 | 
             
                      end
         | 
| 1224 1275 |  | 
| 1225 1276 | 
             
                      it 'deprecates limit:' do
         | 
| 1226 | 
            -
                        expect(DeclareSchema.deprecator).to receive(:warn).with("belongs_to :ad_category, limit: is deprecated since it is now inferred")
         | 
| 1277 | 
            +
                        expect(DeclareSchema.deprecator).to receive(:warn).with("belongs_to :ad_category, limit: 4 is deprecated since it is now inferred")
         | 
| 1227 1278 | 
             
                        eval <<~EOS # rubocop:disable Style/EvalWithLocation
         | 
| 1228 1279 | 
             
                          class UsingLimit < ActiveRecord::Base
         | 
| 1229 1280 | 
             
                            declare_schema { }
         | 
| @@ -1493,7 +1544,7 @@ RSpec.describe 'DeclareSchema Migration Generator' do | |
| 1493 1544 |  | 
| 1494 1545 | 
             
                  it "when equivalent and marked to allow, it is idempotent and doesn't raise" do
         | 
| 1495 1546 | 
             
                    expect do
         | 
| 1496 | 
            -
                      Advert.index [:ad_category_id], name: :on_ad_category_id,  | 
| 1547 | 
            +
                      Advert.index [:ad_category_id], name: :on_ad_category_id, ignore_equivalent_definitions: true
         | 
| 1497 1548 | 
             
                    end.to_not change { Advert.index_definitions.size }
         | 
| 1498 1549 | 
             
                  end
         | 
| 1499 1550 |  | 
| @@ -56,19 +56,13 @@ RSpec.describe DeclareSchema::Model::IndexDefinition do | |
| 56 56 | 
             
                      it { is_expected.to eq(fields) }
         | 
| 57 57 | 
             
                    end
         | 
| 58 58 |  | 
| 59 | 
            -
                    describe '# | 
| 60 | 
            -
                      subject { instance. | 
| 59 | 
            +
                    describe '#allow_equivalent' do
         | 
| 60 | 
            +
                      subject { instance.allow_equivalent }
         | 
| 61 61 |  | 
| 62 62 | 
             
                      context 'with allow_equivalent' do
         | 
| 63 63 | 
             
                        let(:options) { { table_name: table_name, allow_equivalent: true } }
         | 
| 64 64 |  | 
| 65 | 
            -
                        it { is_expected.to eq( | 
| 66 | 
            -
                      end
         | 
| 67 | 
            -
             | 
| 68 | 
            -
                      context 'with name option' do
         | 
| 69 | 
            -
                        let(:options) { { table_name: table_name, name: 'index_auth_users_on_names' } }
         | 
| 70 | 
            -
             | 
| 71 | 
            -
                        it { is_expected.to eq('index_auth_users_on_names') }
         | 
| 65 | 
            +
                        it { is_expected.to eq(true) }
         | 
| 72 66 | 
             
                      end
         | 
| 73 67 | 
             
                    end
         | 
| 74 68 |  | 
    
        metadata
    CHANGED
    
    | @@ -1,14 +1,14 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification
         | 
| 2 2 | 
             
            name: declare_schema
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            -
              version: 2.1 | 
| 4 | 
            +
              version: 2.2.1
         | 
| 5 5 | 
             
            platform: ruby
         | 
| 6 6 | 
             
            authors:
         | 
| 7 7 | 
             
            - Invoca Development adapted from hobo_fields by Tom Locke
         | 
| 8 8 | 
             
            autorequire:
         | 
| 9 9 | 
             
            bindir: bin
         | 
| 10 10 | 
             
            cert_chain: []
         | 
| 11 | 
            -
            date: 2024- | 
| 11 | 
            +
            date: 2024-10-11 00:00:00.000000000 Z
         | 
| 12 12 | 
             
            dependencies:
         | 
| 13 13 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 14 14 | 
             
              name: rails
         | 
| @@ -158,7 +158,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement | |
| 158 158 | 
             
                - !ruby/object:Gem::Version
         | 
| 159 159 | 
             
                  version: 1.3.6
         | 
| 160 160 | 
             
            requirements: []
         | 
| 161 | 
            -
            rubygems_version: 3.4. | 
| 161 | 
            +
            rubygems_version: 3.4.10
         | 
| 162 162 | 
             
            signing_key:
         | 
| 163 163 | 
             
            specification_version: 4
         | 
| 164 164 | 
             
            summary: Database schema declaration and migration generator for Rails
         |