4

I've done an helper for nested resource's urls

# app/urls/url.rb
module Url; end

Then

# app/urls/base.rb
module Url
  class Base
    # common code
  end
end

When I try to inherit from Url::Base, a LoadError arise:

Unable to autoload constant Base, expected xxx/app/urls/base.rb to define it

I've debugged it a little, the file is correctly sourced and the class loaded, but the check is bugged. The error seems to born in ActiveSupport::Dependencies#const_missing, when it pass Object as from_mod (<- this the variable that is expected to include the constant), instead of Url.
Try this:

Url::Base # Raise LoadError
Url::Base # Works!

I can't still understand why const_missing trigger on Object instead of Url... Some help? What I'm doing wrong?


EDIT

Ok, with more digging, I've understand what's going on. Rails search for a file's path like namespace/class_name.rb in PATH; if this file doesn't exists, it try to load the constant in the parent's module (or class), and that's why it will recurse with form_model = Object.

Iazel
  • 2,296
  • 19
  • 23
  • How do you load what is in 'app/urls'? Also: are you sure that is th exact error? Because your module is singular, yet the folder is plural. – nathanvda Jun 08 '14 at 22:19
  • If I recall it correctly, since Rails 3 every folder under 'app/' is included in PATH, so yes, it's correct. You can also see that the correct file is sourced in the exception's message, and that's why if you call it a second time, it works – Iazel Jun 08 '14 at 22:24
  • I'm stuck with the same error. Even better, if I move the class (your `urls` class for example) to `lib` folder, all works :( – André Herculano Jul 03 '16 at 08:48
  • 1
    @AndréHerculano In my case, the error was to use "urls" intead of "url" in the path. It must reflect the namespace, so if your class' full name is "Example::Test", its path must be "app/example/test.rb". Is this a little more clear? :) – Iazel Jul 04 '16 at 09:55
  • If you don't want to move things under app/lib (as maybe lib contains misc classes) you can create a directory such as app/namespaced/ and nest everything under there - eg. app/namespaced/url/base.rb (I think you will need to use 'url' in the directory name rather than 'urls' or the autoloader won't work). – Declan McGrath Sep 05 '17 at 16:03

1 Answers1

0

Ok, with more digging, I've understand what's going on. Rails search for a file's path like namespace/class_name.rb in PATH; if this file doesn't exists, it try to load the constant in the parent's module (or class), and that's why it will recurse with form_model = Object.

Iazel
  • 2,296
  • 19
  • 23