Class: DeclareSchema::Model::IndexDefinition
- Inherits:
-
Object
- Object
- DeclareSchema::Model::IndexDefinition
- Includes:
- Comparable
- Defined in:
- lib/declare_schema/model/index_definition.rb
Defined Under Namespace
Classes: IndexNameTooLongError
Constant Summary collapse
- OPTIONS =
[:name, :unique, :where, :length].freeze
- PRIMARY_KEY_NAME =
"PRIMARY"
Class Method Summary collapse
- .default_index_name(table_name, columns) ⇒ Object
-
.for_table(table_name, ignore_indexes, connection) ⇒ Object
extract IndexSpecs from an existing table includes the PRIMARY KEY index.
-
.normalize_index_length(length, columns:) ⇒ Hash<Symbol, nil>
This method normalizes the length option to be either nil or a Hash of Symbol column names to lengths, so that we can safely compare what the user specified with what we get when querying the database schema.
Instance Method Summary collapse
- #<=>(rhs) ⇒ Object
- #equivalent?(rhs) ⇒ Boolean
- #hash ⇒ Object
-
#initialize(columns, table_name:, name: nil, allow_equivalent: false, unique: false, where: nil, length: nil) ⇒ IndexDefinition
constructor
A new instance of IndexDefinition.
- #options ⇒ Object
- #primary_key? ⇒ Boolean
-
#settings ⇒ Object
The index settings for this object.
-
#to_key ⇒ Object
Unique key for this object.
- #with_name(new_name) ⇒ Object
Constructor Details
#initialize(columns, table_name:, name: nil, allow_equivalent: false, unique: false, where: nil, length: nil) ⇒ IndexDefinition
Returns a new instance of IndexDefinition.
19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
# File 'lib/declare_schema/model/index_definition.rb', line 19 def initialize(columns, table_name:, name: nil, allow_equivalent: false, unique: false, where: nil, length: nil) @table_name = table_name @name = (name || self.class.default_index_name(table_name, columns)).to_s @columns = Array.wrap(columns).map(&:to_s) @explicit_name = @name if !allow_equivalent unique.in?([false, true]) or raise ArgumentError, "unique must be true or false: got #{unique.inspect}" if @name == PRIMARY_KEY_NAME unique or raise ArgumentError, "primary key index must be unique" end @unique = unique if DeclareSchema.max_index_and_constraint_name_length && @name.length > DeclareSchema.max_index_and_constraint_name_length raise IndexNameTooLongError, "Index '#{@name}' exceeds configured limit of #{DeclareSchema.max_index_and_constraint_name_length} characters. Give it a shorter name, or adjust DeclareSchema.max_index_and_constraint_name_length if you know your database can accept longer names." end if where @where = where.start_with?('(') ? where : "(#{where})" end @length = self.class.normalize_index_length(length, columns: @columns) end |
Class Method Details
.default_index_name(table_name, columns) ⇒ Object
66 67 68 69 70 71 72 |
# File 'lib/declare_schema/model/index_definition.rb', line 66 def default_index_name(table_name, columns) if DeclareSchema.current_adapter == 'postgresql' long_index_name(table_name, columns) else longest_valid_index_name(table_name, columns) end end |
.for_table(table_name, ignore_indexes, connection) ⇒ Object
extract IndexSpecs from an existing table includes the PRIMARY KEY index
44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 |
# File 'lib/declare_schema/model/index_definition.rb', line 44 def for_table(table_name, ignore_indexes, connection) primary_key_columns = Array(connection.primary_key(table_name)) primary_key_columns.present? or raise "could not find primary key for table #{table_name} in #{connection.columns(table_name).inspect}" primary_key_found = false index_definitions = connection.indexes(table_name).map do |index| next if ignore_indexes.include?(index.name) if index.name == PRIMARY_KEY_NAME index.columns == primary_key_columns && index.unique or raise "primary key on #{table_name} was not unique on #{primary_key_columns} (was unique=#{index.unique} on #{index.columns})" primary_key_found = true end new(index.columns, name: index.name, table_name: table_name, unique: index.unique, where: index.where, length: index.lengths) end.compact if !primary_key_found index_definitions << new(primary_key_columns, name: PRIMARY_KEY_NAME, table_name: table_name, unique: true) end index_definitions end |
.normalize_index_length(length, columns:) ⇒ Hash<Symbol, nil>
This method normalizes the length option to be either nil or a Hash of Symbol column names to lengths, so that we can safely compare what the user specified with what we get when querying the database schema.
77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 |
# File 'lib/declare_schema/model/index_definition.rb', line 77 def normalize_index_length(length, columns:) case length when nil, {} nil when Integer if columns.size == 1 { columns.first.to_sym => length } else raise ArgumentError, "Index length of Integer only allowed when exactly one column; got #{length.inspect} for #{columns.inspect}" end when Hash length.transform_keys(&:to_sym) else raise ArgumentError, "Index length must be nil or Integer or a Hash of column names to lengths; got #{length.inspect} for #{columns.inspect}" end end |
Instance Method Details
#<=>(rhs) ⇒ Object
159 160 161 |
# File 'lib/declare_schema/model/index_definition.rb', line 159 def <=>(rhs) to_key <=> rhs.to_key end |
#equivalent?(rhs) ⇒ Boolean
163 164 165 |
# File 'lib/declare_schema/model/index_definition.rb', line 163 def equivalent?(rhs) settings == rhs.settings end |
#hash ⇒ Object
155 156 157 |
# File 'lib/declare_schema/model/index_definition.rb', line 155 def hash to_key.hash end |
#options ⇒ Object
138 139 140 141 142 143 |
# File 'lib/declare_schema/model/index_definition.rb', line 138 def ||= OPTIONS.each_with_object({}) do |option, result| result[option] = send(option) end.freeze end |
#primary_key? ⇒ Boolean
134 135 136 |
# File 'lib/declare_schema/model/index_definition.rb', line 134 def primary_key? name == PRIMARY_KEY_NAME end |
#settings ⇒ Object
The index settings for this object. Used for equivalence checking. Does not include the name.
151 152 153 |
# File 'lib/declare_schema/model/index_definition.rb', line 151 def settings @settings ||= [columns, .except(:name)].freeze end |
#to_key ⇒ Object
Unique key for this object. Used for equality checking.
146 147 148 |
# File 'lib/declare_schema/model/index_definition.rb', line 146 def to_key @to_key ||= [name, *settings].freeze end |
#with_name(new_name) ⇒ Object
167 168 169 |
# File 'lib/declare_schema/model/index_definition.rb', line 167 def with_name(new_name) self.class.new(@columns, name: new_name, table_name: @table_name, unique: @unique, allow_equivalent: @explicit_name.nil?, where: @where, length: @length) end |