Class: RailsDevelopmentBoost::LoadedFile
- Inherits:
-
Object
- Object
- RailsDevelopmentBoost::LoadedFile
show all
- Defined in:
- lib/rails_development_boost/loaded_file.rb
Defined Under Namespace
Classes: ConstantsToFiles, Files, Interdependencies
Constant Summary
collapse
- LOADED =
Files.new
- CONSTANTS_TO_FILES =
ConstantsToFiles.new
- INTERDEPENDENCIES =
Interdependencies.new
- NOW_UNLOADING =
Set.new
Instance Attribute Summary collapse
Class Method Summary
collapse
Instance Method Summary
collapse
Constructor Details
#initialize(path, constants = []) ⇒ LoadedFile
Returns a new instance of LoadedFile.
126
127
128
129
130
|
# File 'lib/rails_development_boost/loaded_file.rb', line 126
def initialize(path, constants=[])
@path = path
@constants = constants
@mtime = current_mtime
end
|
Instance Attribute Details
#constants ⇒ Object
Returns the value of attribute constants.
124
125
126
|
# File 'lib/rails_development_boost/loaded_file.rb', line 124
def constants
@constants
end
|
#path ⇒ Object
Returns the value of attribute path.
124
125
126
|
# File 'lib/rails_development_boost/loaded_file.rb', line 124
def path
@path
end
|
Class Method Details
.const_unloaded(const_name) ⇒ Object
275
276
277
|
# File 'lib/rails_development_boost/loaded_file.rb', line 275
def const_unloaded(const_name)
CONSTANTS_TO_FILES.each_file_with_const(const_name) {|file| file.delete_constant(const_name)}
end
|
.for(file_path) ⇒ Object
251
252
253
|
# File 'lib/rails_development_boost/loaded_file.rb', line 251
def for(file_path)
LOADED[file_path]
end
|
.loaded?(file_path) ⇒ Boolean
255
256
257
|
# File 'lib/rails_development_boost/loaded_file.rb', line 255
def loaded?(file_path)
LOADED.loaded?(file_path)
end
|
.loaded_constant?(const_name) ⇒ Boolean
263
264
265
|
# File 'lib/rails_development_boost/loaded_file.rb', line 263
def loaded_constant?(const_name)
CONSTANTS_TO_FILES[const_name]
end
|
.loaded_constants ⇒ Object
259
260
261
|
# File 'lib/rails_development_boost/loaded_file.rb', line 259
def loaded_constants
LOADED.constants
end
|
.relate_files(base_file, related_file) ⇒ Object
279
280
281
|
# File 'lib/rails_development_boost/loaded_file.rb', line 279
def relate_files(base_file, related_file)
LOADED[base_file].associate_with(LOADED[related_file])
end
|
.schedule_containing_file(const_name, file) ⇒ Object
271
272
273
|
# File 'lib/rails_development_boost/loaded_file.rb', line 271
def schedule_containing_file(const_name, file)
file.schedule_consts_for_unloading!
end
|
.schedule_for_unloading_files_with_const!(const_name) ⇒ Object
267
268
269
|
# File 'lib/rails_development_boost/loaded_file.rb', line 267
def schedule_for_unloading_files_with_const!(const_name)
CONSTANTS_TO_FILES.each_file_with_const(const_name) {|file| schedule_containing_file(const_name, file)}
end
|
.unload_modified! ⇒ Object
247
248
249
|
# File 'lib/rails_development_boost/loaded_file.rb', line 247
def unload_modified!
LOADED.unload_modified!
end
|
Instance Method Details
#add_constants(new_constants) ⇒ Object
137
138
139
140
|
# File 'lib/rails_development_boost/loaded_file.rb', line 137
def add_constants(new_constants)
new_constants.each {|new_constant| CONSTANTS_TO_FILES.associate(new_constant, self)}
@constants |= new_constants
end
|
#associate_to_greppable_constants ⇒ Object
160
161
162
163
164
|
# File 'lib/rails_development_boost/loaded_file.rb', line 160
def associate_to_greppable_constants ActiveSupport::Dependencies.currently_loading.each {|path| self.class.relate_files(path, self)}
add_constants(greppable_constants)
end
|
#associate_with(other_loaded_file) ⇒ Object
229
230
231
|
# File 'lib/rails_development_boost/loaded_file.rb', line 229
def associate_with(other_loaded_file)
INTERDEPENDENCIES.associate(self, other_loaded_file)
end
|
#changed? ⇒ Boolean
132
133
134
135
|
# File 'lib/rails_development_boost/loaded_file.rb', line 132
def changed?
previous_mtime, @mtime = @mtime, current_mtime
previous_mtime != @mtime
end
|
#clean_up_if_necessary ⇒ Object
222
223
224
225
226
227
|
# File 'lib/rails_development_boost/loaded_file.rb', line 222
def clean_up_if_necessary
if @constants.empty? && LOADED.stored?(self)
LOADED.delete(@path)
ActiveSupport::Dependencies.loaded.delete(require_path)
end
end
|
#decorator_like? ⇒ Boolean
“decorator” files are popular with certain Rails frameworks (spree/refinerycms etc.) they don’t define their own constants, instead they are usually used for adding methods to other classes via Model.class_eval { def meth; end }
148
149
150
|
# File 'lib/rails_development_boost/loaded_file.rb', line 148
def decorator_like?
@constants.empty? && !INTERDEPENDENCIES[self]
end
|
#delete_constant(const_name) ⇒ Object
216
217
218
219
220
|
# File 'lib/rails_development_boost/loaded_file.rb', line 216
def delete_constant(const_name)
CONSTANTS_TO_FILES.deassociate(const_name, self)
@constants.delete(const_name)
clean_up_if_necessary
end
|
#dependent_file_schedule_for_unloading!(dependent_file) ⇒ Object
202
203
204
|
# File 'lib/rails_development_boost/loaded_file.rb', line 202
def dependent_file_schedule_for_unloading!(dependent_file)
dependent_file.schedule_consts_for_unloading!
end
|
#dirname ⇒ Object
142
143
144
|
# File 'lib/rails_development_boost/loaded_file.rb', line 142
def dirname
File.dirname(@path)
end
|
#eql?(other) ⇒ Boolean
198
199
200
|
# File 'lib/rails_development_boost/loaded_file.rb', line 198
def eql?(other)
@path.eql?(other)
end
|
#greppable_constants ⇒ Object
It is important to catch all the intermediate constants as they might be “nested” constants, that are generally not tracked by AS::Dependencies. Pathological example is as follows:
File ‘a.rb` contains `class A; X = :x; end`. AS::Dependencies only associates the ’A’ const to the ‘a.rb` file (ignoring the nested ’A::X’), while a decorator file ‘b_decorator.rb` containing `B.class_eval A::X` would grep and find the `A::X` const, check that indeed it is in autoloaded namespace and associate it to itself. When `b_decorator.rb` is then being unloaded it simply does `remove_constant(’A::X’)‘ while failing to trigger the unloading of `a.rb`.
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
|
# File 'lib/rails_development_boost/loaded_file.rb', line 173
def greppable_constants
constants = []
read_greppable_constants.each do |const_name|
intermediates = nil
begin
if self.class.loaded_constant?(const_name)
constants << const_name
constants.concat(intermediates) if intermediates
break
end
(intermediates ||= []) << const_name.dup
end while const_name.sub!(/::[^:]+\Z/, '')
end
constants.uniq
end
|
#guard_double_unloading ⇒ Object
206
207
208
209
210
211
212
213
214
|
# File 'lib/rails_development_boost/loaded_file.rb', line 206
def guard_double_unloading
if NOW_UNLOADING.add?(self)
begin
yield
ensure
NOW_UNLOADING.delete(self)
end
end
end
|
#hash ⇒ Object
194
195
196
|
# File 'lib/rails_development_boost/loaded_file.rb', line 194
def hash
@path.hash
end
|
#read_greppable_constants ⇒ Object
189
190
191
|
# File 'lib/rails_development_boost/loaded_file.rb', line 189
def read_greppable_constants
File.read(@path).scan(/[A-Z][_A-Za-z0-9]*(?:::[A-Z][_A-Za-z0-9]*)*/).uniq
end
|
#require_path ⇒ Object
233
234
235
|
# File 'lib/rails_development_boost/loaded_file.rb', line 233
def require_path
File.expand_path(@path.sub(/\.rb\Z/, '')) end
|
#schedule_const_for_unloading(const_name) ⇒ Object
242
243
244
|
# File 'lib/rails_development_boost/loaded_file.rb', line 242
def schedule_const_for_unloading(const_name)
ActiveSupport::Dependencies.schedule_const_for_unloading(const_name)
end
|
#schedule_consts_for_unloading! ⇒ Object
152
153
154
155
156
157
158
|
# File 'lib/rails_development_boost/loaded_file.rb', line 152
def schedule_consts_for_unloading!
guard_double_unloading do
INTERDEPENDENCIES.each_dependent_on(self) {|dependent_file| dependent_file_schedule_for_unloading!(dependent_file)}
@constants.dup.each {|const| schedule_const_for_unloading(const)}
clean_up_if_necessary
end
end
|
#stale! ⇒ Object
237
238
239
240
|
# File 'lib/rails_development_boost/loaded_file.rb', line 237
def stale!
@mtime = 0
INTERDEPENDENCIES.each_dependent_on(self, &:stale!)
end
|