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.
97
98
99
100
101
|
# File 'lib/rails_development_boost/loaded_file.rb', line 97
def initialize(path, constants=[])
@path = path
@constants = constants
@mtime = current_mtime
end
|
Instance Attribute Details
#constants ⇒ Object
Returns the value of attribute constants.
95
96
97
|
# File 'lib/rails_development_boost/loaded_file.rb', line 95
def constants
@constants
end
|
#path ⇒ Object
Returns the value of attribute path.
95
96
97
|
# File 'lib/rails_development_boost/loaded_file.rb', line 95
def path
@path
end
|
Class Method Details
.const_unloaded(const_name) ⇒ Object
238
239
240
|
# File 'lib/rails_development_boost/loaded_file.rb', line 238
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
214
215
216
|
# File 'lib/rails_development_boost/loaded_file.rb', line 214
def for(file_path)
LOADED[file_path]
end
|
.loaded?(file_path) ⇒ Boolean
218
219
220
|
# File 'lib/rails_development_boost/loaded_file.rb', line 218
def loaded?(file_path)
LOADED.loaded?(file_path)
end
|
.loaded_constant?(const_name) ⇒ Boolean
226
227
228
|
# File 'lib/rails_development_boost/loaded_file.rb', line 226
def loaded_constant?(const_name)
CONSTANTS_TO_FILES[const_name]
end
|
.loaded_constants ⇒ Object
222
223
224
|
# File 'lib/rails_development_boost/loaded_file.rb', line 222
def loaded_constants
LOADED.constants
end
|
.relate_files(base_file, related_file) ⇒ Object
242
243
244
|
# File 'lib/rails_development_boost/loaded_file.rb', line 242
def relate_files(base_file, related_file)
LOADED[base_file].associate_with(LOADED[related_file])
end
|
.unload_containing_file(const_name, file) ⇒ Object
234
235
236
|
# File 'lib/rails_development_boost/loaded_file.rb', line 234
def unload_containing_file(const_name, file)
file.unload!
end
|
.unload_files_with_const!(const_name) ⇒ Object
230
231
232
|
# File 'lib/rails_development_boost/loaded_file.rb', line 230
def unload_files_with_const!(const_name)
CONSTANTS_TO_FILES.each_file_with_const(const_name) {|file| unload_containing_file(const_name, file)}
end
|
.unload_modified! ⇒ Object
210
211
212
|
# File 'lib/rails_development_boost/loaded_file.rb', line 210
def unload_modified!
LOADED.unload_modified!
end
|
Instance Method Details
#add_constants(new_constants) ⇒ Object
108
109
110
111
|
# File 'lib/rails_development_boost/loaded_file.rb', line 108
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
127
128
129
130
131
|
# File 'lib/rails_development_boost/loaded_file.rb', line 127
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
196
197
198
|
# File 'lib/rails_development_boost/loaded_file.rb', line 196
def associate_with(other_loaded_file)
INTERDEPENDENCIES.associate(self, other_loaded_file)
end
|
#changed? ⇒ Boolean
103
104
105
106
|
# File 'lib/rails_development_boost/loaded_file.rb', line 103
def changed?
previous_mtime, @mtime = @mtime, current_mtime
previous_mtime != @mtime
end
|
#clean_up_if_necessary ⇒ Object
189
190
191
192
193
194
|
# File 'lib/rails_development_boost/loaded_file.rb', line 189
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 }
115
116
117
|
# File 'lib/rails_development_boost/loaded_file.rb', line 115
def decorator_like?
@constants.empty? && !INTERDEPENDENCIES[self]
end
|
#delete_constant(const_name) ⇒ Object
183
184
185
186
187
|
# File 'lib/rails_development_boost/loaded_file.rb', line 183
def delete_constant(const_name)
CONSTANTS_TO_FILES.deassociate(const_name, self)
@constants.delete(const_name)
clean_up_if_necessary
end
|
#eql?(other) ⇒ Boolean
165
166
167
|
# File 'lib/rails_development_boost/loaded_file.rb', line 165
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`.
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
|
# File 'lib/rails_development_boost/loaded_file.rb', line 140
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
173
174
175
176
177
178
179
180
181
|
# File 'lib/rails_development_boost/loaded_file.rb', line 173
def guard_double_unloading
if NOW_UNLOADING.add?(self)
begin
yield
ensure
NOW_UNLOADING.delete(self)
end
end
end
|
#hash ⇒ Object
161
162
163
|
# File 'lib/rails_development_boost/loaded_file.rb', line 161
def hash
@path.hash
end
|
#read_greppable_constants ⇒ Object
156
157
158
|
# File 'lib/rails_development_boost/loaded_file.rb', line 156
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
200
201
202
|
# File 'lib/rails_development_boost/loaded_file.rb', line 200
def require_path
File.expand_path(@path.sub(/\.rb\Z/, '')) end
|
#stale! ⇒ Object
204
205
206
207
|
# File 'lib/rails_development_boost/loaded_file.rb', line 204
def stale!
@mtime = 0
INTERDEPENDENCIES.each_dependent_on(self, &:stale!)
end
|
#unload! ⇒ Object
119
120
121
122
123
124
125
|
# File 'lib/rails_development_boost/loaded_file.rb', line 119
def unload!
guard_double_unloading do
INTERDEPENDENCIES.each_dependent_on(self) {|dependent_file| unload_dependent_file(dependent_file)}
@constants.dup.each {|const| ActiveSupport::Dependencies.remove_constant(const)}
clean_up_if_necessary
end
end
|
#unload_dependent_file(dependent_file) ⇒ Object
169
170
171
|
# File 'lib/rails_development_boost/loaded_file.rb', line 169
def unload_dependent_file(dependent_file)
dependent_file.unload!
end
|