immigrant 0.1.5 → 0.1.6
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/immigrant.rb +80 -44
- data/test/immigrant_test.rb +19 -0
- metadata +3 -3
data/lib/immigrant.rb
CHANGED
@@ -50,16 +50,14 @@ module Immigrant
|
|
50
50
|
# see what the models say there should be
|
51
51
|
foreign_keys = {}
|
52
52
|
warnings = {}
|
53
|
-
|
54
|
-
|
55
|
-
}.flatten.uniq.each do |foreign_key|
|
53
|
+
|
54
|
+
candidate_model_keys(classes).each do |foreign_key|
|
56
55
|
# we may have inferred it from several different places, e.g.
|
57
56
|
# Bar.belongs_to :foo
|
58
57
|
# Foo.has_many :bars
|
59
58
|
# Foo.has_many :bazzes, :class_name => Bar
|
60
59
|
# we need to make sure everything is legit and see if any of them
|
61
60
|
# specify :dependent => :delete
|
62
|
-
next if foreign_key.nil?
|
63
61
|
if current_key = foreign_keys[foreign_key.hash_key]
|
64
62
|
if current_key.to_table != foreign_key.to_table || current_key.options[:primary_key] != foreign_key.options[:primary_key]
|
65
63
|
warnings[foreign_key.hash_key] ||= "Skipping #{foreign_key.from_table}.#{foreign_key.options[:column]}: it has multiple associations referencing different keys/tables."
|
@@ -74,56 +72,94 @@ module Immigrant
|
|
74
72
|
[foreign_keys, warnings]
|
75
73
|
end
|
76
74
|
|
77
|
-
def
|
78
|
-
|
75
|
+
def candidate_model_keys(classes)
|
76
|
+
classes.inject([]) do |result, klass|
|
77
|
+
result.concat foreign_keys_for(klass)
|
78
|
+
end.uniq
|
79
|
+
end
|
79
80
|
|
80
|
-
|
81
|
+
def candidate_reflections_for(klass)
|
82
|
+
klass.reflections.values.reject do |reflection|
|
81
83
|
# some associations can just be ignored, since:
|
82
84
|
# 1. we aren't going to parse SQL
|
83
85
|
# 2. foreign keys for :through associations will be handled by their
|
84
86
|
# component has_one/has_many/belongs_to associations
|
85
87
|
# 3. :polymorphic(/:as) associations can't have foreign keys
|
86
88
|
(reflection.options.keys & [:finder_sql, :through, :polymorphic, :as]).present?
|
87
|
-
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
def foreign_keys_for(klass)
|
93
|
+
candidate_reflections_for(klass).inject([]) do |result, reflection|
|
88
94
|
begin
|
89
|
-
|
90
|
-
when :belongs_to
|
91
|
-
Foreigner::ConnectionAdapters::ForeignKeyDefinition.new(
|
92
|
-
klass.table_name, reflection.klass.table_name,
|
93
|
-
:column => reflection.send(fk_method).to_s,
|
94
|
-
:primary_key => reflection.klass.primary_key.to_s,
|
95
|
-
# although belongs_to can specify :dependent, it doesn't make
|
96
|
-
# sense from a foreign key perspective
|
97
|
-
:dependent => nil
|
98
|
-
)
|
99
|
-
when :has_one, :has_many
|
100
|
-
Foreigner::ConnectionAdapters::ForeignKeyDefinition.new(
|
101
|
-
reflection.klass.table_name, klass.table_name,
|
102
|
-
:column => reflection.send(fk_method).to_s,
|
103
|
-
:primary_key => klass.primary_key.to_s,
|
104
|
-
:dependent => [:delete, :delete_all].include?(reflection.options[:dependent]) && !qualified_reflection?(reflection, klass) ? :delete : nil
|
105
|
-
)
|
106
|
-
when :has_and_belongs_to_many
|
107
|
-
join_table = (reflection.respond_to?(:join_table) ? reflection.join_table : reflection.options[:join_table]).to_s
|
108
|
-
[
|
109
|
-
Foreigner::ConnectionAdapters::ForeignKeyDefinition.new(
|
110
|
-
join_table, klass.table_name,
|
111
|
-
:column => reflection.send(fk_method).to_s,
|
112
|
-
:primary_key => klass.primary_key.to_s,
|
113
|
-
:dependent => nil
|
114
|
-
),
|
115
|
-
Foreigner::ConnectionAdapters::ForeignKeyDefinition.new(
|
116
|
-
join_table, reflection.klass.table_name,
|
117
|
-
:column => reflection.association_foreign_key.to_s,
|
118
|
-
:primary_key => reflection.klass.primary_key.to_s,
|
119
|
-
:dependent => nil
|
120
|
-
)
|
121
|
-
]
|
122
|
-
end
|
95
|
+
result.concat foreign_key_for(klass, reflection)
|
123
96
|
rescue NameError # e.g. belongs_to :oops_this_is_not_a_table
|
124
|
-
|
97
|
+
result
|
125
98
|
end
|
126
|
-
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
def foreign_key_for(klass, reflection)
|
103
|
+
case reflection.macro
|
104
|
+
when :belongs_to
|
105
|
+
infer_belongs_to_keys(klass, reflection)
|
106
|
+
when :has_one, :has_many
|
107
|
+
infer_has_n_keys(klass, reflection)
|
108
|
+
when :has_and_belongs_to_many
|
109
|
+
infer_habtm_keys(klass, reflection)
|
110
|
+
else
|
111
|
+
[]
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
def infer_belongs_to_keys(klass, reflection)
|
116
|
+
[
|
117
|
+
Foreigner::ConnectionAdapters::ForeignKeyDefinition.new(
|
118
|
+
klass.table_name,
|
119
|
+
reflection.klass.table_name,
|
120
|
+
:column => reflection.send(fk_method).to_s,
|
121
|
+
:primary_key => (reflection.options[:primary_key] || reflection.klass.primary_key).to_s,
|
122
|
+
# although belongs_to can specify :dependent, it doesn't make
|
123
|
+
# sense from a foreign key perspective
|
124
|
+
:dependent => nil
|
125
|
+
)
|
126
|
+
]
|
127
|
+
end
|
128
|
+
|
129
|
+
def infer_has_n_keys(klass, reflection)
|
130
|
+
[
|
131
|
+
Foreigner::ConnectionAdapters::ForeignKeyDefinition.new(
|
132
|
+
reflection.klass.table_name,
|
133
|
+
klass.table_name,
|
134
|
+
:column => reflection.send(fk_method).to_s,
|
135
|
+
:primary_key => (reflection.options[:primary_key] || klass.primary_key).to_s,
|
136
|
+
:dependent => [:delete, :delete_all].include?(reflection.options[:dependent]) && !qualified_reflection?(reflection, klass) ? :delete : nil
|
137
|
+
)
|
138
|
+
]
|
139
|
+
end
|
140
|
+
|
141
|
+
def infer_habtm_keys(klass, reflection)
|
142
|
+
join_table = (reflection.respond_to?(:join_table) ? reflection.join_table : reflection.options[:join_table]).to_s
|
143
|
+
[
|
144
|
+
Foreigner::ConnectionAdapters::ForeignKeyDefinition.new(
|
145
|
+
join_table,
|
146
|
+
klass.table_name,
|
147
|
+
:column => reflection.send(fk_method).to_s,
|
148
|
+
:primary_key => klass.primary_key.to_s,
|
149
|
+
:dependent => nil
|
150
|
+
),
|
151
|
+
Foreigner::ConnectionAdapters::ForeignKeyDefinition.new(
|
152
|
+
join_table,
|
153
|
+
reflection.klass.table_name,
|
154
|
+
:column => reflection.association_foreign_key.to_s,
|
155
|
+
:primary_key => reflection.klass.primary_key.to_s,
|
156
|
+
:dependent => nil
|
157
|
+
)
|
158
|
+
]
|
159
|
+
end
|
160
|
+
|
161
|
+
def fk_method
|
162
|
+
ActiveRecord::VERSION::STRING < '3.1.' ? :primary_key_name : :foreign_key
|
127
163
|
end
|
128
164
|
|
129
165
|
def qualified_reflection?(reflection, klass)
|
data/test/immigrant_test.rb
CHANGED
@@ -202,6 +202,25 @@ class ImmigrantTest < ActiveSupport::TestCase
|
|
202
202
|
)
|
203
203
|
end
|
204
204
|
|
205
|
+
test 'primary_key should be respected' do
|
206
|
+
class User < MockModel
|
207
|
+
has_many :emails, :primary_key => :email, :foreign_key => :to,
|
208
|
+
:dependent => :destroy
|
209
|
+
end
|
210
|
+
class Email < MockModel
|
211
|
+
belongs_to :user, :primary_key => :email, :foreign_key => :to
|
212
|
+
end
|
213
|
+
|
214
|
+
keys = Immigrant.infer_keys([]).first
|
215
|
+
assert_nothing_raised { keys.map { |key| key.to_ruby(:add) } }
|
216
|
+
assert_equal(
|
217
|
+
[foreign_key_definition(
|
218
|
+
'emails', 'users',
|
219
|
+
:column => 'to', :primary_key => 'email', :dependent => nil
|
220
|
+
)],
|
221
|
+
keys
|
222
|
+
)
|
223
|
+
end
|
205
224
|
|
206
225
|
# (no) duplication
|
207
226
|
|
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.1.
|
4
|
+
version: 0.1.6
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2014-03-10 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: activerecord
|
@@ -84,7 +84,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
84
84
|
version: 1.3.5
|
85
85
|
requirements: []
|
86
86
|
rubyforge_project:
|
87
|
-
rubygems_version: 1.8.
|
87
|
+
rubygems_version: 1.8.23
|
88
88
|
signing_key:
|
89
89
|
specification_version: 3
|
90
90
|
summary: Migration generator for Foreigner
|