【问题标题】:Accessing helpers and models from rails engine initializer从 Rails 引擎初始化程序访问帮助程序和模型
【发布时间】:2020-03-10 09:06:41
【问题描述】:

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

文件 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.rb 中还有一个名为 OptionsHelper 的控制器:: p>

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 类。即使将它们放在同一目录中,我也必须添加 require 和 include 才能使其工作。此外,为了工作,我必须将 GlobalVars 从 engine.rb 中自己的文件中移出。

谁能告诉我我做错了什么?

【问题讨论】:

  • module configuration 的操作方法少了很多。如果您希望能够使用MyEngine.foo 而不是MyEngine.configuration.foo,那么只需使用委托。
  • 您能说明MyEngine::Option 的定义方式和位置吗?我猜 rails 无法猜出自动加载它的正确路径?
  • @nathanvda,在app/models/my_engine/

标签: ruby-on-rails rails-engines


【解决方案1】:

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

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

  config.after_initialize do
    MyEngine.GLOBAL.init
  end

【讨论】:

  • 哈我认为这是有道理的:rails 的加载顺序类似于:初始化程序,引擎的初始化程序,然后才启动其余的程序。这允许初始化程序 a.o.注入代码/行为。很好的发现!
【解决方案2】:

在我的engine.rb 我愿意

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

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

【讨论】:

  • 有了这行require_relative '../../models/my_engine/option',错误现在出现在Option类中:option.rb:2:in &lt;module:MyEngine&gt;: uninitialized constant MyEngine::ApplicationRecord (NameError)
  • 但是当我运行应用程序而不在初始化程序中创建GLOBAL 的实例时,一切都可以正常工作,而无需在任何地方编写require,就像普通应用程序一样。它必须是加载引擎类的东西。
【解决方案3】:

我看到一个可能的问题:因为您在模块 MyEngine 内,所以实际上 rails 可能正在寻找 MyEngine::MyEngine::Option,所以我看到了两种方法:

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

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

【讨论】:

  • 我用不同变体的错误更新了问题。另外,我无法让require 工作。我的引擎中会有很多模型,还有很多助手,所以我想让它们都可用在初始化程序中。否则,它会起作用。但是我需要在初始化程序中使用很多帮助器来初始化一些对象
  • 所以将require "my_engine/option" 添加到my_engine/options_helper.rb 的顶部不起作用?会报错吗?
  • options_helper.rb:1:in `require': 无法加载此类文件 -- my_engine/option (LoadError)
猜你喜欢
  • 1970-01-01
  • 2015-10-30
  • 1970-01-01
  • 2011-01-08
  • 1970-01-01
  • 1970-01-01
  • 2015-04-16
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多