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

Use Zeitwerk for autoload/eager load paths (including plugins) #434

Merged
merged 12 commits into from
Nov 5, 2021

Conversation

jaredcwhite
Copy link
Member

@jaredcwhite jaredcwhite commented Nov 2, 2021

Closes #417

@jaredcwhite jaredcwhite added process Improve the development process for the repo SSR Dynamic rendering of Bridgetown pages labels Nov 2, 2021
@render
Copy link

render bot commented Nov 2, 2021

@render
Copy link

render bot commented Nov 2, 2021

@jaredcwhite
Copy link
Member Author

I ended up "leaking" a bit of a refactor of how project-specific subclasses of Bridgetown::Model::Base are found and instantiated relative to collection names (aka you can create a Post model for the posts collection), since this was needed by a client gig which will also rely on this PR's improvements.

@jaredcwhite
Copy link
Member Author

ACK! Somehow I messed up the plugins Markdown and replaced all mention of "gem" with "plugin" which makes no sense. Eeek! Will revert.

@ayushn21
Copy link
Member

ayushn21 commented Nov 4, 2021

This is awesome @jaredcwhite. I'd just like to discuss the code organization within the plugins folder though. As it currently stands with this PR, if I want a class in the top level namespace, I have to place it directly in the plugins directory and it can't be in a subdirectory, correct?

This is the plugins directory structure for my photo gallery website where plugin code reads JPEGs from disk, extracts EXIF data from those files, writes .yml data files from all that and then another builder generates the albums and photos pages from these data files.

├── builders
│   ├── photo_albums_builder.rb
│   └── photo_albums_generator.rb
├── helpers
│   └── hashify.rb
├── models
│   ├── album.rb
│   └── photo.rb
├── pages
│   ├── album_page.rb
│   └── photo_page.rb
└── site_builder.rb

I wouldn't mind namespacing PhotoAlbumsBuilder and PhotoAlbumsGenerator with Builders::; and AlbumPage and PhotoPage with Pages::. But I'd want all the other classes in the top level namespace but within their directories for organizational reasons.

I wonder if we should provide a slightly more opinionated directory structure out of the box? Also, it'd be great to have a config option to treat certain directories as top level. So for eg, I could set a config option so everything in plugins/helpers/ can be in the top level namespace. I believe we can use Zeitwerk's collapsed directories feature for this.

Or we could just keep things super simple and treat all direct subdirectories of plugins as "top level" and start namespacing only deeper in the hierarchy. So for eg, class Photo could be placed in plugins/models/photo.rb but Photos::Jpeg would need to be in plugins/models/photos/jpeg.rb.

Does that make sense? What do you think?

@jaredcwhite
Copy link
Member Author

@ayushn21 That definitely all makes sense. I ended up moving models in one of my projects out of plugins entirely and configuring that as a new loading folder. But I certainly don't want to be too opinionated. Maybe we could add a config option, something like this?

autoload_collapse:
- "plugins/helpers"
- "something/*/else"

@ayushn21
Copy link
Member

ayushn21 commented Nov 4, 2021

Yeah that sounds good. I think it might be worth adding an empty helpers directory to the site_template and specifying that in the config option be default? Just as a demo I suppose.

Also, maybe we could call the option autoloader_collapsed_dirs or something, but honestly not a big fan of that either and it's quite a nitpick so leave it up to your best judgement :)

@jaredcwhite
Copy link
Member Author

jaredcwhite commented Nov 4, 2021

I'll mull over the helpers thing…in the meantime I'll add the config option. Let's call it autoloader_collapsed_paths loader_collapsed_paths so it's consistent with the other loader config options which use path

@jaredcwhite
Copy link
Member Author

(I realized in Zeitwerk-speak they're called "loaders", not "autoloaders", so going with loader_collapsed_paths)

- top_level/*
```

Thus no files directly in `top_level` as well as any of its subfolders will be namespaced (that is, no `TopLevel` module will be implied).
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Might be worth adding the word "direct" just to make it a bit more clear that deeper subfolders will be namespaced.

Suggested change
Thus no files directly in `top_level` as well as any of its subfolders will be namespaced (that is, no `TopLevel` module will be implied).
Thus no files directly in `top_level` as well as any of its direct subfolders will be namespaced (that is, no `TopLevel` module will be implied).

@ayushn21
Copy link
Member

ayushn21 commented Nov 5, 2021

(I realized in Zeitwerk-speak they're called "loaders", not "autoloaders", so going with loader_collapsed_paths)

I would argue the the Bridgetown config file lives outside the context of Zeitwerk and we've got a config item called autoload_paths so we should stick with the "autoload(er)" nomenclature in the project configuration.

It's a small thing though and the docs are pretty clear so 🤷‍♂️

@jaredcwhite jaredcwhite merged commit 55ead25 into main Nov 5, 2021
@jaredcwhite jaredcwhite deleted the zeitwerk-autoload-paths branch November 5, 2021 15:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
process Improve the development process for the repo SSR Dynamic rendering of Bridgetown pages
Projects
None yet
Development

Successfully merging this pull request may close these issues.

feat: Investigate a centralized, configurable plugin autoloading system (Zeitwerk)
2 participants