Overring methods on engines

Hey guys,

I've been working on engines lately and I can't understand why a class in an engine can't be monkey patched. Here's an example:

In the engine:

class MyEngine::MyController < ApplicationController
  def index
    @stuff = 1
  end

  def show
    ... something happens ...
  end
end

In the app including the engine:

class MyEngine::MyController < ApplicationController
  def index
    @stuff = 2
  end
end

In this example I would expect for only the index method to be overriden, but it seems the entire class is overriden. Is there any reason for this behaviour? Is this a feature or a bug?

Regards,
Luís Ferreira

Probably because of the way how Rails is looking for constants ? I would guess that it does not read the file from engine at all, and just reads the file from your app.

Robert Pankowecki

http://robert.pankowecki.pl

Hum… Haven’t thought of that. Thanks.

Still, this is not the expected behaviour for a ruby class right? Or am I completly wrong here?

Also, even if I change the load order of the app and engine and load the engine first the same thing happens. This way the engine’s file has already been loaded and then it is completly overriden.

Maybe I’m missing something here, but this is the behavior I have experienced.

If you are using Rails 3.2, you can tell Rails to load your engine before it loads your app like so:

config.railties_order = [ Your::Engine, :main_app, :all ]

Then your monkey patching should work.

If you are on older versions of Rails you can monkey patch AS::Dependencies like http://www.slideshare.net/AndyMaleh/rails-engine-patterns (Slide 17). You probably want to watch the whole talk by Andy Maleh here.

Godfrey

I just clicked thru those slides the other day too. Having developed engines locally bundled to other applications, the part he talks about continuous development, is a dream. I found that in Bundler 1.2 you can config a repo for local usage without changing the Gemfile too.

http://gembundler.com/v1.2/whats_new.html

Gem/engine authoring has never been so good :slight_smile:

  • Ken

Also, you might want to use class_eval for monkey patching. This way it errors out if the original implementation has not been loaded yet, so you’ll know something has gone wrong. See here - http://practicalruby.blogspot.com/2007/02/reopen-with-moduleeval.html

Godfrey

Thanks for the quick response.

As I’ve said, even if I change the loading order it still won’t work.

I’ll try class_eval but still I don’t understand why the monkey patching does not work. Is it a feature of the engine that it has an all or nothing overriding of classes?