4

我有一个 gem,它通过routes.rb&安装在我的 rails 应用程序中作为引擎Gemfile。以下是重要的部分:

应用程序的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"

应用的路线.rb

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

gem的路线.rb

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

gems 的SessionController

require 'common_client/session_controller_base'

class SessionController < ApplicationController

  include CommonClient::SessionControllerBase
end

gems 的SessionControllerBase

module CommonClient

  module SessionControllerBase

  def new_registration
      #some code goes here
  end
end

这在开发中工作得很好,并且 Rails 能够在访问者到达路线时找到CommonClient::SessionController并执行操作。但在生产中,rails 无法找到并生成以下错误:new_registration/registerCommonClient::SessionController

$ 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

4

2 回答 2

2

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.

于 2012-12-17T12:41:07.307 回答
1

Try update routes.rb like:

require 'common_client'
mount CommonClient::Engine => '/shared'
于 2012-12-14T16:13:37.257 回答