从 rails 引擎初始化程序访问助手和模型

Accessing helpers and models from rails engine initializer

我正在尝试在 Rails 引擎上创建一个 Ruby,我希望初始化程序能够访问助手和模型。
我将在下面写一个示例、部分代码和我遇到的错误。这可能不是推荐的方式,因为我可以看到在某些情况下我在重复自己,但这是我制作的第一个引擎。

文件lib/my_engine/engine.rb

module MyEngine
  require 'my_engine/functions'

  class Engine < ::Rails::Engine
    isolate_namespace MyEngine
    config.autoload_paths += %W( #{config.root}/lib )
  end

  class GlobalVars
    attr_accessor :foo
    def initialize
      @foo = MyEngine::Functions.new
    end
  end

  class << self
    mattr_accessor :GLOBAL
    mattr_accessor :USER_CONFIG

    self.GLOBAL = MyEngine::GlobalVars.new
    # add default values of more config vars here
    self.USER_CONFIG = 'default config'
  end

  def self.setup(&block)
    yield self
  end

end 

文件lib/my_engine/functions.rb

module MyEngine
  require '../../app/helpers/my_engine/options_helper'

  class Functions
    include MyEngine::OptionsHelper

    attr_accessor :some_link

    def initialize
      @some_link = get_option('dummy')
    end
  end
end

app/controllers/my_engine中还有一个名为OptionsController的控制器,在app/helpers/my_engine/options_helper中还有一个名为OptionsHelper的控制器.rb:

module MyEngine
  module OptionsHelper
    def get_option(name)
      MyEngine::Option.new
    end
  end
end 

当我尝试 运行 虚拟应用程序时,出现此错误:

/app/helpers/my_engine/options_helper.rb:4:in `get_option': uninitialized constant MyEngine::Option (NameError)

如果我只更改为 Option.new,我会出现以下错误:

/app/helpers/my_engine/options_helper.rb:4:in `get_option': uninitialized constant MyEngine::OptionsHelper::Option (NameError)

对于::MyEngine::Option.new,我有:

/app/helpers/my_engine/options_helper.rb:4:in `get_option': uninitialized constant MyEngine::Option (NameError)

对于::Option.new,我有:

/app/helpers/my_engine/options_helper.rb:4:in `get_option': uninitialized constant Option (NameError)

虚拟应用程序中没有任何内容。上面定义的所有助手和模型都在引擎中。

在此之前,我遇到了其他错误,因为它无法访问助手,或者 Functions class。我必须添加 require 和 include 才能使其工作,即使它们被放置在同一目录中也是如此。此外,为了工作,我必须从 engine.rb.

中的自己的文件中移动 GlobalVars

谁能告诉我哪里做错了?

我看到一个可能的问题:因为你在模块 MyEngine 中,所以 rails 可能正在寻找 MyEngine::MyEngine::Option,所以我看到两种方法:

  • 只需写 Option:这将查找 MyEngine::Option
  • 写入 ::MyEngine::Option 这将在全局命名空间中查找并找到 MyEngine::Option

其次,如果这没有帮助,即使您的路径看起来是正确的,但您始终可以在文件顶部明确 require "my_engine/option"。我不完全确定引擎中的自动加载以完全相同的方式工作,而且我倾向于在我的 engine 文件中要求几乎所有内容(以确保它工作)。

在我的 engine.rb 我做

require_relative '../../app/models/my_engine/option'

也许这会有所帮助,但这不是一个好的解决方案。

在我为每个 class 使用 required 之后,我以 ActiveRecord::ConnectionNotEstablished 结束,似乎在创建 GLOBAL 对象时并非所有内容都已加载和可用。

所以我将使用模型的代码移到了单独的 init 方法中。然后,我添加了一个初始化后事件:

  config.after_initialize do
    MyEngine.GLOBAL.init
  end