Frage

I could not find a way to generate engines with nested namespaces under rails. Every time I do that, I basically have to edit and move around the generated files by hand. Is there really no support for nested namespaces in rails? Seems unlikely.

At the company we namespace everything like this: CompanyName::SerivceName::Module

So when I'm working on Service1, and making the engine which will be integrated into the app that customer support uses to play around with the users and data of that service on customer requests, I'd like to create that engine under CompanyName::Serive1::CustomerSupport

However rails seems to be unable to do that.

  • Using rails plugin new a::b::blah is not accepted:

    akovanm0:test avandra$ rails plugin new a::b::blah -T --dummy-path=spec/dummy --mountable --full --mountable

    Invalid plugin name a::b::blah. Please give a name which use only alphabetic or numeric or "_" characters.

  • Specifying rails plugin new a/b/blah generates an engine, but has the same output as rails plugin new blah

  • Specifying rails plugin new a_b_blah generates an engine with the literal name a_b_blah, not namespaced. (and the actual name is camelcased to ABBlah)

What I'd like to achieve is an engine whose controllers, models and views are generated under the a::b::blah namespace, and it is mountable the same way. I want all generated controllers to go under app/controllers/a/b/blah, the models to go under app/models/a/b/blah, and so on...

Is there a way to achieve this?

War es hilfreich?

Lösung

For anyone reading this in 2022, I believe later versions of Rails handle engine names with dashes as separate namespaces.

rails plugin new parent_engine-sub_engine --mountable

Will create the following engine.rb:

module ParentEngine
  module SubEngine
    class Engine < ::Rails::Engine
      isolate_namespace ParentEngine::SubEngine
    end
  end
end

Andere Tipps

You need to create engine with mountable option enabled like this, rails plugin new engine_name --mountable. It will add isolate_namespace EngineName method call in lib/engine_name/engine.rb to isolate engine namespace.

I think you can't do that :(

EDIT: Look at the bottom of the answer, I have modified the rails plugin generator just to do it :)

If you look carefully to the source (https://github.com/rails/rails/blob/5f07366bed77116dbfbb5b98d1cdf6c61b3dfc9b/railties/lib/rails/generators/rails/plugin/plugin_generator.rb#L299) you will see that the plugin name is just the basename of the destination folder.

  def original_name
    @original_name ||= File.basename(destination_root)
  end

So if you write rails plugin new a/b/c then the plugin will be created at the a/b/c subfolder in your current folder but the name will be just c :(

If you override that original_name method to return a/b/c as desired then you will need to fight both the valid_const? method (https://github.com/rails/rails/blob/5f07366bed77116dbfbb5b98d1cdf6c61b3dfc9b/railties/lib/rails/generators/rails/plugin/plugin_generator.rb#L307) that validates the format name and accepts "only alphabetic or numeric or _ characters." and the templates that creates the modules.

  def valid_const?
    if original_name =~ /[^0-9a-zA-Z_]+/
      raise Error, "Invalid plugin name #{original_name}. Please give a name which use only alphabetic or numeric or \"_\" characters."
    elsif camelized =~ /^\d/
      raise Error, "Invalid plugin name #{original_name}. Please give a name which does not start with numbers."
    elsif RESERVED_NAMES.include?(name)
      raise Error, "Invalid plugin name #{original_name}. Please give a name which does not match one of the reserved rails words."
    elsif Object.const_defined?(camelized)
      raise Error, "Invalid plugin name #{original_name}, constant #{camelized} is already in use. Please choose another plugin name."
    end
  end

I'm thinking on using a plugin template (http://edgeguides.rubyonrails.org/rails_application_templates.html) for my namespaced plugins instead :(

EDIT: I lied about what methods you would have to fight. It's not the name method, it's the templates

EDIT (II): I have modified the plugin_new folder so nested namespaces are allowed. You have it here: https://github.com/brenes/nested-plugin-generator

I would appreciate any feedback :)

Try https://github.com/T-Dnzt/Modular-Engine or create your own generator

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top