Получить имя класса / модуля

#ruby

#ruby

Вопрос:

Есть ли лучший способ получить имя класса / модуля, а именно, C из A::B::C , B из A::B::C и A Из A::B::C . Следующий код использует string и split для получения "Stegosaurus" из Cowsay::Character::Stegosaurus , Как избавиться от string и split?

 require 'cowsay'
x = Cowsay.random_character().class
x.name.split("::")[2]
require 'cowsay'
true
x = Cowsay.random_character().class
Cowsay::Character::Stegosaurus
x.name.split("::")[2]
"Stegosaurus"
  

Комментарии:

1. Правильно ли я понимаю, что вы хотите извлечь каждый элемент без преобразования A::B::C в строку? Обратите внимание, что в этом примере A это модуль, но B и C не являются модулями, даже не объектами Ruby, поэтому лучшее, что вы могли бы сделать, это A или "A" , и "B" и "C" . Поскольку в итоге вы все равно получаете строки, зачем избегать преобразования A::B::C в строку, поскольку у вас есть очень простой способ сделать это?

2. Если я не был ясен в своем комментарии выше, A::B::C сообщает нам, что есть три вложенных модуля, A , A::B и A::B::C . B и C не являются модулями. Если бы вы определили модули A::C и B::C , что бы это значило для ссылки на module C ?

3. IMO split("::")[2] не так уж и плох. Конечно, не так плохо, как требовать activesupport. Это просто и выполняет свою работу.

Ответ №1:

Я не думаю, что в базовой / стандартной библиотеке есть что-нибудь для обработки этого.

В качестве альтернативы написанным на заказ методам всегда есть activesupport :

 require 'active_support/core_ext/string/inflections'
Cowsay::Character::Stegosaurus.name.demodulize
#=> "Stegosaurus"
Cowsay::Character::Stegosaurus.name.deconstantize
#=> "Cowsay::Character"
  

Эти методы реализованы следующим образом:

 def demodulize(path)
  path = path.to_s
  if i = path.rindex('::')
    path[(i 2)..-1]
  else
    path
  end
end

def deconstantize(path)
  path.to_s[0, path.rindex('::') || 0] # implementation based on the one in facets' Module#spacename
end
  

Загляните в документы, если вас интересуют дополнительные методы.

Что касается

A От A::B::C

Если бы вы использовали require все activesupport , вы бы получили кучу Module методов, включая parent :

 require 'active_support'
Cowsay::Character::Stegosaurus.parent
#=> Cowsay
  

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

Комментарии:

1. Хороший момент в извлечении полезных методов, если они вам нужны. Вот что здорово в использовании open-source: вы всегда можете позаимствовать части, если они вам нужны.