Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why do includes in Rails Engine initializers malfunction when cache_classes = false?

I have an Engine which is extending another Engine's classes in its initializers like so:

module MyApp
    class Engine < ::Rails::Engine
        initializer 'extend Product' do
            AnotherApp::Product.send :include, MyApp::ProductExtender
        end
    end
end

The ProductExtendermodule calls some methods on the AnotherApp::Product when it is included, e.g.

module ProductExtender
    def self.included( model )
        model.send :include, MethodsToCall
    end

    module MethodsToCall
        def self.included( m )
            m.has_many :variations
        end
    end
end

This works in test and production environments, but when config.cache_classes = false, it throws a NoMethodError at me when I try to call something defined by the ProductExtender, like @product.variations.

Needless to say, it is chilling to see all my tests pass and then get slammed with an error in development. It doesn't happen when I set cache_classes = true, but it makes me wonder if I'm doing something I shouldn't be.

My question is twofold: Why is this happening, and is there a better way I should be achieving this functionality of extending/calling methods on another application's object?

Thanks all!

like image 876
jrh Avatar asked May 02 '11 00:05

jrh


1 Answers

I managed to solve this problem using a to_prepare block instead of the initializer. The to_prepare block executes once in production and before each request in development, so seems to meet our needs.

It wasn't obvious when I was researching Rails::Engine since it is inherited from Rails::Railtie::Configuration.

So instead of the code in the question, I would have:

module MyApp
    class Engine < ::Rails::Engine
        config.to_prepare do
            AnotherApp::Product.send :include, MyApp::ProductExtender
        end
    end
end
like image 182
jrh Avatar answered Sep 19 '22 08:09

jrh