1
1
# frozen_string_literal: true
2
2
3
+ require 'torque/postgresql/schema_cache/inheritance'
4
+
5
+ if Torque ::PostgreSQL ::AR710
6
+ require 'torque/postgresql/schema_cache/schema_reflection'
7
+ require 'torque/postgresql/schema_cache/bound_schema_reflection'
8
+ end
9
+
3
10
module Torque
4
11
module PostgreSQL
5
12
LookupError = Class . new ( ArgumentError )
6
13
7
14
# :TODO: Create the +add+ to load inheritance info
8
15
module SchemaCache
16
+ include Torque ::PostgreSQL ::SchemaCache ::Inheritance
9
17
10
18
def initialize ( *) # :nodoc:
11
19
super
@@ -37,7 +45,7 @@ def init_with(coder) # :nodoc:
37
45
@inheritance_associations = coder [ 'inheritance_associations' ]
38
46
end
39
47
40
- def add ( table_name , *) # :nodoc:
48
+ def add ( connection_or_table_name , table_name = connection_or_table_name , *) # :nodoc:
41
49
super
42
50
43
51
# Reset inheritance information when a table is added
@@ -64,8 +72,8 @@ def size # :nodoc:
64
72
] . map ( &:size ) . inject ( :+ )
65
73
end
66
74
67
- def clear_data_source_cache! ( name ) # :nodoc:
68
- super
75
+ def clear_data_source_cache! ( connection_or_name , name = connection_or_name ) # :nodoc:
76
+ Torque :: PostgreSQL :: AR710 ? super : super ( name )
69
77
@data_sources_model_names . delete name
70
78
@inheritance_dependencies . delete name
71
79
@inheritance_associations . delete name
@@ -95,88 +103,29 @@ def add_model_name(table_name, model)
95
103
end
96
104
97
105
# Get all the tables that the given one inherits from
98
- def dependencies ( table_name )
99
- reload_inheritance_data!
106
+ def dependencies ( conn , table_name = conn )
107
+ reload_inheritance_data! ( conn == table_name ? connection : conn )
100
108
@inheritance_dependencies [ table_name ]
101
109
end
102
110
103
111
# Get the list of all tables that are associated (direct or indirect
104
112
# inheritance) with the provided one
105
- def associations ( table_name )
106
- reload_inheritance_data!
113
+ def associations ( conn , table_name = conn )
114
+ reload_inheritance_data! ( conn == table_name ? connection : conn )
107
115
@inheritance_associations [ table_name ]
108
116
end
109
117
110
- # Try to find a model based on a given table
111
- def lookup_model ( table_name , scoped_class = '' )
112
- scoped_class = scoped_class . name if scoped_class . is_a? ( Class )
113
- return @data_sources_model_names [ table_name ] \
114
- if @data_sources_model_names . key? ( table_name )
115
-
116
- # Get all the possible scopes
117
- scopes = scoped_class . scan ( /(?:::)?[A-Z][a-z]+/ )
118
- scopes . unshift ( 'Object::' )
119
-
120
- # Check if the table name comes with a schema
121
- if table_name . include? ( '.' )
122
- schema , table_name = table_name . split ( '.' )
123
- scopes . insert ( 1 , schema . camelize ) if schema != 'public'
124
- end
125
-
126
- # Consider the maximum namespaced possible model name
127
- max_name = table_name . tr ( '_' , '/' ) . camelize . split ( /(::)/ )
128
- max_name [ -1 ] = max_name [ -1 ] . singularize
129
-
130
- # Test all the possible names against all the possible scopes
131
- until scopes . size == 0
132
- scope = scopes . join . chomp ( '::' ) . safe_constantize
133
- model = find_model ( max_name , table_name , scope ) unless scope . nil?
134
- return @data_sources_model_names [ table_name ] = model unless model . nil?
135
- scopes . pop
136
- end
137
-
138
- # If this part is reach, no model name was found
139
- raise LookupError . new ( <<~MSG . squish )
140
- Unable to find a valid model that is associated with the '#{ table_name } ' table.
141
- Please, check if they correctly inherit from ActiveRecord::Base
142
- MSG
118
+ # Override the inheritance implementation to pass over the proper cache of
119
+ # the existing association between data sources and model names
120
+ def lookup_model ( *args , **xargs )
121
+ super ( *args , **xargs , source_to_model : @data_sources_model_names )
143
122
end
144
123
145
124
private
146
125
147
- # Find a model by a given max namespaced class name thath matches the
148
- # given table name
149
- def find_model ( max_name , table_name , scope = Object )
150
- pieces = max_name . is_a? ( ::Array ) ? max_name : max_name . split ( /(::)/ )
151
- ns_places = ( 1 ..( max_name . size - 1 ) ) . step ( 2 ) . to_a
152
-
153
- # Generate all possible combinarions
154
- conditions = [ ]
155
- range = Torque ::PostgreSQL . config . inheritance . inverse_lookup \
156
- ? 0 . upto ( ns_places . size ) \
157
- : ns_places . size . downto ( 0 )
158
- range . each do |size |
159
- conditions . concat ( ns_places . combination ( size ) . to_a )
160
- end
161
-
162
- # Now iterate over
163
- while ( condition = conditions . shift )
164
- ns_places . each { |i | pieces [ i ] = condition . include? ( i ) ? '::' : '' }
165
-
166
- candidate = pieces . join
167
- candidate . prepend ( "#{ scope . name } ::" ) unless scope === Object
168
-
169
- klass = candidate . safe_constantize
170
- next if klass . nil?
171
-
172
- # Check if the class match the table name
173
- return klass if klass < ::ActiveRecord ::Base && klass . table_name == table_name
174
- end
175
- end
176
-
177
126
# Reload information about tables inheritance and dependencies, uses a
178
- # cache to not perform additional checkes
179
- def reload_inheritance_data!
127
+ # cache to not perform additional checks
128
+ def reload_inheritance_data! ( connection )
180
129
return if @inheritance_loaded
181
130
@inheritance_dependencies = connection . inherited_tables
182
131
@inheritance_associations = generate_associations
@@ -186,38 +135,15 @@ def reload_inheritance_data!
186
135
# Calculates the inverted dependency (association), where even indirect
187
136
# inheritance comes up in the list
188
137
def generate_associations
189
- return { } if @inheritance_dependencies . empty?
190
-
191
- result = Hash . new { |h , k | h [ k ] = [ ] }
192
- masters = @inheritance_dependencies . values . flatten . uniq
193
-
194
- # Add direct associations
195
- masters . map do |master |
196
- @inheritance_dependencies . each do |( dependent , associations ) |
197
- result [ master ] << dependent if associations . include? ( master )
198
- end
199
- end
200
-
201
- # Add indirect associations
202
- result . each do |master , children |
203
- children . each do |child |
204
- children . concat ( result [ child ] ) . uniq! if result . key? ( child )
205
- end
206
- end
207
-
208
- # Remove the default proc that would create new entries
209
- result . default_proc = nil
210
- result
138
+ super ( @inheritance_dependencies )
211
139
end
212
140
213
- # Use this method to also load any irregular model name. This is smart
214
- # enought to only load the sources present on this instance
215
- def prepare_data_sources
216
- super
217
- @data_sources_model_names = Torque ::PostgreSQL . config
218
- . irregular_models . slice ( *@data_sources . keys ) . map do |table_name , model_name |
219
- [ table_name , ( model_name . is_a? ( Class ) ? model_name : model_name . constantize ) ]
220
- end . to_h
141
+ # Use this method to also load any irregular model name
142
+ def prepare_data_sources ( connection = nil )
143
+ Torque ::PostgreSQL ::AR710 ? super : super ( )
144
+
145
+ sources = connection . present? ? tables_to_cache ( connection ) : @data_sources . keys
146
+ @data_sources_model_names = prepare_irregular_models ( sources )
221
147
end
222
148
223
149
end
0 commit comments