从单独的文件中请求/扩展ClassMethod

时间:2018-05-25 06:47:01

标签: ruby-on-rails ruby

我有一个模块包含一些" class"或者" DSL"目前的方法如下:

module Things
  module ClassMethods
    def thing id, title, **options
      # ... create and register a thing ...
    end

    # ... more DSL methods ...
  end
  extend ClassMethods

  # define project things
  thing :ruby, "Ruby programming language"
  thing :rails, "Ruby on Rails web framework"
  thing :active_support, "ActiveSupport library"
end

所以我在ClassMethods中定义了DSL方法,用Things扩展ClassMethods然后在模块体中使用DSL。我已经按照约定选择了名称ClassMethods,虽然模块不是主动记录关注,但我看到了轨道。

现在我想将DSL定义与其用法分开,因此我将代码分成

lib/things/class_methods.rb

module Things
  module ClassMethods
    def thing id, title, **options
      # ... create and register a thing ...
    end

    # ... more DSL methods ...
  end
end

lib/things.rb

require_relative "things/class_methods"

module Things
  extend ClassMethods

  # define project things
  thing :ruby, "Ruby programming language"
  thing :rails, "Ruby on Rails web framework"
  thing :active_support, "ActiveSupport library"
end

但是在这个问题出现之后:代码在重新启动rails服务器后第一次按预期工作,但后续使用此模块的请求会引发模糊错误或抱怨DSL方法没有定义或以其他方式表现得好像DSL呼叫没有做他们应该做的事情。感觉好像extend ClassMethods行选择了错误的模块ClassMethod,但后来我不明白为什么我最初工作。

知道我的方法究竟出了什么问题,以及解决这个问题的最佳解决方案是什么?我应该重命名DSL模块,以便它不会与框架中其他地方定义的ClassMethods发生冲突吗?或者我还能做些什么来继续使用名称ClassMethods而不会发生冲突?

2 个答案:

答案 0 :(得分:1)

Rails有时会在autoloading and reloading期间失去对常量的跟踪,需要一些帮助。

这可以是显式依赖:

# lib/things.rb
require_dependency 'things/class_methods' # <- tells Rails that we depend on this
require_relative 'things/class_methods'

module Things
  extend ClassMethods

  # ...
end

或者使用完全合格的内容:

# lib/things.rb
require_relative 'things/class_methods'

module Things
  extend ::Things::ClassMethods

  # ...
end

使用extend Things::ClassMethods可能就足够了,前提是您没有在Things下嵌套另一个Things模块。

哪种方法有效,似乎取决于您的类结构和自动加载配置。

答案 1 :(得分:0)

您是否尝试使用/lib方法将application.rb目录添加到.autoload_paths文件中?