Search code examples
ruby-on-railsrubyrails-engines

Rails engines extending functionality


I have an engine which defines some models and controllers. I want to be able to extend functionality of some models/controllers in my application (eg. adding methods) without loosing the original model/controller functionality from engine. Everywhere I read that you simply need to define controller with the same name in your application and Rails will automatically merge them, however it doesn't work for me and controller in engine is simply ignored (I don't think it's even loaded).


Solution

  • Just if anyone else runs into same issue some time in the future, this is the code I wrote that fixed my problem:

    module ActiveSupport::Dependencies
      alias_method :require_or_load_without_multiple, :require_or_load
      def require_or_load(file_name, const_path = nil)
        if file_name.starts_with?(RAILS_ROOT + '/app')
          relative_name = file_name.gsub(RAILS_ROOT, '')
          @engine_paths ||= Rails::Initializer.new(Rails.configuration).plugin_loader.engines.collect {|plugin| plugin.directory }
          @engine_paths.each do |path|
            engine_file = File.join(path, relative_name)
            require_or_load_without_multiple(engine_file, const_path) if File.file?(engine_file)
          end
        end
        require_or_load_without_multiple(file_name, const_path)
      end
    end
    

    This will automatically require files from engine before requiring from application if file path starts with 'app'.