Search code examples
rubysequel

Chaining autoloaded classes in Ruby


I have a class, User in user.rb that will be autoloaded as needed by the following statement:

autoload :User, 'models/user.rb'

This model is shared between a few different codebases (as a Git submodule, if that makes a difference). In one such codebase, I have a need to reopen the User class and add some methods. Where this gets complicated, for me at least, is that I need the resultant, extended class to be autoloaded in place of the original class.

Is there a pattern for chaining autoloaded classes in Ruby? Something like:

autoload :User, ['models/user.rb', 'extended_models/user.rb']

Or should I be using inheritance instead of monkey-patching? I'm open to suggestions. Thanks in advance.


Solution

  • Here's what I ended up doing: my main file autoloads the extended class, then the extended class autoloads the base class. Reopening the class triggers the second autoload. Although a little clumsy, this lets me keep my base classes pristine while preserving autoloading behavior. (Autoloading is a requirement for me because the database isn't available for Sequel ORM to discover the table schemas when the app first fires up.)

    It looks like this:

    main.rb:

    autoload :User, 'extended_models/user.rb'
    

    extended_models/user.rb:

    autoload :User, '../models/user.rb'
    
    class User
      def self.from_omniauth(authhash)
        # ...
      end
    end
    

    models/user.rb:

    class User < Sequel::Model
      # ...
    end
    

    I have some helper functions that help me autoload directories of models and single models with relative paths, but this is the general idea.