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

Rails engine support: Engine configurations impact the main app #313

Closed
jamesst20 opened this issue Jun 24, 2024 · 2 comments
Closed

Rails engine support: Engine configurations impact the main app #313

jamesst20 opened this issue Jun 24, 2024 · 2 comments

Comments

@jamesst20
Copy link

jamesst20 commented Jun 24, 2024

Hi,

First of all, thank you for this amazing gem. I have been using it for a while and it works very well!

I'm writting a Ruby on Rails gem (Rails Engine) that is meant to be installed in many applications.

My gem provides a built in administration written in Svelte and I use js-routes to handle my routing.

An issue that I am currently facing is that my Engine needs this configuration:

JsRoutes.setup do |c|
  c.application = My::Engine
  c.file = Rcf::Engine.root.join("app/frontend/rails/routes.js")
end

As soon as I install my gem in an app that also uses JsRoutes, I need to explicitly define

  c.application = Rails.application

even if it is the default settings because the gem inself overrides this configuration.

Note: The gem comes with already pre-built javascript/css assets bundled with ruby-vite so the JsRoutes configuration really no longer matter to the gem in an application.

It would be great if instead of having like a "Global" configuration we could have kind of an "Instance" configuration per engine

@jamesst20
Copy link
Author

jamesst20 commented Jun 24, 2024

In case this can be of any source of inspiration, I am able to have a ViteRuby configuration that doesn't impact any application that also uses Vite and my Gem.

ViteRuby uses the "Singleton" pattern to only have one ViteRuby instance and the configuration is under that specific instance. https://github.com/ElMassimo/vite_ruby/blob/main/vite_ruby/lib/vite_ruby.rb#L39

Out of the box indeed it wouldn't work but this provides the flexibility to do that

module MyEngine
  class Engine < ::Rails::Engine
      delegate :vite_ruby, to: :class

      def self.vite_ruby
        ViteRuby.instance
          @vite_ruby ||= ::ViteRuby.new(
            root: root,
            mode: ::Rails.application.class.module_parent.to_s == "Dummy" ? "development" : "production"
          )
      end
  end
end

module MyEngine
  module ApplicationHelper
    # Override vite helper to use our own engine instance configuration
    def vite_manifest
      ::MyEngine::Engine.vite_ruby.manifest
    end
  end
end

Edit: I figured out a workaround. I will leave open in case you have better recommendations

require "js_routes"

module MyEngine
  module Middlewares
    class JsRoutes < ::JsRoutes::Middleware
      protected

      def regenerate
        ::JsRoutes.generate!(**my_engine_configuration(false))
        ::JsRoutes.definitions!(**my_engine_configuration(true))
      end

      def my_engine_configuration(definitions)
        {
          **::JsRoutes::Configuration::DEFAULTS,
          application: MyEngine::Engine,
          module_type: definitions ? "DTS" : "ESM",
          file: MyEngine::Engine.root.join("app/frontend/rails/routes#{definitions ? 'd.ts' : '.js'}")
        }
      end
    end
  end
end

PS: Configuration could have been simplified if module_type and file_name had higher priority than opts
https://github.com/railsware/js-routes/blob/master/lib/js_routes.rb#L38

@bogdan
Copy link
Collaborator

bogdan commented Jun 26, 2024

I am open for a patch that changes priorities. It feels reasonable.

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