immigrant 0.3.3 → 0.3.4
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 +4 -4
- data/lib/immigrant.rb +21 -29
- data/lib/immigrant/key_validator.rb +32 -0
- data/test/immigrant_test.rb +27 -2
- metadata +2 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7ed3d771b38d02c5ff03b07c83d14e820703fe43
|
4
|
+
data.tar.gz: 8408b58635d65127dfcb28125bc23ff701abb442
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d81e14ec77a85039b8cd6fb9ca64b3bb25730ee4b232a220c37c1285340993b808d3ec82a2d721172fc2a5647ee934bf007774d76d32105761cd3279b8d98098
|
7
|
+
data.tar.gz: 29faf9f62a44d17984fd685600e38220a1e3cc355127c98fb810c4e76b1609ec8068eda4380e05a8738b38505c54fd2ab5435e855eba193bd019b0a9a602d42e
|
data/lib/immigrant.rb
CHANGED
@@ -33,15 +33,23 @@ module Immigrant
|
|
33
33
|
if current_key.to_table != foreign_key.to_table || current_key.options[:primary_key] != foreign_key.options[:primary_key]
|
34
34
|
warnings[hash_key] = "Skipping #{foreign_key.from_table}.#{foreign_key.options[:column]}: its association references a different key/table than its current foreign key"
|
35
35
|
end
|
36
|
-
|
37
|
-
new_keys << foreign_key
|
36
|
+
next
|
38
37
|
end
|
38
|
+
|
39
|
+
next if ignore_keys[hash_key]
|
40
|
+
next unless key_validator.valid?(foreign_key)
|
41
|
+
|
42
|
+
new_keys << foreign_key
|
39
43
|
end
|
40
44
|
[new_keys.sort_by{ |key| key.options[:name] }, warnings]
|
41
45
|
end
|
42
46
|
|
43
47
|
private
|
44
48
|
|
49
|
+
def key_validator
|
50
|
+
@key_validator ||= KeyValidator.new
|
51
|
+
end
|
52
|
+
|
45
53
|
def tables
|
46
54
|
@tables ||= ActiveRecord::Base.connection.tables
|
47
55
|
end
|
@@ -129,8 +137,6 @@ module Immigrant
|
|
129
137
|
column = reflection.send(FOREIGN_KEY).to_s
|
130
138
|
primary_key = (reflection.options[:primary_key] || reflection.klass.primary_key).to_s
|
131
139
|
|
132
|
-
return unless column_exists?(from_table, column)
|
133
|
-
|
134
140
|
[
|
135
141
|
ForeignKeyDefinition.new(
|
136
142
|
from_table,
|
@@ -154,8 +160,6 @@ module Immigrant
|
|
154
160
|
actions = {:on_delete => :cascade, :on_update => :cascade}
|
155
161
|
end
|
156
162
|
|
157
|
-
return unless column_exists?(from_table, column)
|
158
|
-
|
159
163
|
[
|
160
164
|
ForeignKeyDefinition.new(
|
161
165
|
from_table,
|
@@ -169,45 +173,32 @@ module Immigrant
|
|
169
173
|
end
|
170
174
|
|
171
175
|
def infer_habtm_keys(klass, reflection)
|
172
|
-
keys = []
|
173
|
-
|
174
176
|
join_table = (reflection.respond_to?(:join_table) ? reflection.join_table : reflection.options[:join_table]).to_s
|
175
177
|
|
176
178
|
left_to_table = klass.table_name
|
177
179
|
left_column = reflection.send(FOREIGN_KEY).to_s
|
178
180
|
left_primary_key = klass.primary_key.to_s
|
179
|
-
if column_exists?(join_table, left_column)
|
180
|
-
keys << ForeignKeyDefinition.new(
|
181
|
-
join_table,
|
182
|
-
left_to_table,
|
183
|
-
:column => left_column,
|
184
|
-
:primary_key => left_primary_key
|
185
|
-
)
|
186
|
-
end
|
187
181
|
|
188
182
|
right_to_table = reflection.klass.table_name
|
189
183
|
right_column = reflection.association_foreign_key.to_s
|
190
184
|
right_primary_key = reflection.klass.primary_key.to_s
|
191
|
-
|
192
|
-
|
185
|
+
|
186
|
+
[
|
187
|
+
ForeignKeyDefinition.new(
|
188
|
+
join_table,
|
189
|
+
left_to_table,
|
190
|
+
:column => left_column,
|
191
|
+
:primary_key => left_primary_key
|
192
|
+
),
|
193
|
+
ForeignKeyDefinition.new(
|
193
194
|
join_table,
|
194
195
|
right_to_table,
|
195
196
|
:column => right_column,
|
196
197
|
:primary_key => right_primary_key
|
197
198
|
)
|
198
|
-
|
199
|
-
|
200
|
-
keys
|
201
|
-
end
|
202
|
-
|
203
|
-
def column_exists?(table_name, column_name)
|
204
|
-
columns_for(table_name).any? { |column| column.name == column_name }
|
199
|
+
]
|
205
200
|
end
|
206
201
|
|
207
|
-
def columns_for(table_name)
|
208
|
-
@columns ||= {}
|
209
|
-
@columns[table_name] ||= ActiveRecord::Base.connection.columns(table_name)
|
210
|
-
end
|
211
202
|
|
212
203
|
def qualified_reflection?(reflection, klass)
|
213
204
|
scope = reflection.scope
|
@@ -225,5 +216,6 @@ module Immigrant
|
|
225
216
|
end
|
226
217
|
|
227
218
|
require 'immigrant/loader'
|
219
|
+
require 'immigrant/key_validator'
|
228
220
|
require 'immigrant/foreign_key_extensions'
|
229
221
|
require 'immigrant/railtie' if defined?(Rails)
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module Immigrant
|
2
|
+
class KeyValidator
|
3
|
+
def valid?(key)
|
4
|
+
tables = connection.tables
|
5
|
+
return false unless tables.include?(key.from_table)
|
6
|
+
return false unless tables.include?(key.to_table)
|
7
|
+
return false unless column_exists?(key.from_table, key.options[:column])
|
8
|
+
return false unless column_exists?(key.to_table, key.options[:primary_key])
|
9
|
+
return false unless key.options[:primary_key] == "id" || has_unique_index?(key.to_table, key.options[:primary_key])
|
10
|
+
true
|
11
|
+
end
|
12
|
+
|
13
|
+
private
|
14
|
+
|
15
|
+
def has_unique_index?(table_name, column_name)
|
16
|
+
connection.indexes(table_name).any? { |index| index.columns == [column_name] && index.unique && index.where.nil? }
|
17
|
+
end
|
18
|
+
|
19
|
+
def column_exists?(table_name, column_name)
|
20
|
+
columns_for(table_name).any? { |column| column.name == column_name }
|
21
|
+
end
|
22
|
+
|
23
|
+
def columns_for(table_name)
|
24
|
+
@columns ||= {}
|
25
|
+
@columns[table_name] ||= connection.columns(table_name)
|
26
|
+
end
|
27
|
+
|
28
|
+
def connection
|
29
|
+
@connection ||= ActiveRecord::Base.connection
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
data/test/immigrant_test.rb
CHANGED
@@ -41,16 +41,21 @@ class ImmigrantTest < ActiveSupport::TestCase
|
|
41
41
|
ActiveSupport::DescendantsTracker.direct_descendants(ActiveRecord::Base).map(&:table_name)
|
42
42
|
end
|
43
43
|
def columns(table_name)
|
44
|
-
|
44
|
+
AnyCollection.new
|
45
|
+
end
|
46
|
+
def indexes(table_name)
|
47
|
+
AnyCollection.new
|
45
48
|
end
|
46
49
|
end
|
47
50
|
|
48
|
-
class
|
51
|
+
class AnyCollection
|
49
52
|
def any?
|
50
53
|
true
|
51
54
|
end
|
52
55
|
end
|
53
56
|
|
57
|
+
Index = ActiveRecord::ConnectionAdapters::IndexDefinition
|
58
|
+
|
54
59
|
def teardown
|
55
60
|
subclasses = ActiveSupport::DescendantsTracker.direct_descendants(ActiveRecord::Base)
|
56
61
|
subclasses.each do |subclass|
|
@@ -455,6 +460,26 @@ class ImmigrantTest < ActiveSupport::TestCase
|
|
455
460
|
end
|
456
461
|
end
|
457
462
|
|
463
|
+
test 'insufficiently unique "primary" keys should not generate a foreign key' do
|
464
|
+
given <<-CODE
|
465
|
+
class Setting < ActiveRecord::Base; end
|
466
|
+
|
467
|
+
class SettingValue < ActiveRecord::Base
|
468
|
+
belongs_to :setting,
|
469
|
+
:conditions => { :deleted_at => nil },
|
470
|
+
foreign_key: :name, primary_key: :name
|
471
|
+
end
|
472
|
+
CODE
|
473
|
+
|
474
|
+
# emulate `"index_settings_on_name" UNIQUE, btree (name) WHERE deleted_at IS NULL`
|
475
|
+
# it's unique, but not enough for a foreign key just on name
|
476
|
+
indexes = [Index.new("settings", ["name"], true, "deleted_at IS NULL")]
|
477
|
+
|
478
|
+
MockConnection.stub_any_instance(:indexes, indexes) do
|
479
|
+
assert_equal([], infer_keys)
|
480
|
+
end
|
481
|
+
end
|
482
|
+
|
458
483
|
test 'ignore_keys should be respected' do
|
459
484
|
given <<-CODE
|
460
485
|
class User < ActiveRecord::Base; end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: immigrant
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.3.
|
4
|
+
version: 0.3.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jon Jensen
|
@@ -48,6 +48,7 @@ files:
|
|
48
48
|
- lib/immigrant/compat/active_record.rb
|
49
49
|
- lib/immigrant/compat/foreigner.rb
|
50
50
|
- lib/immigrant/foreign_key_extensions.rb
|
51
|
+
- lib/immigrant/key_validator.rb
|
51
52
|
- lib/immigrant/loader.rb
|
52
53
|
- lib/immigrant/railtie.rb
|
53
54
|
- lib/immigrant/task.rb
|