including module works in development, fails at startup in production?
I've authored a module that lives in my lib
folder. I'm including it at startup by putting it in my environment.rb
file as follows
# Load the rails application
require File.expand_path('../application', __FILE__)
# Initialize the rails application
MyProject::Application.initialize!
ActiveRecord::Base.send :include, MyProject::Has::Formatter
include MyProject::EventFormatters
This works great in development but if I try to run in production mode or if I deploy my app to production I get the following stack trace when the server tries to start up:
=> Booting WEBrick
=> Rails 3.0.3 application starting in production on http://0.0.0.0:3000
=> Call with -d to detach
=> Ctrl-C to shutdown server
Exiting
C:/Ruby187/lib/ruby/gems/1.8/gems/activerecord-3.0.3/lib/active_record/base.rb:1008:in `method_missing': undefined local variable or method `has_formatter' for #<Class:0x808f830> (NameError)
from C:/Data/myproject/app/models/event.rb:2
from C:/Ruby187/lib/ruby/gems/1.8/gems/activesupport-3.0.3/lib/active_support/dependencies.rb:239:in `require'
from C:/Ruby187/lib/ruby/gems/1.8/gems/activesupport-3.0.3/lib/active_support/dependencies.rb:239:in `require'
from C:/Ruby187/lib/ruby/gems/1.8/gems/activesupport-3.0.3/lib/active_support/dependencies.rb:227:in `load_dependency'
from C:/Ruby187/lib/ruby/gems/1.8/gems/activesupport-3.0.3/lib/active_support/dependencies.rb:239:in `require'
from C:/Ruby187/lib/ruby/gems/1.8/gems/activesupport-3.0.3/lib/active_support/dependencies.rb:346:in `require_or_load'
from C:/Ruby187/lib/ruby/gems/1.8/gems/activesupport-3.0.3/lib/active_support/dependencies.rb:300:in `depend_on'
from C:/Ruby187/lib/ruby/gems/1.8/gems/activesupport-3.0.3/lib/active_support/dependencies.rb:216:in `require_dependency'
from C:/Ruby187/lib/ruby/gems/1.8/gems/railties-3.0.3/lib/rails/engine.rb:138:in `eager_load!'
from C:/Ruby187/lib/ruby/gems/1.8/gems/railties-3.0.3/lib/rails/engine.rb:137:in `each'
from C:/Ruby187/lib/ruby/gems/1.8/gems/railties-3.0.3/lib/rails/engine.rb:137:in `eager_load!'
from C:/Ruby187/lib/ruby/gems/1.8/gems/railties-3.0.3/lib/rails/engine.rb:135:in `each'
from C:/Ruby187/lib/ruby/gems/1.8/gems/railties-3.0.3/lib/rails/engine.rb:135:in `eager_load!'
from C:/Ruby187/lib/ruby/gems/1.8/gems/railties-3.0.3/lib/rails/application.rb:108:in `eager_load!'
from C:/Ruby187/lib/ruby/gems/1.8/gems/railties-3.0.3/lib/rails/application/finisher.rb:41
from C:/Ruby187/lib/ruby/gems/1.8/gems/railties-3.0.3/lib/rails/initializable.rb:25:in `instance_exec'
from C:/Ruby187/lib/ruby/gems/1.8/gems/railties-3.0.3/lib/rails/initializable.rb:25:in `run'
from C:/Ruby187/lib/ruby/gems/1.8/gems/railties-3.0.3/lib/rails/initializable.rb:50:in `run_initializers'
from C:/Ruby187/lib/ruby/gems/1.8/gems/railties-3.0.3/lib/rails/initializable.rb:49:in `each'
from C:/Ruby187/lib/ruby/gems/1.8/gems/railties-3.0.3/lib/rails/initializable.rb:49:in `run_initializers'
from C:/Ruby187/lib/ruby/gems/1.8/gems/railties-3.0.3/lib/rails/application.rb:134:in `initialize!'
from C:/Ruby187/lib/ruby/gems/1.8/gems/railties-3.0.3/lib/rails/application.rb:77:in `send'
from C:/Ruby187/lib/ruby/gems/1.8/gems/railties-3.0.3/lib/rails/application.rb:77:in `method_missing'
from C:/Data/myproject/config/environment.rb:5
from C:/Ruby187/lib/ruby/gems/1.8/gems/activesupport-3.0.3/lib/active_support/dependencies.rb:239:in `require'
from C:/Ruby187/lib/ruby/gems/1.8/gems/activesupport-3.0.3/lib/active_support/dependencies.rb:239:in `require'
from C:/Ruby187/lib/ruby/gems/1.8/gems/activesupport-3.0.3/lib/active_support/dependencies.rb:225:in `load_dependency'
from C:/Ruby187/lib/ruby/gems/1.8/gems/activesupport-3.0.3/lib/active_support/dependencies.rb:596:in `new_constants_in'
from C:/Ruby187/lib/ruby/gems/1.8/gems/activesupport-3.0.3/lib/active_support/dependencies.rb:225:in `load_dependency'
from C:/Ruby187/lib/ruby/gems/1.8/gems/activesupport-3.0.3/lib/active_support/dependencies.rb:239:in `require'
from C:/Data/myproject/config.ru:3
from C:/Ruby187/lib/ruby/gems/1.8/gems/rack-1.2.1/lib/rack/builder.rb:46:in `instance_eval'
from C:/Ruby187/lib/ruby/gems/1.8/gems/rack-1.2.1/lib/rack/builder.rb:46:in `initialize'
from C:/Data/myproject/config.ru:1:in `new'
from C:/Data/myproject/config.ru:1
Now here is the most mind boggling part of the whole thing: If I set config开发者_如何学C.cache_classes = false
in config/environments/production.rb
then I don't get that stack trace and the app behaves the same in production mode as it does dev mode!!
What about settings config.cache_classes = false
makes including a module in this fashion work in production? Am I including the module in a wrong/weird way?
Hope I'm totally, right, I'll at least present my point of view:
In development, all your classes are lazy loaded. This way, you can easily change them since they're loaded only when necessary. This means that:
MyProject::Application.initialize!
does not load module content which requires:
ActiveRecord::Base.send :include, MyProject::Has::Formatter
include MyProject::EventFormatters
which is included afterwards, it makes the whole thing working.
In production, modules and classes are really loaded => crash, they need their dependencies!
As a result, put:
ActiveRecord::Base.send :include, MyProject::Has::Formatter
include MyProject::EventFormatters
in an initializer you create in config/initializers
, call it active_record_extension.rb
for instance.
Does autoloading not work for your scenario?
# config/application.rb
config.autoload_paths += %W(#{config.root}/lib)
# lib/my_project/event_formatters.rb
module MyProject
module EventFormatters
# .. etc. ...
end
end
精彩评论