Class: DeclareSchema::Model::IndexDefinition

Inherits:
Object
  • Object
show all
Includes:
Comparable
Defined in:
lib/declare_schema/model/index_definition.rb

Defined Under Namespace

Classes: IndexNameTooLongError

Constant Summary collapse

PRIMARY_KEY_NAME =
"PRIMARY"
MYSQL_INDEX_NAME_MAX_LENGTH =
64

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(model, fields, **options) ⇒ IndexDefinition

Returns a new instance of IndexDefinition.



17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
# File 'lib/declare_schema/model/index_definition.rb', line 17

def initialize(model, fields, **options)
  @model = model
  @table = options.delete(:table_name) || model.table_name
  @fields = Array.wrap(fields).map(&:to_s)
  @explicit_name = options[:name] unless options.delete(:allow_equivalent)
  @name = options.delete(:name) || self.class.index_name(@fields)
  @unique = options.delete(:unique) || name == PRIMARY_KEY_NAME || false

  if @name.length > MYSQL_INDEX_NAME_MAX_LENGTH
    raise IndexNameTooLongError, "Index '#{@name}' exceeds MySQL limit of #{MYSQL_INDEX_NAME_MAX_LENGTH} characters. Give it a shorter name."
  end

  if (where = options[:where])
    @where = where.start_with?('(') ? where : "(#{where})"
  end
end

Instance Attribute Details

#explicit_nameObject (readonly)

TODO: replace ‘fields` with `columns` and remove alias. -Colin



9
10
11
# File 'lib/declare_schema/model/index_definition.rb', line 9

def explicit_name
  @explicit_name
end

#fieldsObject (readonly) Also known as: columns

TODO: replace ‘fields` with `columns` and remove alias. -Colin



9
10
11
# File 'lib/declare_schema/model/index_definition.rb', line 9

def fields
  @fields
end

#nameObject (readonly)

TODO: replace ‘fields` with `columns` and remove alias. -Colin



9
10
11
# File 'lib/declare_schema/model/index_definition.rb', line 9

def name
  @name
end

#tableObject (readonly)

TODO: replace ‘fields` with `columns` and remove alias. -Colin



9
10
11
# File 'lib/declare_schema/model/index_definition.rb', line 9

def table
  @table
end

#uniqueObject (readonly)

TODO: replace ‘fields` with `columns` and remove alias. -Colin



9
10
11
# File 'lib/declare_schema/model/index_definition.rb', line 9

def unique
  @unique
end

#whereObject (readonly)

TODO: replace ‘fields` with `columns` and remove alias. -Colin



9
10
11
# File 'lib/declare_schema/model/index_definition.rb', line 9

def where
  @where
end

Class Method Details

.for_model(model, old_table_name = nil) ⇒ Object

extract IndexSpecs from an existing table always includes the PRIMARY KEY index for Model unless it is a HABTM Model.



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
# File 'lib/declare_schema/model/index_definition.rb', line 37

def for_model(model, old_table_name = nil)
  t = old_table_name || model.table_name

  habtm_model = model.is_a?(DeclareSchema::Model::HabtmModelShim)

  primary_key_columns = Array(model.connection.primary_key(t)).presence
  primary_key_columns || habtm_model or
    raise "could not find primary key for table #{t} in #{model.connection.columns(t).inspect}"

  primary_key_found = false
  index_definitions = model.connection.indexes(t).map do |i|
    model.ignore_indexes.include?(i.name) and next
    if i.name == PRIMARY_KEY_NAME
      i.columns == primary_key_columns && i.unique or
        raise "primary key on #{t} was not unique on #{primary_key_columns} (was unique=#{i.unique} on #{i.columns})"
      primary_key_found = true
    elsif i.columns == primary_key_columns && i.unique && !habtm_model
      # skip this primary key index since we'll create it below, with PRIMARY_KEY_NAME
      next
    end
    new(model, i.columns, name: i.name, unique: i.unique, where: i.where, table_name: old_table_name)
  end.compact

  if !primary_key_found && !habtm_model
    index_definitions << new(model, primary_key_columns, name: PRIMARY_KEY_NAME, unique: true, where: nil, table_name: old_table_name)
  end
  index_definitions
end

.index_name(columns) ⇒ Object



66
67
68
# File 'lib/declare_schema/model/index_definition.rb', line 66

def index_name(columns)
  "on_#{Array(columns).join("_and_")}"
end

Instance Method Details

#<=>(rhs) ⇒ Object



87
88
89
# File 'lib/declare_schema/model/index_definition.rb', line 87

def <=>(rhs)
  to_key <=> rhs.to_key
end

#equivalent?(rhs) ⇒ Boolean

Returns:



91
92
93
# File 'lib/declare_schema/model/index_definition.rb', line 91

def equivalent?(rhs)
  settings == rhs.settings
end

#hashObject



83
84
85
# File 'lib/declare_schema/model/index_definition.rb', line 83

def hash
  to_key.hash
end

#primary_key?Boolean

Returns:



71
72
73
# File 'lib/declare_schema/model/index_definition.rb', line 71

def primary_key?
  name == PRIMARY_KEY_NAME
end

#settingsObject



79
80
81
# File 'lib/declare_schema/model/index_definition.rb', line 79

def settings
  @settings ||= [table, fields, unique].map(&:to_s)
end

#to_keyObject



75
76
77
# File 'lib/declare_schema/model/index_definition.rb', line 75

def to_key
  @key ||= [table, fields, name, unique, where].map(&:to_s)
end

#with_name(new_name) ⇒ Object



95
96
97
# File 'lib/declare_schema/model/index_definition.rb', line 95

def with_name(new_name)
  self.class.new(@model, @fields, table_name: @table_name, index_name: @index_name, unique: @unique, name: new_name)
end