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

Creates modules for empty directories #216

Closed
fsateler opened this issue May 11, 2022 · 10 comments
Closed

Creates modules for empty directories #216

fsateler opened this issue May 11, 2022 · 10 comments

Comments

@fsateler
Copy link

fsateler commented May 11, 2022

I didn't expect that.

Example:

# asdf.rb
require 'bundler/inline'

gemfile do
  source 'https://rubygems.org'
  gem 'zeitwerk'
end

loader = Zeitwerk::Loader.for_gem
loader.setup

module Asdf
end

puts Asdf::SomeDir.class
% find .
.
./asdf
./asdf/some_dir
./asdf.rb
% ruby -r ./asdf -e '1'
Module

This of course also happens for directories that don't contain any ruby files (eg, contain only erb files). This ends up polluting namespaces a bit.

PS: thanks for this awesome gem!

@fxn
Copy link
Owner

fxn commented May 12, 2022

Thanks! :)

Yes, this is the way it works. The rules in Zeitwerk are simple: A directory is a namespace, unless you say otherwise. For example, in a Rails application app/assets or app/views are not in the autoload paths.

Zeitwerk does not even "peek" at the contents of directories, it is part of the design that it descends level by level strictly.

@fxn
Copy link
Owner

fxn commented May 12, 2022

I have added documentation about this in 30650ed.

Which is your use case?

@fsateler
Copy link
Author

Yes, this is the way it works. The rules in Zeitwerk are simple: A directory is a namespace, unless you say otherwise

Is this "only" due to simplicity, or for some other principled reason?

Which is your use case?

My use case is the usage of the Cells library. It is a view library, that encourages the creation of components (cells), which are a ruby class + one or more templates. The directory structure is something like this:

# this implements the Location::HintCell
app/cells/location/hint_cell.rb
app/cells/location/hint/show.erb

This in practice ends up creating lots of empty modules, as this would create Location::Hint, which is not used anywhere.

For example, in a Rails application app/assets or app/views are not in the autoload paths.

As you can see from my usecase, it is not a whole directory tree that is to be ignored.

@fxn
Copy link
Owner

fxn commented May 12, 2022

Is this "only" due to simplicity, or for some other principled reason?

To have clear and simple rules in a somewhat tricky subject: A directory defines a namespace. If you don't want it, you can collapse or ignore, but you do not need to (recursively) peek at their contents. You see the directory, it is a namespace. You ship a gem with a namespace where 3rd-party gems toss constants as plugins. A directory is enough, is simple and consistent.

Let me say I totally understand your surprise, this is a trade-off and it is debatable.

Regarding Cells, the linked documentation has

app/concepts/comment/cell.rb
app/concepts/comment/views/show.haml

?

@fsateler
Copy link
Author

Cells is part of an alternative framework called Trailblazer, which is organized around "concepts". In rails you usually use only the cells part: https://trailblazer.to/2.1/docs/cells.html#cells-rails

@fxn
Copy link
Owner

fxn commented May 12, 2022

I'd like to think about a solution for your use case. My question is that the documented pattern

app/concepts/comment/cell.rb
app/concepts/comment/views/show.haml

is different from your example above

app/cells/location/hint_cell.rb
app/cells/location/hint/show.erb

Which pattern should I think about?

@fsateler
Copy link
Author

Hm, does it make a difference? In the first case Comment::Views is created empty, and in the second Location::Hint is the one created. What I use is the second one you quoted FWIW.

@fxn
Copy link
Owner

fxn commented May 13, 2022

Hm, does it make a difference?

I was looking for ignore patterns, and wanted to focus on the exact naming convention for view directories. However, your use case has been the last drop to reconsider this compromise:

  1. I don't find a good solution to your project layout with the current features.
  2. I have seen in the docs individual cells can override the convention.
  3. That layout worked in Rails applications with the previous autoloader and did not result in the definition of these artificial namespaces.
  4. Uses cases like tasks directories that only contain Rake tasks already challenged this trade-off in practice.
  5. Conceptually, you can definitely argue that a directory that does not contain Ruby files is not meant to be a Ruby namespace.
  6. Empty directories are a rare edge case in a gray area, but considering all of the above, maybe we can move them to the other side of the gray spectrum :).

This has been implemented in 68976b6.

@fxn fxn closed this as completed May 13, 2022
@fsateler
Copy link
Author

Thanks again for maintaining this very important gem!

@fxn
Copy link
Owner

fxn commented Jun 13, 2022

Hey! This shipped with the just released 2.6.0.

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