Accessing helpers and models from rails engine initializer

rails engine configuration
rails engines best practices
rails engine api only
rails engine example
rails engine routes
rails engine migrations
rails::engine autoload paths
rails engine vs gem

I'm trying to make a Ruby on Rails engine, and I want the initializer to be able to have access to the helpers and models. I'll write below an example, part of the code, and the error that I have. It may not be the recommended way, because I can see that in some cases I'm repeating myself, but it's the first engine I make.

file lib/my_engine/engine.rb

module MyEngine
  require 'my_engine/functions'

  class Engine < ::Rails::Engine
    isolate_namespace MyEngine
    config.autoload_paths += %W( #{config.root}/lib )
  end

  class GlobalVars
    attr_accessor :foo
    def initialize
      @foo = MyEngine::Functions.new
    end
  end

  class << self
    mattr_accessor :GLOBAL
    mattr_accessor :USER_CONFIG

    self.GLOBAL = MyEngine::GlobalVars.new
    # add default values of more config vars here
    self.USER_CONFIG = 'default config'
  end

  def self.setup(&block)
    yield self
  end

end 

file lib/my_engine/functions.rb

module MyEngine
  require '../../app/helpers/my_engine/options_helper'

  class Functions
    include MyEngine::OptionsHelper

    attr_accessor :some_link

    def initialize
      @some_link = get_option('dummy')
    end
  end
end

There is also a controller named OptionsController in app/controllers/my_engine, and OptionsHelper in app/helpers/my_engine/options_helper.rb:

module MyEngine
  module OptionsHelper
    def get_option(name)
      MyEngine::Option.new
    end
  end
end 

When I try to run the dummy application, this error occurs:

/app/helpers/my_engine/options_helper.rb:4:in `get_option': uninitialized constant MyEngine::Option (NameError)

If I change to just Option.new, I have this error:

/app/helpers/my_engine/options_helper.rb:4:in `get_option': uninitialized constant MyEngine::OptionsHelper::Option (NameError)

For ::MyEngine::Option.new, I have:

/app/helpers/my_engine/options_helper.rb:4:in `get_option': uninitialized constant MyEngine::Option (NameError)

For ::Option.new, I have:

/app/helpers/my_engine/options_helper.rb:4:in `get_option': uninitialized constant Option (NameError)

The dummy application has nothing in it. All helpers and models defined above are in the engine.

Before this, I had other errors because it couldn't access the helper, or the Functions class. I had to add require and include to make it work even if they are placed in the same directory. Also, to work, I had to move GlobalVars from its own file inside engine.rb.

Can somebody show me what I'm doing wrong?

After I used required for every class, I ended with ActiveRecord::ConnectionNotEstablished, and it seems that not everything is loaded and available at that point when the GLOBAL object is created.

So I moved the code that was using the models in a separate init method. Then, I added an after initialize event:

  config.after_initialize do
    MyEngine.GLOBAL.init
  end

Rails::Engine, Overriding Models and Controllers; Overriding Views; Routes; Assets; Separate Without calling isolate_namespace , the engine's helpers would be included in an Create a new initializer at config/initializers/blorgh.rb inside the application � By inheriting from the Rails::Engine class, this gem notifies Rails that there's an engine at the specified path, and will correctly mount the engine inside the application, performing tasks such as adding the app directory of the engine to the load path for models, mailers, controllers, and views.

Getting Started with Engines — Ruby on Rails Guides, config/routes.rb Rails.application.routes.draw do # app routes # mount Myengine ::Engine Access engine's route from the main app view: Myengine::Engine. routes.url_helpers.articles_path Myengine/app/models/article.rb class Article < ActiveRecord::Base has_many :comments def config/initializers/assets.rb The Rails Initialization Process. This guide explains the internals of the initialization process in Rails as of Rails 3.1. It is an extremely in-depth guide and recommended for advanced Rails developers.

In my engine.rb I do

require_relative '../../app/models/my_engine/option'

maybe this will help, but it is not a nice solution.

Integrating Gem/Engine and Main Rails App � GitHub, The key thing here is to inherit from ::Rails::Engine . It will force scoping all classes (AR models, controllers, helpers etc…) about routes is accessing base application routing helpers in engine and vice versa. module FooBar class Engine < Rails::Engine isolate_namespace FooBar initializer "foo_bar",� The Rails Initialization ProcessThis guide explains the internals of the initialization process in Rails. It is an extremely in-depth guide and recommended for advanced Rails developers.After reading this guide, you will know: How to use rails server. The timeline of Rails' initialization sequence. Where different files are required by the boot sequence. How the Rails::Server interface is

Rails mountable engines, I knew about Rails engines (and, like most Rails developers, I use Almost all configurable engines expose an API like the following to be used in a Rails initializer: access to some helpers in the parent application's base controller. I created a model in the engine that belonged to the user class in the� A Rails application is actually just a “supercharged” engine, with the Rails::Application class inheriting from Rails::Engine. Therefore, engines and applications share common functionality but are at the same time two separate beasts. Engines and applications also share a common structure, as you’ll see throughout this guide.

Patterns for Successful Rails Engines, Check out this breakdown of some of the best Rails engine design patterns being model you would like to use within an initializer file, as suggested by the Rails Guide will now have access to the class methods defined in Devise::Models : the currently loaded Rails applications with Refinery's controllers and helpers. Configuring Rails ApplicationsThis guide covers the configuration and initialization features available to Rails applications.After reading this guide, you will know: How to adjust the behavior of your Rails applications. How to add additional code to be run at application start time.

A Guide to Rails Engines and Design Patterns with Examples, Building a Ruby on Rails Engine is a great way to ensure Some directories that the rails generator would have added are missing (i.e. models , helpers Alternatively, an Engine can mount itself using the same initializer� Draper: View Models for Rails. Draper adds an object-oriented layer of presentation logic to your Rails application. Without Draper, this functionality might have been tangled up in procedural helpers or adding bulk to your models.

Comments
  • There is a lot less messy way to do module configuration. If you then want to be able to do MyEngine.foo instead of MyEngine.configuration.foo then just use delegation.
  • Can you show how and where MyEngine::Option is defined? I am guessing rails is unable to guess the correct path to autoload it?
  • @nathanvda, it is in app/models/my_engine/
  • Ha I think this makes sense: the load-order of rails is something like: the initializers, the engine's initializers, and only then the rest is started .. This allows the initializers a.o. to inject code/behaviour. Good find!
  • I updated the question with the errors I have using different variants. Also, I am unable to make require to work. There will be many models in my engine, and also, many helpers, so I would like to make all of them available in the initializer. Otherwise, it works. But I need to do initialize some objects using a lot of helpers in the initializer
  • So adding the require "my_engine/option" to the top of my_engine/options_helper.rb does not work? Does it give an error?
  • options_helper.rb:1:in `require': cannot load such file -- my_engine/option (LoadError)
  • With this line require_relative '../../models/my_engine/option' the error is now at the Option class: option.rb:2:in <module:MyEngine>: uninitialized constant MyEngine::ApplicationRecord (NameError)
  • But When I run the application without creating the instance for GLOBAL in the initializer, everything works without having to write require everywhere, just like a normal application. It must be something with loading the classes for an engine.