Class: DeclareSchema::Model::ForeignKeySpec

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

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(model, foreign_key, options = {}) ⇒ ForeignKeySpec

Returns a new instance of ForeignKeySpec.



108
109
110
111
112
113
114
115
116
117
118
119
120
121
# File 'lib/declare_schema/model/index_spec.rb', line 108

def initialize(model, foreign_key, options = {})
  @model = model
  @foreign_key = foreign_key.presence
  @options = options

  @child_table = model.table_name # unless a table rename, which would happen when a class is renamed??
  @parent_table_name = options[:parent_table]
  @foreign_key_name = options[:foreign_key] || self.foreign_key
  @index_name = options[:index_name] || model.connection.index_name(model.table_name, column: foreign_key)
  @constraint_name = options[:constraint_name] || @index_name || ''
  @on_delete_cascade = options[:dependent] == :delete

  # Empty constraint lets mysql generate the name
end

Instance Attribute Details

#constraint_name ⇒ Object (readonly)

Returns the value of attribute constraint_name.



106
107
108
# File 'lib/declare_schema/model/index_spec.rb', line 106

def constraint_name
  @constraint_name
end

#foreign_key ⇒ Object (readonly)

Returns the value of attribute foreign_key.



106
107
108
# File 'lib/declare_schema/model/index_spec.rb', line 106

def foreign_key
  @foreign_key
end

#model ⇒ Object (readonly)

Returns the value of attribute model.



106
107
108
# File 'lib/declare_schema/model/index_spec.rb', line 106

def model
  @model
end

#on_delete_cascade ⇒ Object (readonly)

Returns the value of attribute on_delete_cascade.



106
107
108
# File 'lib/declare_schema/model/index_spec.rb', line 106

def on_delete_cascade
  @on_delete_cascade
end

#options ⇒ Object (readonly)

Returns the value of attribute options.



106
107
108
# File 'lib/declare_schema/model/index_spec.rb', line 106

def options
  @options
end

#parent_table_name ⇒ Object



141
142
143
144
145
146
147
148
149
150
151
# File 'lib/declare_schema/model/index_spec.rb', line 141

def parent_table_name
  @parent_table_name ||=
    options[:class_name]&.is_a?(Class) &&
    options[:class_name].respond_to?(:table_name) &&
    options[:class_name]&.table_name
  @parent_table_name ||=
    options[:class_name]&.constantize &&
    options[:class_name].constantize.respond_to?(:table_name) &&
    options[:class_name].constantize.table_name ||
    foreign_key.gsub(/_id/, '').camelize.constantize.table_name
end

Class Method Details

.for_model(model, old_table_name) ⇒ Object



124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
# File 'lib/declare_schema/model/index_spec.rb', line 124

def for_model(model, old_table_name)
  show_create_table = model.connection.select_rows("show create table #{model.connection.quote_table_name(old_table_name)}").first.last
  constraints = show_create_table.split("\n").map { |line| line.strip if line['CONSTRAINT'] }.compact

  constraints.map do |fkc|
    options = {}
    name, foreign_key, parent_table = fkc.match(/CONSTRAINT `([^`]*)` FOREIGN KEY \(`([^`]*)`\) REFERENCES `([^`]*)`/).captures
    options[:constraint_name] = name
    options[:parent_table] = parent_table
    options[:foreign_key] = foreign_key
    options[:dependent] = :delete if fkc['ON DELETE CASCADE']

    new(model, foreign_key, options)
  end
end

Instance Method Details

#<=>(rhs) ⇒ Object



168
169
170
# File 'lib/declare_schema/model/index_spec.rb', line 168

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

#hash ⇒ Object



164
165
166
# File 'lib/declare_schema/model/index_spec.rb', line 164

def hash
  to_key.hash
end

#to_add_statement(_ = true) ⇒ Object



155
156
157
158
# File 'lib/declare_schema/model/index_spec.rb', line 155

def to_add_statement(_ = true)
  statement = "ALTER TABLE #{@child_table} ADD CONSTRAINT #{@constraint_name} FOREIGN KEY #{@index_name}(#{@foreign_key_name}) REFERENCES #{parent_table_name}(id) #{'ON DELETE CASCADE' if on_delete_cascade}"
  "execute #{statement.inspect}"
end

#to_key ⇒ Object



160
161
162
# File 'lib/declare_schema/model/index_spec.rb', line 160

def to_key
  @key ||= [@child_table, parent_table_name, @foreign_key_name, @on_delete_cascade].map(&:to_s)
end