foreign_key_checker 0.2.0 → 0.4.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b355b8130d2225136101b32202f457ee9615c33621730fa693fcbcb969af3fcf
4
- data.tar.gz: ee8b977be65abc39da0914c804f612bb2fb2a33a98a46c922eedde3866147da1
3
+ metadata.gz: a7420be9666625e34337a8a40eefd53f36acc704b2e222d563bd5811d9b5cc7b
4
+ data.tar.gz: 5abb9fc0b244a85a61022fe24f7810cb39c497197caa8c526d5099fb043add9e
5
5
  SHA512:
6
- metadata.gz: 8f34d020417ddcaefc15a6faec34ffb495f6383157104b660f28013f85a57d8a390cee15c47613ffed64a884ffc581c4c0c5557c97a36d9e2fadf0ff54021d7a
7
- data.tar.gz: a4b0f8032dc6adc78f4780c7c939acc661bb2e9dde713cddee43a5080f59e2882a1433550964f26abb4120491752a83e596f5cc37821561c6ba118cd52f2ad16
6
+ metadata.gz: 76a2abcb77030614a6c0a7b9c8951273796ca1ed09ef0c07ee75ec0e222a7bd8ad636d1409ee3e852e9cdfb37c93a7c8f4dee7ce433ade8a6c842a46a55ee95f
7
+ data.tar.gz: 400ef91dba5578aa3e84b96875a2317066501ec8b49994c9287606e5c77e8e57b02f09d0860d38fab465d3e90c4754e43a39e0d1abda4a86be46f200821bdd65
data/README.md CHANGED
@@ -23,6 +23,12 @@ ForeignKeyChecker.check.each do |key, result|
23
23
  end
24
24
  ```
25
25
 
26
+ Get general information about foreign keys
27
+ ```ruby
28
+ ForeignKeyChecker::Utils.get_foreign_keys_hash
29
+ # => {"users"=>[#<ForeignKeyChecker::Utils::Result:0x00005645e51756e8 @from_table="user_rating_changes", @from_column="user_id", @to_table="users", @to_column="id">]}
30
+ ```
31
+
26
32
  ## Installation
27
33
  Add this line to your application's Gemfile:
28
34
 
@@ -1,6 +1,12 @@
1
1
  require "foreign_key_checker/railtie"
2
+ require 'foreign_key_checker/utils'
3
+ module ForeignKeyChecker::Checkers
4
+ end
5
+ require 'foreign_key_checker/checkers/relations'
6
+ require 'foreign_key_checker/checkers/tables'
2
7
 
3
8
  module ForeignKeyChecker
9
+ class TypeMismatch < StandardError; end
4
10
  class Result
5
11
  attr_reader :model, :association
6
12
  def initialize(data)
@@ -34,6 +40,11 @@ module ForeignKeyChecker
34
40
  def inspect
35
41
  "#<#{self.class.name}:#{self.object_id} #{message}>"
36
42
  end
43
+
44
+ def nullable?
45
+ model.columns_hash[from_column.to_s].null
46
+ end
47
+
37
48
  end
38
49
 
39
50
  class ForeignKeyResult < Result
@@ -73,7 +84,7 @@ module ForeignKeyChecker
73
84
  to_t = model.connection.quote_table_name(to_table)
74
85
  to_c = model.connection.quote_column_name(to_column)
75
86
  #"DELETE #{from_t} FROM #{from_t}.#{from_c} LEFT OUTER JOIN #{to_t} ON #{to_t}.#{to_c} = #{from_t}.#{from_c} WHERE #{to_t}.#{to_c} IS NULL"
76
- "DELETE FROM #{from_t} WHERE #{from_c} IS NOT NULL AND #{from_c} NOT IN (SELECT #{to_c} FROM #{to_t})"
87
+ "DELETE FROM #{from_t} WHERE #{from_c} IS NOT NULL AND #{from_c} NOT IN (SELECT * FROM (SELECT #{to_c} FROM #{to_t}) AS t )"
77
88
  end
78
89
 
79
90
  def set_null_sql
@@ -82,7 +93,7 @@ module ForeignKeyChecker
82
93
  to_t = model.connection.quote_table_name(to_table)
83
94
  to_c = model.connection.quote_column_name(to_column)
84
95
  #"UPDATE #{from_t} SET #{from_t}.#{from_c} = NULL FROM #{from_t} LEFT OUTER JOIN #{to_t} ON #{to_t}.#{to_c} = #{from_t}.#{from_c} WHERE #{to_t}.#{to_c} IS NULL"
85
- "UPDATE #{from_t} SET #{from_c} = NULL WHERE #{from_c} IS NOT NULL AND #{from_c} NOT IN (SELECT #{to_c} FROM #{to_t})"
96
+ "UPDATE #{from_t} SET #{from_c} = NULL WHERE #{from_c} IS NOT NULL AND #{from_c} NOT IN (SELECT * FROM (SELECT #{to_c} FROM #{to_t}) AS t )"
86
97
  end
87
98
 
88
99
  def set_null_migration
@@ -152,15 +163,32 @@ module ForeignKeyChecker
152
163
 
153
164
  end
154
165
 
166
+ def check_types(model, association)
167
+ type_from = model.columns_hash[association.foreign_key.to_s].sql_type
168
+ type_to = association.klass.columns_hash[association.klass.primary_key.to_s].sql_type
169
+ raise TypeMismatch, "TypeMissMatch for relation #{model}##{association.name} #{type_from} != #{type_to}" if type_from != type_to
170
+ end
171
+
155
172
  def check_foreign_key_bt_association(model, association)
156
173
  return if model.name.starts_with?('HABTM_')
157
- related = association.klass
174
+ begin
175
+ related = association.klass
176
+ rescue NameError => error
177
+ @result[:broken] << BrokenRelationResult.new(
178
+ model: model,
179
+ association: association,
180
+ error: error,
181
+ )
182
+ return
183
+ end
158
184
 
159
185
  column_name = model.connection.quote_column_name(association.foreign_key)
160
186
  scope = model.left_outer_joins(association.name).where(
161
187
  "#{related.quoted_table_name}.#{related.quoted_primary_key} IS NULL AND #{model.quoted_table_name}.#{column_name} IS NOT NULL"
162
188
  )
163
189
 
190
+ check_types(model, association)
191
+
164
192
  if zombies
165
193
  number = scope.count
166
194
  if number > 0
@@ -173,7 +201,8 @@ module ForeignKeyChecker
173
201
  end
174
202
  end
175
203
 
176
- if foreign_keys && !model.connection.foreign_key_exists?(model.table_name, related.table_name)
204
+ if foreign_keys && !model.connection.foreign_key_exists?(model.table_name, related.table_name, column: association.foreign_key, primary_key: related.primary_key)
205
+ scope.first
177
206
  @result[:foreign_keys] << ForeignKeyResult.new(
178
207
  model: model,
179
208
  association: association,
@@ -187,7 +216,7 @@ module ForeignKeyChecker
187
216
  association: association,
188
217
  )
189
218
  end
190
- rescue ActiveRecord::InverseOfAssociationNotFoundError, ActiveRecord::StatementInvalid => error
219
+ rescue ActiveRecord::InverseOfAssociationNotFoundError, ActiveRecord::StatementInvalid, TypeMismatch => error
191
220
  @result[:broken] << BrokenRelationResult.new(
192
221
  model: model,
193
222
  association: association,
@@ -195,6 +224,13 @@ module ForeignKeyChecker
195
224
  )
196
225
  end
197
226
 
227
+ def already_done_fk?(model, association)
228
+ @_done ||= {}
229
+ ret = @_done[[model.table_name, association.foreign_key]]
230
+ @_done[[model.table_name, association.foreign_key]] = true
231
+ ret
232
+ end
233
+
198
234
  def check
199
235
  Rails.application.eager_load!
200
236
  ActiveRecord::Base.descendants.each do |model|
@@ -202,11 +238,13 @@ module ForeignKeyChecker
202
238
  next if excluded_specification?(model)
203
239
 
204
240
  model.reflect_on_all_associations(:belongs_to).each do |association|
241
+
205
242
  if association.options[:polymorphic] && polymorphic_zombies
206
243
  check_polymorphic_bt_association(model, association)
207
244
  next
208
245
  end
209
246
 
247
+ next if already_done_fk?(model, association)
210
248
  check_foreign_key_bt_association(model, association)
211
249
  end
212
250
  end
@@ -0,0 +1,122 @@
1
+ require 'foreign_key_checker/utils'
2
+
3
+ module ForeignKeyChecker::Checkers::Relations
4
+ class Result
5
+ attr_reader :ok, :model, :association, :fk, :error, :table
6
+ def initialize(**args)
7
+ %i[model association ok error fk table].each do |key|
8
+ instance_variable_set("@#{key}", args[key])
9
+ end
10
+ end
11
+ end
12
+ class JoinResult < Result
13
+ def message
14
+ "expect { #{model.to_s}.joins(:#{association.name}).first }.to_not raise_exception" if !ok
15
+ end
16
+ end
17
+ class ErrorResult < Result
18
+ def message
19
+ "`#{model.to_s}##{association.name}` is broken\n#{error.class.to_s}\n#{error.message}\n#{error.backtrace.join("\n")}" if !ok
20
+ end
21
+ end
22
+ class HasOneOrManyResult < Result
23
+ def message
24
+ "expected has_many or has_one association for #{fk.inspect}"
25
+ end
26
+ end
27
+ class HasOneOrManyDependentResult < Result
28
+ def message
29
+ "expected has_many or has_one association with dependent option for #{fk.inspect}"
30
+ end
31
+ end
32
+ class NoModelResult < Result
33
+ def message
34
+ "expected find model for table #{table}"
35
+ end
36
+ end
37
+ def self.check_by_join
38
+ Rails.application.eager_load!
39
+ models = ActiveRecord::Base.descendants
40
+ models.each_with_object([]) do |model, results|
41
+ next if model.to_s.include?('HABTM')
42
+ model.reflect_on_all_associations.each do |association|
43
+ begin
44
+ next if association.options[:polymorphic]
45
+ next if association.scope && association.scope.is_a?(Proc) && association.scope.arity > 0
46
+ next if model.connection_specification_name != association.klass.connection_specification_name
47
+
48
+ model.joins(association.name).first
49
+ result = JoinResult.new(model: model, association: association, ok: true)
50
+ yield result if block_given?
51
+ results << result
52
+ rescue => e
53
+ result = JoinResult.new(model: model, association: association, ok: false, error: e)
54
+ yield result if block_given?
55
+ results << result
56
+ end
57
+ end
58
+ end
59
+ end
60
+
61
+ def self.check_by_fks
62
+ Rails.application.eager_load!
63
+ models = ActiveRecord::Base.descendants.group_by(&:table_name)
64
+ check_relation = proc do |model, fk, association|
65
+ begin
66
+ pk = association.options[:primary_key] || model.primary_key
67
+ association.klass.table_name.to_s == fk.from_table.to_s && association.foreign_key.to_s == fk.from_column.to_s && pk.to_s == fk.to_column.to_s
68
+ rescue => e
69
+ if block_given?
70
+ yield ErrorResult.new(model: model, association: association, fk: fk, ok: false, error: e)
71
+ else
72
+ p model
73
+ p fk
74
+ p association
75
+ raise e
76
+ end
77
+ end
78
+ end
79
+ ForeignKeyChecker::Utils.get_foreign_keys_hash.each do |to_table, fks|
80
+ fks.each do |fk|
81
+ unless models.key?(fk.to_table)
82
+ result = NoModelResult.new(ok: false, table: fk.to_table)
83
+ if block_given?
84
+ yield result
85
+ else
86
+ raise result.message
87
+ end
88
+ next
89
+ end
90
+ models[fk.to_table].each do |model|
91
+ next if model.connection_specification_name != 'primary'
92
+ ok = false
93
+ ok ||= !!model.reflect_on_all_associations(:has_many).find do |association|
94
+ check_relation.call(model, fk, association)
95
+ end
96
+ ok ||= !!model.reflect_on_all_associations(:has_one).find do |association|
97
+ check_relation.call(model, fk, association)
98
+ end
99
+ if block_given?
100
+ yield HasOneOrManyResult.new(model: model, fk: fk, ok: ok)
101
+ else
102
+ raise "expected has_many or has_one association for #{fk.inspect}" if !ok
103
+ end
104
+ next if !ok
105
+
106
+ dep = false
107
+ dep ||= !!model.reflect_on_all_associations(:has_many).find do |association|
108
+ check_relation.call(model, fk, association) && association.options[:dependent]
109
+ end
110
+ dep ||= !!model.reflect_on_all_associations(:has_one).find do |association|
111
+ check_relation.call(model, fk, association) && association.options[:dependent]
112
+ end
113
+ if block_given?
114
+ yield HasOneOrManyDependentResult.new(model: model, fk: fk, ok: ok)
115
+ else
116
+ raise "expected has_many or has_one association with dependent option for #{fk.inspect}" if !dep
117
+ end
118
+ end
119
+ end
120
+ end
121
+ end
122
+ end
@@ -0,0 +1,88 @@
1
+ require 'foreign_key_checker/utils'
2
+
3
+ # Стоит использовать в тех случаях, когда подключается rails к уже существующей базе
4
+ # Можно проверить, для каких таблиц всё ещё нет ActiveRecord-моделей
5
+ module ForeignKeyChecker::Checkers::Tables
6
+ SPECIAL_TABLES = ['schema_migrations', 'ar_internal_metadata'].freeze
7
+ # Список таблиц, не описанных моделями (в том числе HABTM-моделями, сгенерированными автоматически rails)
8
+ def self.without_models(specification_name = 'primary')
9
+ Rails.application.eager_load!
10
+
11
+ actual_tables = ForeignKeyChecker::Utils.get_tables
12
+ actual_tables - modelised_tables(specification_name) - SPECIAL_TABLES
13
+ end
14
+
15
+ def self.without_foreign_keys(specification_name = 'primary')
16
+ all_fks = ForeignKeyChecker::Utils.get_foreign_keys
17
+ results = []
18
+ models(specification_name).each do |model|
19
+ model.column_names.each do |column_name|
20
+ next unless column_name.ends_with?('_id')
21
+ next if all_fks.find { |fk| fk.from_table = model.table_name && fk.from_column == column_name }
22
+
23
+ table_name = column_name.delete_suffix('_id')
24
+ results << ["#{table_name}.#{column_name}"]
25
+ end
26
+ end
27
+ end
28
+
29
+ def self.modelised_tables(specification_name = 'primary')
30
+ models(specification_name).map(&:table_name)
31
+ end
32
+
33
+ def self.models(specification_name = 'primary')
34
+ ActiveRecord::Base.descendants.select do |model|
35
+ model.connection_specification_name == specification_name
36
+ end
37
+ end
38
+
39
+
40
+ def self.common_tables
41
+ ForeignKeyChecker::Utils.get_tables - SPECIAL_TABLES
42
+ end
43
+
44
+ class Result
45
+ attr_reader :table_name, :foreign_keys, :internal_references
46
+ def initialize(**args)
47
+ %i[table_name foreign_keys internal_references].each do |key|
48
+ instance_variable_set("@#{key}", args[key] || args[key].to_s)
49
+ end
50
+ end
51
+
52
+ def ok?
53
+ foreign_keys.blank?
54
+ end
55
+
56
+ def referenced?
57
+ foreign_keys.present?
58
+ end
59
+
60
+ def ext_ref?
61
+ !internal_references
62
+ end
63
+
64
+ end
65
+
66
+ def self.check
67
+ tables = without_models
68
+ fks = ForeignKeyChecker::Utils.get_foreign_keys_hash
69
+ fks.default = []
70
+ tables.map do |table|
71
+ Result.new(
72
+ table_name: table,
73
+ foreign_keys: fks[table] || [],
74
+ internal_references: (fks[table].map(&:from_table) - tables).empty?,
75
+ )
76
+ end
77
+ end
78
+
79
+ # TODO вспомнить, что я тут задумал
80
+ def self.ordered(results = check)
81
+ return results if results.size == 0
82
+ oks = results.select(&:ok?)
83
+ if oks.size == 0
84
+ raise "no ok"
85
+ end
86
+ end
87
+
88
+ end
@@ -0,0 +1,126 @@
1
+ module ForeignKeyChecker
2
+ module Utils
3
+ class Result
4
+ attr_reader :from_table, :to_table, :from_column, :to_column
5
+ def initialize(args)
6
+ args.each { |k, v| instance_variable_set("@#{k}", v) }
7
+ end
8
+ end
9
+ class UnsupportedConnectionAdapter < StandardError; end
10
+ def self.get_foreign_keys(model = ActiveRecord::Base)
11
+ adapter = model.connection_config[:adapter]
12
+ raise(UnsupportedConnectionAdapter, adapter) unless %w[postgresql mysql2 sqlserver sqlite3].include?(adapter)
13
+
14
+ connection = model.connection
15
+ send("get_#{adapter}_foreign_keys", connection)
16
+ end
17
+
18
+ def self.get_foreign_keys_hash(model = ActiveRecord::Base)
19
+ get_foreign_keys(model).to_a.each_with_object({}) do |datum, obj|
20
+ obj[datum.to_table] ||= []
21
+ obj[datum.to_table].push(datum)
22
+ end
23
+ end
24
+
25
+ def self.get_sqlite3_foreign_keys(connection)
26
+ res = connection.select_all <<-SQL
27
+ SELECT
28
+ m.name as from_table,
29
+ p."from" as from_column,
30
+ p."table" as to_table,
31
+ p."to" as to_column
32
+ FROM
33
+ sqlite_master m
34
+ JOIN pragma_foreign_key_list(m.name) p ON 1
35
+ WHERE m.type = 'table'
36
+ ORDER BY m.name ;
37
+ SQL
38
+ res.to_a.map{|i| Result.new(i) }
39
+ end
40
+
41
+ def self.get_mysql2_foreign_keys(connection)
42
+ res = connection.select_all <<-SQL
43
+ SELECT
44
+ fks.TABLE_NAME AS from_table,
45
+ fks.COLUMN_NAME AS from_column,
46
+ fks.REFERENCED_TABLE_NAME AS to_table,
47
+ fks.REFERENCED_COLUMN_NAME AS to_column
48
+ FROM information_schema.KEY_COLUMN_USAGE AS fks
49
+ INNER JOIN information_schema.REFERENTIAL_CONSTRAINTS rules ON rules.CONSTRAINT_NAME = fks.CONSTRAINT_NAME
50
+ WHERE
51
+ fks.CONSTRAINT_SCHEMA = DATABASE()
52
+ AND rules.CONSTRAINT_SCHEMA = DATABASE();
53
+ SQL
54
+ res.to_a.map{|i| Result.new(i) }
55
+ end
56
+
57
+ def self.get_postgresql_foreign_keys(connection)
58
+ res = connection.select_all <<-SQL
59
+ SELECT
60
+ tc.table_name AS from_table,
61
+ kcu.column_name AS from_column,
62
+ ccu.table_name AS to_table,
63
+ ccu.column_name AS to_column
64
+ FROM
65
+ information_schema.table_constraints AS tc
66
+ JOIN information_schema.key_column_usage AS kcu
67
+ ON tc.constraint_name = kcu.constraint_name
68
+ AND tc.table_schema = kcu.table_schema
69
+ JOIN information_schema.constraint_column_usage AS ccu
70
+ ON ccu.constraint_name = tc.constraint_name
71
+ AND ccu.table_schema = tc.table_schema
72
+ WHERE tc.constraint_type = 'FOREIGN KEY';
73
+ SQL
74
+ res.to_a.map{ |i| Result.new(i) }
75
+ end
76
+
77
+ def self.get_sqlserver_foreign_keys(connection)
78
+ res = connection.select_all <<-SQL
79
+ SELECT obj.name AS FK_NAME,
80
+ sch.name AS [schema_name],
81
+ tab1.name AS [from_table],
82
+ col1.name AS [from_column],
83
+ tab2.name AS [to_table],
84
+ col2.name AS [to_column]
85
+ FROM sys.foreign_key_columns fkc
86
+ INNER JOIN sys.objects obj
87
+ ON obj.object_id = fkc.constraint_object_id
88
+ INNER JOIN sys.tables tab1
89
+ ON tab1.object_id = fkc.parent_object_id
90
+ INNER JOIN sys.schemas sch
91
+ ON tab1.schema_id = sch.schema_id
92
+ INNER JOIN sys.columns col1
93
+ ON col1.column_id = parent_column_id AND col1.object_id = tab1.object_id
94
+ INNER JOIN sys.tables tab2
95
+ ON tab2.object_id = fkc.referenced_object_id
96
+ INNER JOIN sys.columns col2
97
+ ON col2.column_id = referenced_column_id AND col2.object_id = tab2.object_id
98
+ SQL
99
+ res.to_a.map { |i| Result.new(i) }
100
+ end
101
+
102
+ def self.get_tables(model = ActiveRecord::Base)
103
+ adapter = model.connection_config[:adapter]
104
+ raise(UnsupportedConnectionAdapter, adapter) unless %w[postgresql mysql2 sqlite3 sqlserver].include?(adapter)
105
+
106
+ connection = model.connection
107
+ send("get_#{adapter}_tables", connection)
108
+ end
109
+
110
+ def self.get_mysql2_tables(connection)
111
+ connection.select_all("SELECT table_name FROM information_schema.tables WHERE TABLE_SCHEMA = '#{connection.current_database}'").to_a.pluck('table_name')
112
+ end
113
+
114
+ def self.get_postgresql_tables(connection)
115
+ connection.select_all("SELECT tablename FROM pg_catalog.pg_tables WHERE schemaname != 'pg_catalog' AND schemaname != 'information_schema'").to_a.pluck('tablename')
116
+ end
117
+
118
+ def self.get_sqlite3_tables(connection)
119
+ connection.select_all("SELECT name FROM sqlite_master WHERE type='table'").to_a.pluck('name') - ['sqlite_sequence']
120
+ end
121
+
122
+ def self.get_sqlserver_tables(connection)
123
+ connection.tables
124
+ end
125
+ end
126
+ end
@@ -1,3 +1,3 @@
1
1
  module ForeignKeyChecker
2
- VERSION = '0.2.0'
2
+ VERSION = '0.4.1'
3
3
  end
@@ -14,7 +14,7 @@ module ForeignKeyChecker
14
14
  @done = Dir.glob(Rails.root.join('db', 'migrate', '*.rb')).map do |path|
15
15
  File.open(path).readlines.find { |line| line.include?('ActiveRecord::Migration') && line.include?(@class_name) }
16
16
  end.compact.size
17
- @checks = ForeignKeyChecker.check(zombies: false, indexes: false) unless @behavior == :revoke
17
+ @checks = ForeignKeyChecker.check(zombies: false) unless @behavior == :revoke
18
18
  if @behavior == :revoke
19
19
  @file_suffix = "_v#{@done}" if @done > 1
20
20
  @class_suffix = "V#{@done}" if @done > 1
@@ -3,8 +3,13 @@ class <%= @class_name %><%= @class_suffix %> < ActiveRecord::Migration[<%= Activ
3
3
  <% @checks[:foreign_keys].each do |fk| %>
4
4
  reversible do |dir|
5
5
  dir.up do
6
- # <%= fk.to_zombie.migration(set_null: true) %>
6
+ <% if fk.nullable? %>
7
+ # <%= fk.to_zombie.migration %>
8
+ <%= fk.to_zombie.migration(set_null: true) %>
9
+ <% else %>
10
+ # column <%= fk.from_column %> can't be set to null
7
11
  <%= fk.to_zombie.migration %>
12
+ <% end %>
8
13
  end
9
14
  end
10
15
  <%= fk.migration %>
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: foreign_key_checker
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.4.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - AnatolyShirykalov
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-10-24 00:00:00.000000000 Z
11
+ date: 2020-07-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -38,6 +38,104 @@ dependencies:
38
38
  - - ">="
39
39
  - !ruby/object:Gem::Version
40
40
  version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: pg
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: mysql2
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: tiny_tds
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: activerecord-sqlserver-adapter
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: irb
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: e2mmap
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
125
+ - !ruby/object:Gem::Dependency
126
+ name: annotate
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - ">="
130
+ - !ruby/object:Gem::Version
131
+ version: '0'
132
+ type: :development
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - ">="
137
+ - !ruby/object:Gem::Version
138
+ version: '0'
41
139
  description: Run task to obtain problems with your database
42
140
  email:
43
141
  - pipocavsobake@gmail.com
@@ -49,7 +147,10 @@ files:
49
147
  - README.md
50
148
  - Rakefile
51
149
  - lib/foreign_key_checker.rb
150
+ - lib/foreign_key_checker/checkers/relations.rb
151
+ - lib/foreign_key_checker/checkers/tables.rb
52
152
  - lib/foreign_key_checker/railtie.rb
153
+ - lib/foreign_key_checker/utils.rb
53
154
  - lib/foreign_key_checker/version.rb
54
155
  - lib/generators/foreign_key_checker/migration/migration_generator.rb
55
156
  - lib/generators/foreign_key_checker/migration/templates/migrations/fix_foreign_keys.rb.erb
@@ -59,7 +160,7 @@ licenses:
59
160
  - MIT
60
161
  metadata:
61
162
  allowed_push_host: https://rubygems.org
62
- post_install_message:
163
+ post_install_message:
63
164
  rdoc_options: []
64
165
  require_paths:
65
166
  - lib
@@ -74,8 +175,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
74
175
  - !ruby/object:Gem::Version
75
176
  version: '0'
76
177
  requirements: []
77
- rubygems_version: 3.0.6
78
- signing_key:
178
+ rubygems_version: 3.1.3
179
+ signing_key:
79
180
  specification_version: 4
80
181
  summary: Find problems with relations in active_record models
81
182
  test_files: []