Ruby, как делегировать функцию модуля Пространства имен Пространству имен:: Базовый внутренний класс

Я столкнулся с выбором либо № 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), я хотел бы иметь возможность запросить коллекцию / таблицу с

Abstract.where(...) вместо Abstract::Base.where(...)

Можно ли делегировать функцию модуля .where константе / классу Base?

Что-то вроде

module Abstract
  class Base
  end

  delegate_module_function :where, to: :Base
end

Или есть другой / лучший способ сделать это?

1 ответ

Решение

Вы можете использовать стандартную библиотеку Ruby под названием Forwardable.

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
Другие вопросы по тегам