ruby-on-rails-4 - 为什么 Rails 引擎的 gem 名称必须为 "match"模块/命名空间名称?

标签 ruby-on-rails-4 module namespaces rubygems

我正在构建我的第一个 Rails 引擎。我叫它my_engine , 所以它会生成文件

lib/my_engine.rb
lib/my_engine/engine.rb
lib/my_engine/version.rb

它们都有名为 MyEngine 的模块.并且在 gemspec 中,gem 名称也设置为 my_engine .

如果我创建一个模型 my_model , 它进入 app/models/my_engine/my_model.rb , 并生成为
module MyEngine
  class MyModel < ActiveRecord::Base
  end
end

如果我在这里创建一个类方法,并将 gem 放入 Rails 项目中,一切正常。
def self.hello
  "Hello from your Engine's model!"
end

$ bundle exec rails c
[1] (pry) main: 0> MyEngine::MyModel.hello
=> "Hello from your Engine's model!"

但是,我不希望 gem 名称为 my_engine .但是,如果我将 gemspec 中的名称更改为其他名称,例如 what-i-really-want-to-name-it ,一切都停止工作。 Rails 看不到我的模型,尽管它可以看到我的命名空间。我确实正在更改 Rails 应用程序中的 gem 名称并重新捆绑,所以这不是问题。
$ bundle exec rails c
[1] (pry) main: 0> MyEngine::VERSION
=> "0.0.1"   # default version from engine generation
[2] (pry) main: 0> MyEngine::MyModel.hello
NameError: uninitialized constant MyEngine::MyModel
from (pry):2:in `__pry__'

为什么“this”直接与 gem 名称相关联?有什么解决方法吗?我真的很想让 gem 名称和模块名称成为不同的值。

使用:Rails 4.2.6、Ruby 2.3.0

最佳答案

答案是 Rails 的基本概念之一是:

Convention over configuration.



当您决定用配置覆盖约定的原则时,这就是 Rails 的反模式。是否有可能做到这一点并感到高兴并拥有一个正常工作的 Rails 应用程序?当然可以,但这不是您想要展示的代码,作为您在 Rails 应用程序上的工作示例。

因此,约定是模块名称与 gem 名称匹配。这只是一个约定,但由于约定是 Rails 镇中共同商定的法律,如果你不遵守它,你就会反模式。

添加以响应 OP 评论

Rails 引擎的典型特征是它们使用隔离的命名空间和隔离的资源。 Gems 没有,所以实际上,答案是肯定的,使用 Rails 引擎确实强制执行 gem 不存在的命名空间约定。中间件使用该命名空间来保持 main_app 在运行时与引擎分离。举两个例子来说明:

一个极端的例子:您可以将一个应用程序作为引擎安装在其自身上。命名空间将一个与另一个隔离开,因此中间件服务作用于仅由命名空间区分的正确进程。

另一个例子:2 个引擎安装在一个 main_app 上。现在基本上有 3 个应用程序正在运行。在这种情况下,您希望如何实现非常规的命名空间隔离?

所以...
是否可以在 Rails 引擎中敲入不合格的命名空间?大概。我从来没有试过。 但是您的引擎将不是可移植的。更糟糕的是,安装它的人将无法安装另一个符合要求的引擎(并共享 main_app 和中间件堆栈),因为你已经强制他们进入一个破坏传统 Rails 引擎的配置迷宫。 最后一部分是一个理论。

关于ruby-on-rails-4 - 为什么 Rails 引擎的 gem 名称必须为 "match"模块/命名空间名称?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36877210/

相关文章:

javascript - Rails 4 jQuery/Ajax 在创建后刷新并将项目添加到部分

ruby-on-rails - 用符号打印哈希值内的值

haskell - 数学|x|怎么写在 haskell ?

angular - 路由 Dart Angular Tour of Heroes 时无法找到模块

c++ - 如何正确使用命名空间避免名称冲突?

c# - StyleCop/FxCop 10 - 如何仅在命名空间级别正确抑制消息?

ruby-on-rails-4 - 使用 Rails 4 强参数处理嵌套表单的 DRY 方式

ruby-on-rails - Rails 4 - 如何在事件记录查询中为包含()和连接()提供别名

asp.net - 使用管理面板编辑网站的 DotNetNuke 皮肤 CSS

Ruby:如何将命名空间类包含到 IRB 中的全局命名空间中