Ruby如何将Namespace的模块功能委托给Namespace::Base内部class

Ruby how to delegate module function of Namespace to Namespace::Base inner class

我面临着选择 #1 中的任何一个:

class Abstract
end
class Abstract::Foo < Abstract
end
class Abstract::Bar < Abstract
end

对比#2:

module Abstract
  class Base
  end
  class Foo < Base
  end
  class Bar < Base
  end
end

我最终选择了选项 #2,因为我的 Abstract 感觉更像是一个命名空间,我最终可以添加其他东西,比如

module Abstract # Instead of class if I had used option #1
  class SomeAbstractService
  end
end

不过我觉得调用Abstract::Base.some_class_method有点奇怪。可以添加模块功能委托吗?例如,如果我的 Base 是 ActiveRecord 或 Mongoid 模型(所以 Foo 和 Bar 就像 STI),我希望能够使用

查询 collection/table

Abstract.where(...) 而不是 Abstract::Base.where(...)

是否可以将模块功能 .where 委托给 constant/class Base

类似

module Abstract
  class Base
  end

  delegate_module_function :where, to: :Base
end

或者有 different/better 的方法吗?

您可以使用名为 Forwardable 的标准 Ruby 库。

require 'forwardable'

module Abstract
  extend SingleForwardable
  class Base
    def self.where(p)
      "where from base : #{p}"
    end
  end

  delegate :where => Base
end

Abstract.where(id: 3)
# => "where from base : {:id=>3}"

多个方法可以这样写:

delegate [:where, :another_method] => Base