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
fxn
(Xavier Noria)
October 23, 2010, 9:39am
2
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.
fxn
(Xavier Noria)
October 26, 2010, 8:39am
5
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"
fxn
(Xavier Noria)
October 26, 2010, 8:48am
6
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.