You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: guides/source/autoloading_and_reloading_constants.md
+52-25Lines changed: 52 additions & 25 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -314,44 +314,71 @@ Single Table Inheritance is a feature that doesn't play well with lazy loading.
314
314
315
315
In a sense, applications need to eager load STI hierarchies regardless of the loading mode.
316
316
317
-
Of course, if the application eager loads on boot, that is already accomplished. When it does not, there are two options.
318
-
319
-
### Enumerate the leaves of the hierarchy
320
-
321
-
Since the leaves of the hierarchy connect all the hierarchy nodes upwards, following super classes, as soon as the root of the hierarchy is loaded, you can force loading them all:
317
+
Of course, if the application eager loads on boot, that is already accomplished. When it does not, it is in practice enough to instantiate the existing types in the database, which in development or test modes is usually fine. One way to do that is to include an STI preloading module in your `lib` directory:
# Constantizes all types present in the database. There might be more on
335
+
# disk, but that does not matter in practice as far as the STI API is
336
+
# concerned.
337
+
#
338
+
# Assumes store_full_sti_class is true, the default.
339
+
defpreload_sti
340
+
types_in_db = \
341
+
base_class.
342
+
unscoped.
343
+
select(inheritance_column).
344
+
distinct.
345
+
pluck(inheritance_column).
346
+
compact
347
+
348
+
types_in_db.each do |type|
349
+
logger.debug("Preloading STI type #{type}")
350
+
type.constantize
351
+
end
352
+
353
+
self.preloaded =true
354
+
end
355
+
end
329
356
end
330
357
end
331
358
```
332
359
333
-
This approach is easy and loads the entire STI hierarchy, but you need to maintain this list by hand. This may be OK.
360
+
and then include it in the STI root classes of your project:
334
361
335
-
### Load what's in the database
362
+
```ruby
363
+
# app/models/shape.rb
364
+
require"sti_preload"
336
365
337
-
As far as Active Record is concerned, in practice it may be enough to load what's in the database. Normally, in the environments where eager load is disabled, you can afford this query:
366
+
classShape < ApplicationRecord
367
+
includeStiPreload# Only in the root class.
368
+
end
369
+
```
338
370
339
371
```ruby
340
-
# config/initializers/preload_stis.rb
341
-
unlessRails.application.config.eager_load
342
-
Rails.autoloaders.main.on_load("RootSTIModel") do |klass|
This approach does not need manual maintenance. However, if you need an exhaustive enumeration to fill a dropdown or something, and the database does not have rows for all types, you'll miss some.
0 commit comments