diff options
-rw-r--r-- | activesupport/activesupport.gemspec | 2 | ||||
-rw-r--r-- | guides/source/constant_autoloading_and_reloading.md | 81 |
2 files changed, 40 insertions, 43 deletions
diff --git a/activesupport/activesupport.gemspec b/activesupport/activesupport.gemspec index 06c0429bc5..d896ee76e6 100644 --- a/activesupport/activesupport.gemspec +++ b/activesupport/activesupport.gemspec @@ -24,5 +24,5 @@ Gem::Specification.new do |s| s.add_dependency 'json', '~> 1.7', '>= 1.7.7' s.add_dependency 'tzinfo', '~> 1.1' s.add_dependency 'minitest', '~> 5.1' - s.add_dependency 'thread_safe','~> 0.3.4' + s.add_dependency 'thread_safe','~> 0.3', '>= 0.3.4' end diff --git a/guides/source/constant_autoloading_and_reloading.md b/guides/source/constant_autoloading_and_reloading.md index 4eb9cc16ad..c552f2bfa3 100644 --- a/guides/source/constant_autoloading_and_reloading.md +++ b/guides/source/constant_autoloading_and_reloading.md @@ -1062,68 +1062,65 @@ spots. ### When Constants aren't Missed -Let's consider an `Image` model, superclass of `Hotel::Image`: +Let's consider a flight simulator. The application has a default flight model ```ruby -# app/models/image.rb -class Image -end - -# app/models/hotel/image.rb -module Hotel - class Image < Image - end +# app/models/flight_model.rb +class FlightModel end ``` -No matter which file is interpreted first, `app/models/hotel/image.rb` is -well-defined. - -Now consider a third file with this apparently harmless code: +that can be overriden by each airplane, for instance ```ruby -# app/models/hotel/poster.rb -module Hotel - class Poster < Image +# app/models/bell_x1/flight_model.rb +module BellX1 + class FlightModel < FlightModel end end -``` - -The intention is to subclass `Hotel::Image`, but which is actually the -superclass of `Hotel::Poster`? Well, it depends on the order of execution: - -1. If neither `app/models/image.rb` nor `app/models/hotel/image.rb` have been -loaded at that point, the superclass is `Hotel::Image` because Rails is told -`Hotel` is missing a constant called "Image" and loads -`app/models/hotel/image.rb`. Good. -2. If `app/models/hotel/image.rb` has been loaded at that point, the superclass -is `Hotel::Image` because Ruby is able to resolve the constant. Good. +# app/models/bell_x1/aircraft.rb +module BellX1 + class Aircraft + def initialize + @flight_model = FlightModel.new + end + end +end +``` -3. Lastly, if only `app/models/image.rb` has been loaded so far, the superclass -is `Image`. Gotcha! +The initializer wants to create a `BellX1::FlightModel` and nesting has +`BellX1`, that looks good. But if the default flight model is loaded and the +one for the Bell-X1 is not, the interpreter is able to resolve the top-level +`FlightModel` and autoloading is thus not triggered for `BellX1::FlightModel`. -The last scenario (3) may be surprising. Why isn't `Hotel::Image` autoloaded? -Because Ruby is able to resolve `Image` as a top-level constant, so -autoloading does not even get a chance. +That code depends on the execution path. -Most of the time, these kind of ambiguities can be resolved using qualified -constants. In this case we would write +These kind of ambiguities can often be resolved using qualified constants: ```ruby -module Hotel - class Poster < Hotel::Image +module BellX1 + class Plane + def flight_model + @flight_model ||= BellX1::FlightModel.new + end end end ``` -That class definition now is robust. +Also, `require_dependency` is a solution: + +```ruby +require_dependency 'bell_x1/flight_model' -It is interesting to note here that the fix works because `Hotel` is a module, and -`Hotel::Image` won’t look for `Image` in `Object` as it would if `Hotel` was a -class with `Object` in its ancestors. If `Hotel` was a class we would resort to -loading `Hotel::Image` with `require_dependency`. Furthermore, with that -solution the qualified name would no longer be necessary. +module BellX1 + class Plane + def flight_model + @flight_model ||= FlightModel.new + end + end +end +``` ### Autoloading within Singleton Classes |