80

Would it be possible to have something like this?

app/models/
app/models/users/user.rb
app/models/users/education.rb

The goal is to organize the /app/models folder better, but without having to namespace the models.

An unanswered question for Rails 3 is here: Rails 3.2.9 and models in subfolders.

Specifying table_name with namespaces seems to work (see Rails 4 model subfolder), but I want to do this without a namespace.

2
  • I understood that you dont want namespace, but i think the best way to do that is using ActiveSupport Concerns.
    – Nando
    Nov 28, 2013 at 18:43
  • 2
    @NandoSousa. No. ActiveSupport Concerns are for shared behaviour. The way you use models.
    – berkes
    Jun 16, 2015 at 15:36

1 Answer 1

116

By default, Rails doesn't add subfolders of the models directory to the autoload path. Which is why it can only find namespaced models -- the namespace illuminates the subdirectory to look in.

To add all subfolders of app/models to the autoload path, add the following to config/application.rb:

config.autoload_paths += Dir[Rails.root.join("app", "models", "{*/}")]

Or, if you have a more complex app/models directory, the above method of globing together all subfolders of app/models may not work properly. In which case, you can get around this by being a little more explicit and only adding the subfolders that you specify:

config.autoload_paths += Rails.root.join("app", "models", "<my_subfolder_name1>")
config.autoload_paths += Rails.root.join("app", "models", "<my_subfolder_name2>")

UPDATE for Rails 4.1+

As of Rails 4.1, the app generator doesn't include config.autoload_paths by default. So, note that the above really does belong in config/application.rb.

UPDATE

Fixed autoload path examples in the above code to use {*/} instead of {**}. Be sure to read muichkine's comment for details on this.

8
  • 6
    Tried it but it fails with a Unable to autoload constant User::Credits, expected /srv/books/app/models/user/credits.rb to define it. So it still wan't the files to be named spaced. Placed them above the lib entry as suggested.
    – Rubytastic
    Sep 21, 2013 at 18:36
  • 1
    This error is actually good news. It means it found the file. But, you're using an odd pluralization here. If your file name is app/models/user/credits.rb then make sure the class name in the file is also plural: class Credits. But, I would recommend to use the Rails standard and make it class Credit and the file name be app/models/user/credit.rb (models should be singular). Either way, this should be the problem. Let me know!
    – pdobb
    Sep 21, 2013 at 18:44
  • 1
    In Rails 4.1 config I use config.autoload_paths += %W( #{Rails.root}/app/models/namespace #{Rails.root}/app/models/other_namespace )
    – Epigene
    Apr 2, 2015 at 8:08
  • 14
    config.autoload_paths += Dir[Rails.root.join('app', 'models', '{**}')] works but slows the application down, specially in development mode where the app is reloaded often. The reason is that you must not add all the files to the autoload_paths but only the root folders where then file names and modules can be inferred from. In simple termes, if you have only one level of subfolders into models and no namespace models, you should only do config.autoload_paths += Dir[Rails.root.join('app', 'models', '*/')] which adds only the first level of sub directories. Same for lib or other paths.
    – muichkine
    Oct 14, 2015 at 14:16
  • 3
    @pdobb it's experience :) if you look at how auto loading works you will see that it loops at all auto_loading_paths to which it adds the inference for the model. For instance if you have NameSpace::Model it will try to find in all the autoloading_paths a path/namespace/model. This can obviously match only when path is a directory. As a rule of thumb, you should only have directories in the autoload_paths for maximum efficiency. Hope it helps.
    – muichkine
    Oct 14, 2015 at 15:52

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.