Проверьте, есть ли класс ruby в определенном модуле - PullRequest
1 голос
/ 21 февраля 2020

У меня есть controller объект с controller.class == Admin::TeamsController. У меня также может быть такое обстоятельство, как controller.class == Admin::UsersController. Теперь я хочу проверить, верно ли это:

controller.class.to_s.match?('Admin::')

Т.е. я хочу знать: является ли этот объект класса, который определен в пространстве имен модуля Admin? Чтобы объяснить это, структура выглядит следующим образом?

module Admin
  module SomeOtherModulePerhaps
    class TeamsController
    end
  end
end

Мой вопрос: есть ли лучший способ проверить это на 1027 *? Это немного хакерски - преобразовать класс в строку, а затем выполнить такое регулярное выражение.

РЕДАКТИРОВАТЬ:

Для моего ограниченного варианта использования я мог бы проверить так:

controller.class.to_s.split('::').first == 'Admin'

Но это не совсем решает общий случай, который могут иметь другие люди. Например, могут быть такие случаи, как XyzAdmin::TeamsController, которые можно исключить, при которых мое первое решение дает сбой, или Foo::Admin::TeamsController, когда можно включить , при которых мое второе решение дает сбой.

Я бы хотел найти лучший способ.

Ответы [ 5 ]

0 голосов
/ 21 февраля 2020

Я хочу знать: это объект класса, который определен в пространстве имен модуля Admin?

[...]

Есть ли лучше Ruby способ проверить это?

Классы не определены в модулях, поэтому нет ни хорошего, ни другого способа проверить это.

Когда вы пишете тело определения класса внутри тела определения модуля, вы не создаете никаких отношений между модулем и классом. Единственная связь существует между константой , которой назначен класс, и модулем, а не классом.

Поэтому, поскольку эта связь не существует, вы не можете проверить ее.

0 голосов
/ 21 февраля 2020

Рельсы поставляются с module_parents:

module Admin
  module SomeOtherModulePerhaps
    class TeamsController
    end
  end
end

controller = Admin::SomeOtherModulePerhaps::TeamsController.new

controller.class.module_parents
#=> [Admin::SomeOtherModulePerhaps, Admin, Object]

controller.class.module_parents.include?(Admin)
#=> true

Под капотом используется Module#name, т.е. "Admin::SomeOtherModulePerhaps::TeamsController".

0 голосов
/ 21 февраля 2020

Как насчет

controller.class.const_defined?(:Admin)

возвращает true или false

0 голосов
/ 21 февраля 2020

Вы можете попробовать поиграть с Module#nesting, но он выдаст довольно неожиданные результаты в зависимости от того, был ли класс определен с использованием полного имени или набора вложенных операторов.

В конце концов, имена классов в ruby являются простыми константами, и можно определить имя класса разными способами, например:

module A
  def self.class!
    Class.new do |c|
      define_method :test do puts c.name end
    end
  end
end
A.const_set :C, A.class!
#⇒ A::C
A::C.new.test
#⇒ A::C

Что примерно означает Есть множество способов обмануть лучший механизм обнаружения. Тем не менее, я бы go с самым простым.

controller.class.to_s.split('::')[0...-1].include?('Admin')

Любое вхождение Admin будет засчитано, за исключением случаев, когда Admin является последним элементом в 1019 * в цепочка имен классов.

0 голосов
/ 21 февраля 2020

Как насчет использования controller_path

https://api.rubyonrails.org/classes/AbstractController/Base.html#method - c -controller_path

controller_path.match?('admin')
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...