Autoload path and STI inheritance issue in Rails 2.3.9

I have two models: User and Manager. I use STI to inherit `Manager` from `User` model.

app/models/user.rb

class User < ActiveRecord::Base end

custom_lib/models/manager.rb

class Manager < User end

I have added the models in the custom directory to load path as follows:

config/environment.rb

config.autoload_path += File.join(RAILS_ROOT, "custom_lib", "models")

Every thing works as expected in development mode. In the production mode I get the following error:

The single-table inheritance mechanism failed to locate the subclass: Manager

For some reason rails is not loading the inherited classes.

To work around this issue I explicitly require the classes in an initializer.

config/initializers/custom_models.rb

Dir[File.join(RAILS_ROOT, "custom_lib", "models", "*.rb")].each do | file_name|   require(File.join(File.dirname(file_name), File.basename(file_name, ".rb"))) end

I prefer to use autoload_path. I am wondering if anybody can explain the reason for this behavior and any possible fix.

I am on Ruby 1.8.7, Rails 2.3.9, Ubuntu

The option is called "autoload_paths", guess the singular is a typo in the mail right?

In that case, please try to reproduce it in a minimal application, file a ticket with it, and assign it to me.

It is a typo, I am using autoload_paths.

I will file a bug after reproducing it in a simpler setup

-kb

Does it work if you add your path to eager_load_paths as well as autoload_paths? e.g:

  config.eager_load_paths << File.join(RAILS_ROOT, "custom_lib", "models")

It looks as though extra autoload_paths don't get added to eager_load_paths by default and autoloading is turned off when cache_classes is true.

Indeed autoloading is on in any environment, that is, the const_missing hook is always there.

fxn@halmos:~/tmp/test-autoloading ∵ cat config/application.rb require File.expand_path('../boot', __FILE__) require 'rails/all' module TestAutoloading   class Application < Rails::Application     config.autoload_paths += %W(#{config.root}/lib)   end end

fxn@halmos:~/tmp/test-autoloading ∵ cat lib/foo.rb module Foo   p Rails.env end

fxn@halmos:~/tmp/test-autoloading ∵ rails runner -e production Foo "production"

I've seen this confusion several times. Let me explain.

In production we eager load from a few places. Reason is thread-safety, and it is also COW-friendly for multi-process.

Now, since Rails eager loads model/user.rb, the User constant won't trigger const_missing in production. But const_missing is still there, and custom directories added to autoload_paths get autoloading just fine.

Yes, you're right - I was under the impression that it was turned off in production since require and autoload are inherently unsafe in threaded applications.