Class: DeclareSchema::Model::ForeignKeyDefinition

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

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

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

Returns a new instance of ForeignKeyDefinition.



10
11
12
13
14
15
16
17
18
19
20
21
22
23
# File 'lib/declare_schema/model/foreign_key_definition.rb', line 10

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_nameObject (readonly)

Returns the value of attribute constraint_name.



8
9
10
# File 'lib/declare_schema/model/foreign_key_definition.rb', line 8

def constraint_name
  @constraint_name
end

#foreign_keyObject (readonly)

Returns the value of attribute foreign_key.



8
9
10
# File 'lib/declare_schema/model/foreign_key_definition.rb', line 8

def foreign_key
  @foreign_key
end

#modelObject (readonly)

Returns the value of attribute model.



8
9
10
# File 'lib/declare_schema/model/foreign_key_definition.rb', line 8

def model
  @model
end

#on_delete_cascadeObject (readonly)

Returns the value of attribute on_delete_cascade.



8
9
10
# File 'lib/declare_schema/model/foreign_key_definition.rb', line 8

def on_delete_cascade
  @on_delete_cascade
end

#optionsObject (readonly)

Returns the value of attribute options.



8
9
10
# File 'lib/declare_schema/model/foreign_key_definition.rb', line 8

def options
  @options
end

#parent_table_nameObject



43
44
45
46
47
48
49
# File 'lib/declare_schema/model/foreign_key_definition.rb', line 43

def parent_table_name
  @parent_table_name ||=
    if (klass = options[:class_name])
      klass = klass.to_s.constantize unless klass.is_a?(Class)
      klass.try(:table_name)
    end || foreign_key.sub(/_id\z/, '').camelize.constantize.table_name
end

Class Method Details

.for_model(model, old_table_name) ⇒ Object



26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
# File 'lib/declare_schema/model/foreign_key_definition.rb', line 26

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



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

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

#hashObject



62
63
64
# File 'lib/declare_schema/model/foreign_key_definition.rb', line 62

def hash
  key.hash
end

#keyObject



58
59
60
# File 'lib/declare_schema/model/foreign_key_definition.rb', line 58

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

#to_add_statementObject



53
54
55
56
# File 'lib/declare_schema/model/foreign_key_definition.rb', line 53

def to_add_statement
  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