views:

144

answers:

2

I have a gem:

# in /Library/Ruby/Gems/1.8/gems/my_gem-1.0.0/lib/my_gem.rb
module MyGem
  def do_stuff
    ..
  end
end

And I loaded it in Rails:

# in [rails_root]/config/environment.rb:
config.gem 'my_gem', :version => '1.0.0'

And used it:

# in [rails_root]/app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
  include MyGem
end

But I need to monkey-patch it a bit in an environment-specific way:

# in [rails_root]/config/environments/development.rb:
MyGem.class_eval do
  def do_stuff
    raise 'Ack! - just testing'
  end
end

Unfortunately, MyGem reloads on every request, so my monkey-patching is useless.

I've checked load_once_paths:

ActiveSupport::Dependencies.load_once_paths
# => ["/Library/Ruby/Gems/1.8/gems/my_gem-1.0.0/lib", "other stuff"]

Any idea how I can get the effect I want?

A: 

If you're including the gem in your environment.rb you shouldn't need to include it in your controller.

You might want to think about how the gem hooks into ActionController - it sounds like you want to add class methods to ActionController::Base, which is quite straightforward. Have a look at how many common gems implement this.

It sounds too, like you might even want to check for the existence & value of RAILS_ENV to ensure different behaviour for different environments.

mylescarrick
I'm _requiring_ it (implicitly) in environment.rb; I'm _including_ it in ApplicationController. Those are very different actions. What I'm wondering is why Rails reloads the gem each time it reloads ApplicationController. The proof that it does so is that my monkey-patching goes away.
James A. Rosen
+3  A: 

Seems you are working in development mode where Rails loads all classes in every request to help the developer to reflect the code changes + you have included the gem in your controller. To overcome this go to project_path/config/environments/development.rb and add this line

config.cache_classes = true

Notice that you won't have your code changes reflected unless you restart the server.

Update 1: Also as a second solution you can add the moneky patch after you you include the gem in that controller. You can add it to the bottom of your controller file.

Update 2: A third solution (recommended) If you can add the following snippet to my_gem.rb

class ActionController::Base
  include MyGem
end

then things should work as you won't need to manually include it in your application controller.

khelll