Xero
Xero

Reputation: 4175

Rails autoload don't load module

In my rails app, I have a custom directory in app/entities/keycard_generator/

I have a data_source.rb (a module) and register_keycard.rb (a class)

module DataSource
  ...
end

class RegisterKeycard
  include DataSource
...
end

I have added this line in my application.rb, to autoload the path.

Dir[Rails.root.join('app/entities/keycard_generator/**/*.rb')].each(&method(:require))

But I get this errors (cannot run rails) :

uninitialized constant RegisterKeycard::DataSource (NameError)

Edit

I think that the issue is only with modules

Upvotes: 2

Views: 709

Answers (2)

jvillian
jvillian

Reputation: 20263

Given that you have:

app/entities/keycard_generator/data_source.rb

Then the content of that file, by convention, should be:

module KeycardGenerator
  module DataSource
    ...
  end
end

Because rails essentially ignores the directory name under app (here, entities) in terms of naming:

app/entities/keycard_generator/data_source.rb
    ^^^^^^^^

But expects the directory name under the directory under app (here, keycard_generator) to be a module name:

app/entities/keycard_generator/data_source.rb
             ^^^^^^^^^^^^^^^^^

And given that you have:

app/entities/keycard_generator/register_keycard.rb

Then the content of that file, by convention, should be:

module KeycardGenerator
  class RegisterKeycard 
    include DataSource
  end
end

When following the convention, you do not need:

Dir[Rails.root.join('app/entities/keycard_generator/**/*.rb')].each(&method(:require))

Personally, I like to append the type (here, indicated by entities) to the files and modules/classes, like:

app/entities/keycard_generator/data_source_entity.rb
module KeycardGenerator
  module DataSourceEntity
    ...
  end
end

Which is how rails often (e.g., with controller) but not always (e.g., with model) does it.

In which case you would also do:

app/entities/keycard_generator/register_keycard_entity.rb
module KeycardGenerator
  class RegisterKeycardEntity
    include DataSourceEntity
  end
end

Upvotes: 1

mrzasa
mrzasa

Reputation: 23307

Mark the included module as global by prefixing the name with ::

class RegisterKeycard
  include ::DataSource
...
end

Upvotes: 0

Related Questions