rails-dev-boost 0.1.1 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.markdown +240 -39
- data/VERSION +1 -1
- data/lib/rails-dev-boost.rb +1 -0
- data/lib/rails_development_boost.rb +44 -15
- data/lib/rails_development_boost/async.rb +73 -0
- data/lib/rails_development_boost/dependencies_patch.rb +245 -123
- data/lib/rails_development_boost/dependencies_patch/instrumentation_patch.rb +171 -0
- data/lib/rails_development_boost/descendants_tracker_patch.rb +2 -0
- data/lib/rails_development_boost/loadable_patch.rb +18 -0
- data/lib/rails_development_boost/loaded_file.rb +207 -30
- data/lib/rails_development_boost/observable_patch.rb +38 -0
- data/lib/rails_development_boost/reference_cleanup_patch.rb +14 -0
- data/lib/rails_development_boost/reference_patch.rb +4 -0
- data/lib/rails_development_boost/reloader.rb +51 -0
- data/lib/rails_development_boost/required_dependency.rb +36 -0
- data/lib/rails_development_boost/view_helpers_patch.rb +5 -1
- metadata +28 -26
- data/.gitignore +0 -1
- data/Rakefile +0 -52
- data/TODO.txt +0 -2
- data/init.rb +0 -3
- data/rails-dev-boost.gemspec +0 -116
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'active_support/dependencies'
|
2
|
+
|
1
3
|
module RailsDevelopmentBoost
|
2
4
|
module DependenciesPatch
|
3
5
|
module LoadablePatch
|
@@ -9,6 +11,8 @@ module RailsDevelopmentBoost
|
|
9
11
|
end
|
10
12
|
|
11
13
|
def self.apply!
|
14
|
+
return if applied?
|
15
|
+
|
12
16
|
# retain the original method in case the application overwrites it on its modules/klasses
|
13
17
|
Module.send :alias_method, :_mod_name, :name
|
14
18
|
|
@@ -34,34 +38,130 @@ module RailsDevelopmentBoost
|
|
34
38
|
end
|
35
39
|
|
36
40
|
def self.debug!
|
37
|
-
if
|
41
|
+
if applied?
|
38
42
|
InstrumentationPatch.apply!
|
39
43
|
else
|
40
44
|
@do_instrument = true
|
41
45
|
end
|
42
46
|
end
|
43
47
|
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
+
def self.async!
|
49
|
+
@async = true
|
50
|
+
end
|
51
|
+
|
52
|
+
def self.async?
|
53
|
+
@async
|
54
|
+
end
|
48
55
|
|
49
|
-
|
50
|
-
|
56
|
+
def self.applied?
|
57
|
+
ActiveSupport::Dependencies < self
|
58
|
+
end
|
51
59
|
|
60
|
+
autoload :InstrumentationPatch, 'rails_development_boost/dependencies_patch/instrumentation_patch'
|
61
|
+
|
52
62
|
mattr_accessor :constants_being_removed
|
53
63
|
self.constants_being_removed = []
|
54
64
|
|
55
65
|
mattr_accessor :explicit_dependencies
|
56
66
|
self.explicit_dependencies = {}
|
57
67
|
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
68
|
+
mattr_accessor :currently_loading
|
69
|
+
self.currently_loading = []
|
70
|
+
|
71
|
+
module Util
|
72
|
+
extend self
|
73
|
+
|
74
|
+
def anonymous_const?(mod)
|
75
|
+
anonymous_const_name?(mod._mod_name)
|
76
|
+
end
|
77
|
+
|
78
|
+
def anonymous_const_name?(const_name)
|
79
|
+
!const_name || const_name.empty?
|
80
|
+
end
|
81
|
+
|
82
|
+
def first_non_anonymous_superclass(klass)
|
83
|
+
while (klass = klass.superclass) && anonymous_const?(klass); end
|
84
|
+
klass
|
85
|
+
end
|
86
|
+
|
87
|
+
NOTHING = ''
|
88
|
+
def in_autoloaded_namespace?(const_name) # careful, modifies passed in const_name!
|
89
|
+
begin
|
90
|
+
return true if LoadedFile.loaded_constant?(const_name)
|
91
|
+
end while const_name.sub!(/::[^:]+\Z/, NOTHING)
|
92
|
+
false
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
class ModuleCache
|
97
|
+
def initialize
|
98
|
+
@classes, @modules = [], []
|
99
|
+
ObjectSpace.each_object(Module) {|mod| self << mod if relevant?(mod)}
|
100
|
+
@singleton_ancestors = Hash.new {|h, klass| h[klass] = klass.singleton_class.ancestors}
|
101
|
+
end
|
102
|
+
|
103
|
+
def each_dependent_on(mod, &block)
|
104
|
+
arr = []
|
105
|
+
each_inheriting_from(mod) do |other|
|
106
|
+
mod_name = other._mod_name
|
107
|
+
arr << other if qualified_const_defined?(mod_name) && mod_name.constantize == other
|
108
|
+
end
|
109
|
+
arr.each(&block)
|
110
|
+
end
|
111
|
+
|
112
|
+
def remove_const(const_name, object)
|
113
|
+
if object && Class === object
|
114
|
+
remove_const_from_colletion(@classes, const_name, object)
|
115
|
+
else
|
116
|
+
[@classes, @modules].each {|collection| remove_const_from_colletion(collection, const_name, object)}
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
def <<(mod)
|
121
|
+
(Class === mod ? @classes : @modules) << mod
|
122
|
+
end
|
123
|
+
|
124
|
+
private
|
125
|
+
def relevant?(mod)
|
126
|
+
const_name = mod._mod_name
|
127
|
+
!Util.anonymous_const_name?(const_name) && Util.in_autoloaded_namespace?(const_name)
|
128
|
+
end
|
129
|
+
|
130
|
+
def remove_const_from_colletion(collection, const_name, object)
|
131
|
+
if object
|
132
|
+
collection.delete(object)
|
133
|
+
else
|
134
|
+
collection.delete_if {|mod| mod._mod_name == const_name}
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
def each_inheriting_from(mod_or_class)
|
139
|
+
if Class === mod_or_class
|
140
|
+
@classes.each do |other_class|
|
141
|
+
yield other_class if other_class < mod_or_class && Util.first_non_anonymous_superclass(other_class) == mod_or_class
|
142
|
+
end
|
143
|
+
else
|
144
|
+
[@classes, @modules].each do |collection|
|
145
|
+
collection.each do |other|
|
146
|
+
yield other if other < mod_or_class || @singleton_ancestors[other].include?(mod_or_class)
|
147
|
+
end
|
148
|
+
end
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
def qualified_const_defined?(const_name)
|
153
|
+
ActiveSupport::Dependencies.qualified_const_defined?(const_name)
|
62
154
|
end
|
63
155
|
end
|
64
156
|
|
157
|
+
def unload_modified_files!
|
158
|
+
unloaded_something = unload_modified_files_internal!
|
159
|
+
load_failure = clear_load_failure
|
160
|
+
unloaded_something || load_failure
|
161
|
+
ensure
|
162
|
+
async_synchronize { @module_cache = nil }
|
163
|
+
end
|
164
|
+
|
65
165
|
def remove_explicitely_unloadable_constants!
|
66
166
|
explicitly_unloadable_constants.each { |const| remove_constant(const) }
|
67
167
|
end
|
@@ -71,26 +171,20 @@ module RailsDevelopmentBoost
|
|
71
171
|
end
|
72
172
|
|
73
173
|
# Augmented `load_file'.
|
74
|
-
def load_file_with_constant_tracking(path, *args
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
new_constants = autoloaded_constants - file_map.values.map(&:constants).flatten
|
79
|
-
|
80
|
-
# Associate newly loaded constants to the file just loaded
|
81
|
-
associate_constants_to_file(new_constants, path)
|
174
|
+
def load_file_with_constant_tracking(path, *args)
|
175
|
+
async_synchronize do
|
176
|
+
@module_cache = nil # nuking the module_cache helps to avoid any stale-class issues when the async mode is used in a console session
|
177
|
+
load_file_with_constant_tracking_internal(path, args)
|
82
178
|
end
|
83
|
-
|
84
|
-
result
|
85
179
|
end
|
86
180
|
|
87
181
|
def now_loading(path)
|
88
|
-
|
182
|
+
currently_loading << path
|
89
183
|
yield
|
90
184
|
rescue Exception => e
|
91
|
-
error_loading_file(
|
185
|
+
error_loading_file(currently_loading.last, e)
|
92
186
|
ensure
|
93
|
-
|
187
|
+
currently_loading.pop
|
94
188
|
end
|
95
189
|
|
96
190
|
def associate_constants_to_file(constants, file_path)
|
@@ -98,16 +192,13 @@ module RailsDevelopmentBoost
|
|
98
192
|
constants.map!(&:freeze)
|
99
193
|
file_path.freeze
|
100
194
|
|
101
|
-
|
102
|
-
end
|
103
|
-
|
104
|
-
def loaded_file_for(file_path)
|
105
|
-
file_map[file_path] ||= LoadedFile.new(file_path)
|
195
|
+
LoadedFile.for(file_path).add_constants(constants)
|
106
196
|
end
|
107
197
|
|
108
198
|
# Augmented `remove_constant'.
|
109
199
|
def remove_constant_with_handling_of_connections(const_name)
|
110
|
-
|
200
|
+
async_synchronize do
|
201
|
+
module_cache # make sure module_cache has been created
|
111
202
|
prevent_further_removal_of(const_name) do
|
112
203
|
unprotected_remove_constant(const_name)
|
113
204
|
end
|
@@ -116,31 +207,89 @@ module RailsDevelopmentBoost
|
|
116
207
|
|
117
208
|
def required_dependency(file_name)
|
118
209
|
# Rails uses require_dependency for loading helpers, we are however dealing with the helper problem elsewhere, so we can skip them
|
119
|
-
if
|
120
|
-
|
121
|
-
|
210
|
+
return if (curr_loading = currently_loading.last) && curr_loading =~ /_controller(?:\.rb)?\Z/ && file_name =~ /_helper(?:\.rb)?\Z/
|
211
|
+
|
212
|
+
if full_path = ActiveSupport::Dependencies.search_for_file(file_name)
|
213
|
+
RequiredDependency.new(curr_loading).related_files.each do |related_file|
|
214
|
+
LoadedFile.relate_files(related_file, full_path)
|
122
215
|
end
|
123
216
|
end
|
124
217
|
end
|
125
218
|
|
126
219
|
def add_explicit_dependency(parent, child)
|
127
|
-
(
|
220
|
+
if !Util.anonymous_const_name?(child_mod_name = child._mod_name) && !Util.anonymous_const_name?(parent_mod_name = parent._mod_name)
|
221
|
+
((explicit_dependencies[parent_mod_name] ||= []) << child_mod_name).uniq!
|
222
|
+
end
|
128
223
|
end
|
129
224
|
|
130
225
|
def handle_already_autoloaded_constants! # we might be late to the party and other gems/plugins might have already triggered autoloading of some constants
|
131
226
|
loaded.each do |require_path|
|
132
|
-
|
227
|
+
unless load_once_path?(require_path)
|
228
|
+
associate_constants_to_file(autoloaded_constants, "#{require_path}.rb") # slightly heavy-handed..
|
229
|
+
end
|
230
|
+
end
|
231
|
+
end
|
232
|
+
|
233
|
+
def in_autoload_path?(expanded_file_path)
|
234
|
+
autoload_paths.any? do |autoload_path|
|
235
|
+
autoload_path = autoload_path.to_s # handle Pathnames
|
236
|
+
expanded_file_path.starts_with?(autoload_path.ends_with?('/') ? autoload_path : "#{autoload_path}/")
|
237
|
+
end
|
238
|
+
end
|
239
|
+
|
240
|
+
def load_file_from_explicit_load(expanded_path)
|
241
|
+
unless LoadedFile.loaded?(expanded_path)
|
242
|
+
load_file(expanded_path)
|
243
|
+
if LoadedFile.loaded?(expanded_path) && (file = LoadedFile.for(expanded_path)).decorator_like?
|
244
|
+
file.associate_to_greppable_constants
|
245
|
+
end
|
133
246
|
end
|
134
247
|
end
|
135
248
|
|
136
249
|
private
|
250
|
+
def unload_modified_files_internal!
|
251
|
+
log_call
|
252
|
+
if DependenciesPatch.async?
|
253
|
+
# because of the forking ruby servers (threads don't survive the forking),
|
254
|
+
# the Async heartbeat/init check needs to be here (instead of it being a boot time thing)
|
255
|
+
Async.heartbeat_check!
|
256
|
+
else
|
257
|
+
LoadedFile.unload_modified!
|
258
|
+
end
|
259
|
+
end
|
260
|
+
|
261
|
+
def clear_load_failure
|
262
|
+
@load_failure.tap { @load_failure = false }
|
263
|
+
end
|
264
|
+
|
265
|
+
def load_file_with_constant_tracking_internal(path, args)
|
266
|
+
result = now_loading(path) { load_file_without_constant_tracking(path, *args) }
|
267
|
+
|
268
|
+
unless load_once_path?(path)
|
269
|
+
new_constants = autoloaded_constants - LoadedFile.loaded_constants
|
270
|
+
|
271
|
+
# Associate newly loaded constants to the file just loaded
|
272
|
+
associate_constants_to_file(new_constants, path)
|
273
|
+
end
|
274
|
+
|
275
|
+
result
|
276
|
+
end
|
277
|
+
|
278
|
+
def async_synchronize
|
279
|
+
if DependenciesPatch.async?
|
280
|
+
Async.synchronize { yield }
|
281
|
+
else
|
282
|
+
yield
|
283
|
+
end
|
284
|
+
end
|
285
|
+
|
137
286
|
def unprotected_remove_constant(const_name)
|
138
287
|
if qualified_const_defined?(const_name) && object = const_name.constantize
|
139
288
|
handle_connected_constants(object, const_name)
|
140
|
-
|
289
|
+
LoadedFile.unload_files_with_const!(const_name)
|
141
290
|
if object.kind_of?(Module)
|
142
291
|
remove_parent_modules_if_autoloaded(object)
|
143
|
-
remove_child_module_constants(object)
|
292
|
+
remove_child_module_constants(object, const_name)
|
144
293
|
end
|
145
294
|
end
|
146
295
|
result = remove_constant_without_handling_of_connections(const_name)
|
@@ -148,14 +297,9 @@ module RailsDevelopmentBoost
|
|
148
297
|
result
|
149
298
|
end
|
150
299
|
|
151
|
-
def unload_file(file)
|
152
|
-
file.constants.dup.each {|const| remove_constant(const)}
|
153
|
-
clean_up_if_no_constants(file)
|
154
|
-
end
|
155
|
-
alias_method :unload_modified_file, :unload_file
|
156
|
-
|
157
300
|
def error_loading_file(file_path, e)
|
158
|
-
|
301
|
+
LoadedFile.for(file_path).stale! if LoadedFile.loaded?(file_path)
|
302
|
+
@load_failure = true
|
159
303
|
raise e
|
160
304
|
end
|
161
305
|
|
@@ -164,32 +308,29 @@ module RailsDevelopmentBoost
|
|
164
308
|
remove_explicit_dependencies_of(const_name)
|
165
309
|
remove_dependent_modules(object)
|
166
310
|
update_activerecord_related_references(object)
|
311
|
+
update_mongoid_related_references(object)
|
167
312
|
remove_nested_constants(const_name)
|
168
313
|
end
|
169
314
|
|
170
315
|
def remove_nested_constants(const_name)
|
171
|
-
autoloaded_constants.grep(/\A#{const_name}::/)
|
316
|
+
autoloaded_constants.grep(/\A#{const_name}::/) { |const| remove_nested_constant(const_name, const) }
|
172
317
|
end
|
173
318
|
|
174
319
|
def remove_nested_constant(parent_const, child_const)
|
175
320
|
remove_constant(child_const)
|
176
321
|
end
|
177
322
|
|
178
|
-
def autoloaded_namespace_object?(object) # faster than going through Dependencies.autoloaded?
|
179
|
-
LoadedFile.constants_to_files[object._mod_name]
|
180
|
-
end
|
181
|
-
|
182
323
|
# AS::Dependencies doesn't track same-file nested constants, so we need to look out for them on our own.
|
183
324
|
# For example having loaded an abc.rb that looks like this:
|
184
325
|
# class Abc; class Inner; end; end
|
185
326
|
# AS::Dependencies would only add "Abc" constant name to its autoloaded_constants list, completely ignoring Abc::Inner. This in turn
|
186
327
|
# can cause problems for classes inheriting from Abc::Inner somewhere else in the app.
|
187
328
|
def remove_parent_modules_if_autoloaded(object)
|
188
|
-
unless
|
329
|
+
unless autoloaded_object?(object)
|
189
330
|
initial_object = object
|
190
331
|
|
191
332
|
while (object = object.parent) != Object
|
192
|
-
if
|
333
|
+
if autoloaded_object?(object)
|
193
334
|
remove_autoloaded_parent_module(initial_object, object)
|
194
335
|
break
|
195
336
|
end
|
@@ -201,39 +342,45 @@ module RailsDevelopmentBoost
|
|
201
342
|
remove_constant(parent_object._mod_name)
|
202
343
|
end
|
203
344
|
|
345
|
+
def autoloaded_object?(object) # faster than going through Dependencies.autoloaded?
|
346
|
+
LoadedFile.loaded_constant?(object._mod_name)
|
347
|
+
end
|
348
|
+
|
204
349
|
# AS::Dependencies doesn't track same-file nested constants, so we need to look out for them on our own and remove any dependent modules/constants
|
205
|
-
def remove_child_module_constants(object)
|
206
|
-
object.constants.each do |
|
350
|
+
def remove_child_module_constants(object, object_const_name)
|
351
|
+
object.constants.each do |child_const_name|
|
207
352
|
# we only care about "namespace" constants (classes/modules)
|
208
|
-
if
|
209
|
-
|
353
|
+
if (child_const = get_child_const(object, child_const_name)).kind_of?(Module)
|
354
|
+
# make sure this is not "const alias" created like this: module Y; end; module A; X = Y; end, const A::X is not a proper "namespacing module",
|
355
|
+
# but only an alias to Y module
|
356
|
+
if (full_child_const_name = child_const._mod_name) == "#{object_const_name}::#{child_const_name}"
|
357
|
+
remove_child_module_constant(object, full_child_const_name)
|
358
|
+
end
|
210
359
|
end
|
211
360
|
end
|
212
361
|
end
|
213
362
|
|
214
|
-
def
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
363
|
+
def get_child_const(object, child_const_name)
|
364
|
+
if local_const_defined?(object, child_const_name)
|
365
|
+
begin
|
366
|
+
object.const_get(child_const_name)
|
367
|
+
rescue NameError
|
368
|
+
# Apparently even though we get a list of constants through the native Module#constants and do a local_const_defined? check the const_get
|
369
|
+
# can still fail with a NameError (const undefined etc.)
|
370
|
+
# See https://github.com/thedarkone/rails-dev-boost/pull/33 for more details.
|
371
|
+
end
|
222
372
|
end
|
223
|
-
false
|
224
|
-
end
|
225
|
-
|
226
|
-
def remove_same_file_constants(const_name)
|
227
|
-
LoadedFile.each_file_with_const(const_name) {|file| unload_containing_file(const_name, file)}
|
228
373
|
end
|
229
374
|
|
230
|
-
def
|
231
|
-
|
375
|
+
def remove_child_module_constant(parent_object, full_child_const_name)
|
376
|
+
remove_constant(full_child_const_name)
|
232
377
|
end
|
233
378
|
|
234
379
|
def remove_explicit_dependencies_of(const_name)
|
235
380
|
if dependencies = explicit_dependencies.delete(const_name)
|
236
|
-
dependencies.
|
381
|
+
dependencies.each do |depending_const|
|
382
|
+
remove_explicit_dependency(const_name, depending_const) if LoadedFile.loaded_constant?(depending_const)
|
383
|
+
end
|
237
384
|
end
|
238
385
|
end
|
239
386
|
|
@@ -241,50 +388,21 @@ module RailsDevelopmentBoost
|
|
241
388
|
remove_constant(depending_const)
|
242
389
|
end
|
243
390
|
|
244
|
-
def clear_tracks_of_removed_const(const_name, object)
|
391
|
+
def clear_tracks_of_removed_const(const_name, object = nil)
|
245
392
|
autoloaded_constants.delete(const_name)
|
246
|
-
module_cache.
|
247
|
-
|
248
|
-
|
249
|
-
LoadedFile.each_file_with_const(const_name) do |file|
|
250
|
-
file.delete_constant(const_name)
|
251
|
-
clean_up_if_no_constants(file)
|
252
|
-
end
|
253
|
-
end
|
254
|
-
|
255
|
-
def clean_up_if_no_constants(file)
|
256
|
-
if file.constants.empty?
|
257
|
-
loaded.delete(file.require_path)
|
258
|
-
file_map.delete(file.path)
|
259
|
-
end
|
260
|
-
end
|
261
|
-
|
262
|
-
def clean_up_references(const_name, object)
|
263
|
-
ActiveSupport::Dependencies::Reference.loose!(const_name)
|
264
|
-
ActiveSupport::DescendantsTracker.delete(object)
|
393
|
+
@module_cache.remove_const(const_name, object)
|
394
|
+
LoadedFile.const_unloaded(const_name)
|
265
395
|
end
|
266
396
|
|
267
397
|
def remove_dependent_modules(mod)
|
268
|
-
|
269
|
-
modules.dup.each do |other|
|
270
|
-
next unless other < mod || other.singleton_class.ancestors.include?(mod)
|
271
|
-
next unless first_non_anonymous_superclass(other) == mod if Class === mod
|
272
|
-
next unless qualified_const_defined?(other._mod_name) && other._mod_name.constantize == other
|
273
|
-
next unless in_autoloaded_namespace?(other)
|
274
|
-
remove_dependent_constant(mod, other)
|
275
|
-
end
|
276
|
-
end
|
398
|
+
module_cache.each_dependent_on(mod) {|other| remove_dependent_constant(mod, other)}
|
277
399
|
end
|
278
400
|
|
279
401
|
def remove_dependent_constant(original_module, dependent_module)
|
280
402
|
remove_constant(dependent_module._mod_name)
|
281
403
|
end
|
282
404
|
|
283
|
-
|
284
|
-
while (klass = klass.superclass) && anonymous?(klass); end
|
285
|
-
klass
|
286
|
-
end
|
287
|
-
|
405
|
+
AR_REFLECTION_CACHES = [:@klass]
|
288
406
|
# egrep -ohR '@\w*([ck]lass|refl|target|own)\w*' activerecord | sort | uniq
|
289
407
|
def update_activerecord_related_references(klass)
|
290
408
|
return unless defined?(ActiveRecord)
|
@@ -293,30 +411,34 @@ module RailsDevelopmentBoost
|
|
293
411
|
# Reset references held by macro reflections (klass is lazy loaded, so
|
294
412
|
# setting its cache to nil will force the name to be resolved again).
|
295
413
|
ActiveRecord::Base.descendants.each do |model|
|
296
|
-
model.reflections
|
297
|
-
reflection.instance_eval do
|
298
|
-
@klass = nil if @klass == klass
|
299
|
-
end
|
300
|
-
end
|
414
|
+
clean_up_relation_caches(model.reflections, klass, AR_REFLECTION_CACHES)
|
301
415
|
end
|
302
416
|
end
|
303
417
|
|
304
|
-
|
305
|
-
|
418
|
+
MONGOID_RELATION_CACHES = [:@klass, :@inverse_klass]
|
419
|
+
def update_mongoid_related_references(klass)
|
420
|
+
if defined?(Mongoid::Document) && klass < Mongoid::Document
|
421
|
+
while (superclass = Util.first_non_anonymous_superclass(superclass || klass)) != Object && superclass < Mongoid::Document
|
422
|
+
remove_constant(superclass._mod_name) # this is necessary to nuke the @_types caches
|
423
|
+
end
|
424
|
+
|
425
|
+
module_cache.each_dependent_on(Mongoid::Document) do |model|
|
426
|
+
clean_up_relation_caches(model.relations, klass, MONGOID_RELATION_CACHES)
|
427
|
+
end
|
428
|
+
end
|
306
429
|
end
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
ObjectSpace.each_object(Module) { |mod| module_cache << mod unless anonymous?(mod) }
|
314
|
-
begin
|
315
|
-
yield module_cache
|
316
|
-
ensure
|
317
|
-
module_cache.clear
|
430
|
+
|
431
|
+
def clean_up_relation_caches(relations, klass, ivar_names)
|
432
|
+
relations.each_value do |relation|
|
433
|
+
ivar_names.each do |ivar_name|
|
434
|
+
relation.instance_variable_set(ivar_name, nil) if relation.instance_variable_get(ivar_name) == klass
|
435
|
+
end
|
318
436
|
end
|
319
437
|
end
|
438
|
+
|
439
|
+
def module_cache
|
440
|
+
@module_cache ||= ModuleCache.new
|
441
|
+
end
|
320
442
|
|
321
443
|
def prevent_further_removal_of(const_name)
|
322
444
|
return if constants_being_removed.include?(const_name)
|