#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
, что бы это значило для ссылки на moduleC
?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: вы всегда можете позаимствовать части, если они вам нужны.