Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Question on File Structure Best Practices #71

Closed
dcromer opened this issue Aug 6, 2019 · 2 comments
Closed

Question on File Structure Best Practices #71

dcromer opened this issue Aug 6, 2019 · 2 comments

Comments

@dcromer
Copy link

dcromer commented Aug 6, 2019

Hi, I have question regarding the best practices for file structure (ref)

In my Rails project, I organize lengthy constant declarations into separate files in order to keep classes clean.

For example:

# app/models/foo.rb
class Foo
end

# app/models/foo/constants.rb
class Foo
  MY_CONSTANT = ...
end

# elsewhere in app
Foo::MY_CONSTANT

However, Zeitwerk doesn't like this because it maps from filenames to constants, and requires those constants to be defined (ref). So, if you try to load the code above, you'll get an error message:

Excpeted file app/models/foo/constants.rb to define constant Foo::Constants, but didn't.

The obvious solution here is to define Foo::Constants:

# app/models/foo/constants.rb
class Foo
  module Constants
    MY_CONSTANT = ...
  end
end

# elsewhere in app
Foo::Constants::MY_CONSTANT

But, I have a lot of files like foo/constants.rb, and I am lazy. Are there any other alternatives for getting zeitwerk to autoload files like this?

I appreciate the work the team has done in this gem! It's a big improvement.

@fxn
Copy link
Owner

fxn commented Aug 6, 2019

One possible solution that would flow well with everything would be to define Foo::Constants:

# app/models/foo/constants.rb
module Foo::Constants
  MY_CONSTANT = ...
end

and then include that one in Foo:

# app/models/foo.rb
module Foo
  include Constants
end

That works because to resolve Foo:: MY_CONSTANT Ruby looks the ancestors of Foo up, follows the conventions, works well with reloading.... Also, anyone opening app/models/foo.rb sees clearly that you're injecting constants into Foo.

@dcromer
Copy link
Author

dcromer commented Aug 6, 2019

Ok, so it sounds like the module has to be defined if the file exists. Thanks for the quick reply.

@dcromer dcromer closed this as completed Aug 6, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants