2
votes

We have a concern we want to use as a mixin for our User classes. This concern is found in our separate rails engine that we use for multiple products.

Everything in this engine, we keep in the same module, which we will call MyEngine.

module MyEngine
  module EngineUser
    extend ActiveSupport::Concern
  end
end

And we are tring to include it like any other concern in our Rails Application:

class User < ActiveRecord::Base
  include MyEngine::EngineUser
  # ...
end

This causes an error where it says: (formatted some for readability)

/Users/foo/.rvm/gems/ruby-2.1.5/gems/activesupport-4.2.4/lib/active_support/dependencies.rb:495:in `load_missing_constant':

Unable to autoload constant EngineUser, expected /Users/foo/Perforce/engine_folder/app/models/concerns/engine_user.rb to define it

Which..... is the right file... <.<

If I remove the module MyEngine around the class, and form the include in User, it works just fine.

I know rails does so autoloading behind the scenes, but why isn't this working? It knows that file has the class... if I move it to engine/app/concerns it says it cant find it there. So frustrating.

2

2 Answers

3
votes

This should solve your problem. I had the same issue recently..

Take a look at the additional module, Concerns, I've added.

module MyEngine
  module Concerns
    module EngineUser
      extend ActiveSupport::Concern
    end
  end
end

# lib/my_engine/engine.rb
module MyEngine
  class Engine < ::Rails::Engine
    config.autoload_paths += %W(#{MyEngine::Engine.root}/app/models/my_engine/concerns/engine_user.rb)
    isolate_namespace MyEngine
  end
end

# app/models/user.rb
class User < ActiveRecord::Base
  include MyEngine::Concerns::EngineUser
  # ...
end

Here is the RailsGuide post that led me to the answer.

0
votes

So the answer from Justin Licata is probably the "correct" answer, but the solution that I ended up going with was as follows:

in engine_folder/lib/my_engine.rb, which is what is included as part of loading the engine, I just used the line:

Dir[File.dirname(__FILE__) + "/my_engine/concerns/**/*.rb"].each { |file| require file[0..-4]}

It certainly has some smell to it, I admit, but it lets us follow our own conventions and structure, and allows us to add folder hierarchy as needed without worrying about rails autoloading issues.

Thanks for the answers!