CuriousMind
CuriousMind

Reputation: 34155

Rails can't find the module, if config.cache_classes = true

I have a gem which is mounted as engine in my rails app via routes.rb & Gemfile. Here are the important pieces:

Apps' Gemfile

source 'https://rubygems.org'

gem 'rails', '3.2.9'
gem 'mysql2'


group :assets do
  gem 'sass-rails'
  gem 'coffee-rails'
end
gem 'jquery-rails'
gem "common_client", path: "../common-client"

App's routes.rb

mount CommonClient::Engine => "", :as => 'shared'

gem's routes.rb

get '/register' => 'session#new_registration'

gems's SessionController

require 'common_client/session_controller_base'

class SessionController < ApplicationController

  include CommonClient::SessionControllerBase
end

gems's SessionControllerBase

module CommonClient

  module SessionControllerBase

  def new_registration
      #some code goes here
  end
end

This works just fine in development & rails is able to find CommonClient::SessionController & execute new_registration action whenever visitor hits /register route. But in Production, rails is unable to find CommonClient::SessionController & generates the following error:

$ RAILS_ENV=production rails s
=> Booting WEBrick
=> Rails 3.2.9 application starting in production on http://0.0.0.0:3000
=> Call with -d to detach
=> Ctrl-C to shutdown server
[2012-12-09 03:27:29] INFO  WEBrick 1.3.1
[2012-12-09 03:27:29] INFO  ruby 1.9.3 (2012-10-12) [x86_64-linux]
[2012-12-09 03:27:29] INFO  WEBrick::HTTPServer#start: pid=4248 port=3000
Started GET "/" for 127.0.0.1 at 2012-12-09 03:28:17 +0530
Processing by WelcomeController#index as HTML
Redirected to localhost:3000/register
Filter chain halted as :check_credentials rendered or redirected
Completed 302 Found in 267ms (ActiveRecord: 0.0ms)
Started GET "/register" for 127.0.0.1 at 2012-12-09 03:28:18 +0530

ActionController::RoutingError (uninitialized constant CommonClient::SessionController):
  vendor/bundles/ruby/1.9.1/gems/activesupport-3.2.9/lib/active_support/inflector/methods.rb:230:in `block in constantize'
  vendor/bundles/ruby/1.9.1/gems/activesupport-3.2.9/lib/active_support/inflector/methods.rb:229:in `each'
  vendor/bundles/ruby/1.9.1/gems/activesupport-3.2.9/lib/active_support/inflector/methods.rb:229:in `constantize'
  vendor/bundles/ruby/1.9.1/gems/actionpack-3.2.9/lib/action_dispatch/routing/route_set.rb:69:in `controller_reference'
  vendor/bundles/ruby/1.9.1/gems/actionpack-3.2.9/lib/action_dispatch/routing/route_set.rb:54:in `controller'
  vendor/bundles/ruby/1.9.1/gems/actionpack-3.2.9/lib/action_dispatch/routing/route_set.rb:32:in `call'
  vendor/bundles/ruby/1.9.1/gems/journey-1.0.4/lib/journey/router.rb:68:in `block in call'
  vendor/bundles/ruby/1.9.1/gems/journey-1.0.4/lib/journey/router.rb:56:in `each'
  vendor/bundles/ruby/1.9.1/gems/journey-1.0.4/lib/journey/router.rb:56:in `call'
  vendor/bundles/ruby/1.9.1/gems/actionpack-3.2.9/lib/action_dispatch/routing/route_set.rb:601:in `call'
  vendor/bundles/ruby/1.9.1/gems/railties-3.2.9/lib/rails/engine.rb:479:in `call'
  vendor/bundles/ruby/1.9.1/gems/railties-3.2.9/lib/rails/railtie/configurable.rb:30:in `method_missing'
  vendor/bundles/ruby/1.9.1/gems/journey-1.0.4/lib/journey/router.rb:68:in `block in call'
  vendor/bundles/ruby/1.9.1/gems/journey-1.0.4/lib/journey/router.rb:56:in `each'
  vendor/bundles/ruby/1.9.1/gems/journey-1.0.4/lib/journey/router.rb:56:in `call'
  vendor/bundles/ruby/1.9.1/gems/actionpack-3.2.9/lib/action_dispatch/routing/route_set.rb:601:in `call'
  vendor/bundles/ruby/1.9.1/gems/actionpack-3.2.9/lib/action_dispatch/middleware/best_standards_support.rb:17:in `call'
  vendor/bundles/ruby/1.9.1/gems/rack-1.4.1/lib/rack/etag.rb:23:in `call'
  vendor/bundles/ruby/1.9.1/gems/rack-1.4.1/lib/rack/conditionalget.rb:25:in `call'
  vendor/bundles/ruby/1.9.1/gems/actionpack-3.2.9/lib/action_dispatch/middleware/head.rb:14:in `call'
  vendor/bundles/ruby/1.9.1/gems/actionpack-3.2.9/lib/action_dispatch/middleware/params_parser.rb:21:in `call'
  vendor/bundles/ruby/1.9.1/gems/actionpack-3.2.9/lib/action_dispatch/middleware/flash.rb:242:in `call'
  vendor/bundles/ruby/1.9.1/gems/rack-1.4.1/lib/rack/session/abstract/id.rb:205:in `context'
  vendor/bundles/ruby/1.9.1/gems/rack-1.4.1/lib/rack/session/abstract/id.rb:200:in `call'
  vendor/bundles/ruby/1.9.1/gems/actionpack-3.2.9/lib/action_dispatch/middleware/cookies.rb:341:in `call'
  vendor/bundles/ruby/1.9.1/gems/activerecord-3.2.9/lib/active_record/query_cache.rb:64:in `call'
  vendor/bundles/ruby/1.9.1/gems/activerecord-3.2.9/lib/active_record/connection_adapters/abstract/connection_pool.rb:479:in `call'
  vendor/bundles/ruby/1.9.1/gems/actionpack-3.2.9/lib/action_dispatch/middleware/callbacks.rb:28:in `block in call'
  vendor/bundles/ruby/1.9.1/gems/activesupport-3.2.9/lib/active_support/callbacks.rb:405:in `_run__4296103602150594596__call__1936882885794917979__callbacks'
  vendor/bundles/ruby/1.9.1/gems/activesupport-3.2.9/lib/active_support/callbacks.rb:405:in `__run_callback'
  vendor/bundles/ruby/1.9.1/gems/activesupport-3.2.9/lib/active_support/callbacks.rb:385:in `_run_call_callbacks'
  vendor/bundles/ruby/1.9.1/gems/activesupport-3.2.9/lib/active_support/callbacks.rb:81:in `run_callbacks'
  vendor/bundles/ruby/1.9.1/gems/actionpack-3.2.9/lib/action_dispatch/middleware/callbacks.rb:27:in `call'
  vendor/bundles/ruby/1.9.1/gems/actionpack-3.2.9/lib/action_dispatch/middleware/remote_ip.rb:31:in `call'
  vendor/bundles/ruby/1.9.1/gems/actionpack-3.2.9/lib/action_dispatch/middleware/debug_exceptions.rb:16:in `call'
  vendor/bundles/ruby/1.9.1/gems/actionpack-3.2.9/lib/action_dispatch/middleware/show_exceptions.rb:56:in `call'
  vendor/bundles/ruby/1.9.1/gems/railties-3.2.9/lib/rails/rack/logger.rb:32:in `call_app'
  vendor/bundles/ruby/1.9.1/gems/railties-3.2.9/lib/rails/rack/logger.rb:16:in `block in call'
  vendor/bundles/ruby/1.9.1/gems/activesupport-3.2.9/lib/active_support/tagged_logging.rb:22:in `tagged'
  vendor/bundles/ruby/1.9.1/gems/railties-3.2.9/lib/rails/rack/logger.rb:16:in `call'
  vendor/bundles/ruby/1.9.1/gems/actionpack-3.2.9/lib/action_dispatch/middleware/request_id.rb:22:in `call'
  vendor/bundles/ruby/1.9.1/gems/rack-1.4.1/lib/rack/methodoverride.rb:21:in `call'
  vendor/bundles/ruby/1.9.1/gems/rack-1.4.1/lib/rack/runtime.rb:17:in `call'
  vendor/bundles/ruby/1.9.1/gems/activesupport-3.2.9/lib/active_support/cache/strategy/local_cache.rb:72:in `call'
  vendor/bundles/ruby/1.9.1/gems/rack-1.4.1/lib/rack/lock.rb:15:in `call'
  vendor/bundles/ruby/1.9.1/gems/rack-cache-1.2/lib/rack/cache/context.rb:136:in `forward'
  vendor/bundles/ruby/1.9.1/gems/rack-cache-1.2/lib/rack/cache/context.rb:245:in `fetch'
  vendor/bundles/ruby/1.9.1/gems/rack-cache-1.2/lib/rack/cache/context.rb:185:in `lookup'
  vendor/bundles/ruby/1.9.1/gems/rack-cache-1.2/lib/rack/cache/context.rb:66:in `call!'
  vendor/bundles/ruby/1.9.1/gems/rack-cache-1.2/lib/rack/cache/context.rb:51:in `call'
  vendor/bundles/ruby/1.9.1/gems/railties-3.2.9/lib/rails/engine.rb:479:in `call'
  vendor/bundles/ruby/1.9.1/gems/railties-3.2.9/lib/rails/application.rb:223:in `call'
  vendor/bundles/ruby/1.9.1/gems/rack-1.4.1/lib/rack/content_length.rb:14:in `call'
  vendor/bundles/ruby/1.9.1/gems/railties-3.2.9/lib/rails/rack/log_tailer.rb:17:in `call'
  vendor/bundles/ruby/1.9.1/gems/rack-1.4.1/lib/rack/handler/webrick.rb:59:in `service'
  /home/gaurish/.rvm/rubies/ruby-1.9.3-p286-perf/lib/ruby/1.9.1/webrick/httpserver.rb:138:in `service'
  /home/gaurish/.rvm/rubies/ruby-1.9.3-p286-perf/lib/ruby/1.9.1/webrick/httpserver.rb:94:in `run'
  /home/gaurish/.rvm/rubies/ruby-1.9.3-p286-perf/lib/ruby/1.9.1/webrick/server.rb:191:in `block in start_thread'


^C[2012-12-09 03:42:57] INFO  going to shutdown ...
[2012-12-09 03:42:57] INFO  WEBrick::HTTPServer#start done.
Exiting

Now, here is the interesting part. These errors goes away in production & app works just fine when I disable code caching in production.rb. by setting

config.cache_classes = false

All this makes me wonder,

  1. why rails can CommonClient::SessionController in development env but not in production env?
  2. How does setting config.cache_classes = false makes it work in production? And rails can find CommonClient::SessionController which it was not able to do earlier
  3. What I need to do when so that rails finds CommonClient::SessionController other than ugly hack of disabling code cache & reloading all code on each request?

Lastly, I have tried to explain as best I could but still something is not clear or more information is required. Please leave a comment. Thanks

Upvotes: 4

Views: 1071

Answers (2)

Chris Heald
Chris Heald

Reputation: 62668

I suspect this has to do with load order. In development mode (when cache_classes is false), Rails will load up all your unloadable classes on every request. This happens after the rest of the framework has been initialized.

By comparison, in production mode, everything is loaded up in one shot, so it's possible that your CommonClient is being loaded before some other piece of the Rails stack, and then getting hidden by the Rails load. Valery's suggestion about the ActiveSupport hooks is a good one - what does the CommonClient railtie look like? You may be able to modify your gem's railtie to load your controllers after ActionController loads, which should provide behavior much more similar to Rails' development-mode load behavior.

Upvotes: 2

Alexander Randa
Alexander Randa

Reputation: 870

Try update routes.rb like:

require 'common_client'
mount CommonClient::Engine => '/shared'

Upvotes: 1

Related Questions