komposable / komponent

An opinionated way of organizing front-end code in Ruby on Rails, based on components
http://komponent.io
MIT License
427 stars 31 forks source link

Zeitwerk compatibility #148

Closed aldhsu closed 2 months ago

aldhsu commented 4 years ago

Are there any tips for making components compatible with Zeitwerks name expectations?

Related to this issue https://github.com/komposable/komponent/issues/117

The error I'm seeing is like this:

ActionView::Template::Error:
       expected file /Users/allen.hsu/Code/komponent-namespace/frontend/components/users/avatar/users_avatar_component.rb to define constant Users::Avatar::UsersAvatarComponent, but didn't

This dependent on test ordering I don't actually see it in development. However it is reproducible by loading the view twice in the test.

I have considered:

  1. Using a custom inflector - you can't inflect the paths leading up to the component that turns into the module path
  2. Monkey patch Komponent until something lands for #117
    • this requires renaming all the modules as well
  3. Don't autoload the components
    • changes to a components rb file requires server restarts
    • I am investigating not autoloading or eagerloading in tests
aldhsu commented 4 years ago

I have settled on disabling autoloading for frontend in tests for now.

aldhsu commented 4 years ago

Actually tried to deploy this but similar issues cropped up in production.

danieldocki commented 4 years ago

I have same issues.

Spone commented 4 years ago

Hi @aldhsu thanks for opening this issue. Actually we haven't been using Komponent in Rails 6 yet, so I'm not really informed to debug this.

I'd be happy to move on with #117 if it solves this issue at the same time.

We're welcoming any contribution :)

nicolas-brousse commented 4 years ago

Hi @aldhsu we have the same issue here on Rails 6 with Zeitwerks.

I start investigating on my side too.

And, I think the following should resolve the issue.

config.paths.add "frontend/components", eager_load: true, glob: "*".

Before change:

% abr zeitwerk:check 
Hold on, I am eager loading the application.
expected file frontend/components/alert/alert_component.rb to define constant Alert::AlertComponent

After:

% abr zeitwerk:check
Hold on, I am eager loading the application.
All is good!

I'll try it on production tomorrow. Let me know if you do some tries in your side.
Also I'm not sure if it's compatible with Rails < 6.0

nicolas-brousse commented 4 years ago

I just deployed and it seems to works 🎉

aldhsu commented 4 years ago

Ok @nicolas-brousse I'll give it a go. Is that only in production?

nicolas-brousse commented 4 years ago

I've to check, but my coworker adds some issues on development too. Ruby part of component was loaded but didn't seems to reload code on changes. He adds to restart is server on component changes.

I'll try to do more test tomorrow.

nicolas-brousse commented 4 years ago

It seems to resolve the issue in development too, on our side.

nicolas-brousse commented 4 years ago

I have to double check, but this fix seems to resolve issue only for component without namespace unfortunately ...

nicolas-brousse commented 4 years ago

Zeitwerk release 2.3.0 added #collapse. Maybe it may help us.

https://github.com/fxn/zeitwerk#collapsing-directories

GeoffTidey commented 3 years ago

Hi. Bit of a workaround, but this is working for me atm on Rails 6 with zeitwerk 2.4.0

module MyApp 
  class Application < Rails::Application
    config.i18n.load_path += Dir[config.root.join('frontend/components/**/*.*.yml')]
    config.paths.add 'frontend/components', eager_load: true, glob: '*'
    # Initialize configuration defaults for originally generated Rails version.
    config.load_defaults 6.0

    overrides = Rails.root.join('frontend/components/komponent')
    Rails.autoloaders.main.ignore(overrides)
    config.to_prepare do
      Dir.glob("#{overrides}/**/*.rb").each do |override|
        load override
      end
    end

    # Settings in config/environments/* take precedence over those specified here.
    # Application configuration can go into files in config/initializers
    # -- all .rb files in that directory are automatically loaded after loading
    # the framework and any gems in your application.
  end
end