Skip to content

Commit

Permalink
Change DescendantLoader to handle non-AR classes in the models directory
Browse files Browse the repository at this point in the history
Class is patched by ActiveSupport to add the descendants method, so this change
keeps our patching of ActiveSupport consistent across the board by also patching
Class.  This was handled specifically for ActsAsArModel previously, but there
are other classes that also might need this functionality such as Authenticator.
Individually adding new classes is not maintainable and also not expected, so
this is handled generically via a patch to Class.

We still need to keep our ActiveRecord::Base patch because due to timing.  By
the time we hit the patching lines, ActiveRecord::Base has already been further
modified with ActiveSupport::DescendantsTracker via prepend, and if we were to
rely on the Class patch, then we wouldn't be able to get ahead of
DescendantsTracker.

Visually, the singleton_class' ancestors chain looks like this for Object:

    [
      #<Class:Object>,
      ...
      DescendantLoader::ArDescendantsWithLoader,
      Class,
      ...
      Object,
      ...
    ]

but looks like this for ActiveRecord::Base (if we were to rely on the
Class patch only):

    [
      #<Class:ActiveRecord::Base>,
      ...
      ActiveSupport::DescendantsTracker,
      ...
      #<Class:Object>,
      ...
      DescendantLoader::ArDescendantsWithLoader,
      Class,
      ...
      Object,
      ...
    ]

Thus ActiveSupport::DescendantsTracker's definition of descedants wins, unless
we patch ActiveRecord::Base directly.

https://bugzilla.redhat.com/show_bug.cgi?id=1537299
  • Loading branch information
Fryguy committed Jan 23, 2018
1 parent 962af5d commit 104416d
Showing 1 changed file with 5 additions and 3 deletions.
8 changes: 5 additions & 3 deletions lib/extensions/descendant_loader.rb
Original file line number Diff line number Diff line change
Expand Up @@ -267,9 +267,11 @@ def clear
end
end

ActiveRecord::Base.singleton_class.send(:prepend, DescendantLoader::ArDescendantsWithLoader)
ActiveSupport::Dependencies.send(:prepend, DescendantLoader::AsDependenciesClearWithLoader)
ActsAsArModel.singleton_class.send(:prepend, DescendantLoader::ArDescendantsWithLoader)
# Patch Class to support non-AR models in the models directory
Class.prepend(DescendantLoader::ArDescendantsWithLoader)
# Patch ActiveRecord specifically to get ahead of ActiveSupport::DescendantsTracker
# The patching of Class does not put it in the right place in the ancestors chain
ActiveRecord::Base.singleton_class.prepend(DescendantLoader::ArDescendantsWithLoader)

at_exit do
DescendantLoader.instance.save_cache!
Expand Down

0 comments on commit 104416d

Please sign in to comment.