Skip to content

[WIP] Add support for Rails::Engine #47

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

Closed
wants to merge 2 commits into from

Conversation

zlw
Copy link
Contributor

@zlw zlw commented Sep 18, 2021

Closed in favour of #49

Don't mind me yet, just looking what's what πŸ‘€

image

Adding dry-rails to monolith Rails app works like a charm, thanks for all the work πŸ™‡β€β™‚οΈ

However, it's not so great when used with Engines :bowtie:

  • There's no way for an Engine to define its own Container
  • There's no way to not have Container for main app (sounds odd but that's actually our use case, we want to have DRY-rb setup only in one Engine)

I think each Engine should define its own Container, otherwise we're loosing whole namespace isolation that Engines provide

MainApp::Container.resolve('users.create')        #> Dry::Container::Error: Nothing registered with the key "users.create"
SuperComponent::Container.resolve('users.create') #> #<SomeComponent::Users::Create:0x00007fa6d963e368>

πŸ₯³

# /components/some_component/lib/some_component/engine.rb
module SuperComponent
  class Engine < ::Rails::Engine
    isolate_namespace SuperComponent

    initializer 'super_component.dry_container' do |_app|
      Dry::Rails::Engine.container(:super_component) do
        config.features = %i[application_contract]
        config.auto_registrar = Dry::System::AutoRegistrar
        auto_register!('domain')
      end
    end

    config.to_prepare do
      Engine.finalize!
    end

    # Code-reloading-aware finalization process
    #
    # This sets up `Container` and `Deps` constants, reloads them if this is in reloading mode,
    # and registers default components like the railtie itself or the inflector
    #
    # @api public
    #
    delegate :finalize!, to: :finalizer
    alias reload finalize!

    # Stops all configured features (bootable components)
    #
    # This is *crucial* when reloading code in development mode. Every bootable component
    # should be able to clear the runtime from any constants that it created in its `stop`
    # lifecycle step
    #
    # @api public
    delegate :stop_features, to: :finalizer

    # Exposes the container constant
    #
    # @return [Dry::Rails::Container]
    #
    # @api public
    delegate :container, to: :finalizer

    # @api private
    delegate :set_or_reload, to: :finalizer

    # @api private
    delegate :remove_constant, to: :finalizer

    private

    def finalizer
      @finalizer ||= Dry::Rails::Engine::Finalizer.new(
        railtie: self,
        app_namespace: SuperComponent,
        root_path: ::Rails.root.join('components/super_component'),
      )
    end
  end
end

# /components/some_component/domain/some_component/users/create.rb
module SuperComponent
  module Users
    class Create
    end
  end
end

Step 1: Make it (sort of) work

Add bunch of methods back by delegating to finalizer

Extract Dry::Rails::Engine to allow building separate Containers

Fix CI error

Fix specs πŸ€“ (FIXME: main-app name still hardcoded)

Make main_app name configurable

Extract Dry::Rails::Engine

Do not load Main App container if its disabled

Inject SafeParams everywhere

Clean-up codes
@zlw zlw force-pushed the zlw/engine-support branch from 97ecea1 to c1f3fe2 Compare September 18, 2021 21:35
@zlw
Copy link
Contributor Author

zlw commented Sep 19, 2021

Closing in favour of #49

@zlw zlw closed this Sep 19, 2021
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

Successfully merging this pull request may close these issues.

1 participant