ruby-on-railsmodelrubygemsruby-on-rails-5ruby-on-rails-plugins

Add methods to a Rails engine model from a Rails plugin


I'm writing a Rails plugin to extend a Rails engine. Namely MyPlugin has MyEngine as a dependency.

On my Rails engine I have a MyEngine::Foo model.

I'd like to add new methods to this model so I created a file in my plugin app/models/my_engine/foo.rb which has the following code:

module MyEngine
  class Foo

        def sayhi
            puts "hi"
        end

  end
end

If I enter the Rails console on the plugin dummy application I can find MyEngine::Foo, but runnning MyEngine::Foo.new.sayhi returns

NoMethodError: undefined method `sayhi'

Why MyPlugin cannot see the updates to MyEngine::Foo model? Where am I wrong?


Solution

  • Ok, found out. To make MyPlugin aware and able to modify MyEngine models the engine must be required on the plugin engine.rb like so:

    require "MyEngine"
    
    module MyPlugin
      class Engine < ::Rails::Engine
        isolate_namespace MyPlugin
    
        # You can also inherit the ApplicationController from MyEngine
        config.parent_controller = 'MyEngine::ApplicationController'
      end
    end
    

    In order to extend MyEngine::Foo model I then had to create a file lib/my_engine/foo_extension.rb:

    require 'active_support/concern'
    
    module FooExtension
        extend ActiveSupport::Concern
    
        def sayhi
            puts "Hi!"
        end
    
        class_methods do 
            def sayhello
                puts "Hello!"
            end
        end
    end
    
    ::MyEngine::Foo(:include, FooExtension)
    

    And require it in config/initializers/my_engine_extensions.rb

    require 'my_engine/foo_extension' 
    

    Now from MyPlugin I can:

     MyEngine::Foo.new.sayhi
     => "Hi!"
     MyEngine::Foo.sayhello
     => "Hello!"
    

    See ActiveSupport Concern documentation for more details.