Ruby: Как требовать и создавать экземпляры всех файлов в каталоге? - PullRequest
1 голос
/ 18 февраля 2012

Я разрабатываю Gem, который позволит пользователям автоматически запрашивать, создавать экземпляры и регистрировать классы в определенном каталоге. Я просто не уверен, как этого добиться. Это то, что я до сих пор придумал ...

Dir[Dir.pwd + '/extensions/*.rb'].each do |file|
  require file
  extension_class = # instantiate the class here
  MyApp.extensions << extension_class
end

Как я могу создать экземпляр класса, не зная, как он называется?

Ответы [ 2 ]

6 голосов
/ 18 февраля 2012

Похоже, вы создаете систему для написания расширений для программного обеспечения.Поскольку все классы расширения, вероятно, все в некотором роде похожи, например, совместно используют некоторые общие методы, возможно, имеет смысл иметь базовый класс с именем Extension, от которого наследуются все классы расширения.Это очень полезно для указанной проблемы, потому что когда пользователь наследует ваш класс, вы можете обнаружить его и добавить подкласс в список.Вот некоторые доказательства концепции кода:

class Extension
  class << self
    attr_reader :list
  end
  @list = []

  def self.inherited(klass)
    @list << klass.new
  end
end

# The MyExt class would be in another file, loaded by require.
class MyExt < Extension
end

p Extension.list   # => [#<MyExt:0xb777d884>]

Если вы по какой-то причине не хотите использовать подклассы, то столь же легко сделать Extension модулем и использовать вместо него included hookиз inherited.

Лично я бы просто убрал вызов .new, потому что не вижу причин для создания экземпляра класса сразу, но это зависит от вас.Я бы просто сохранил список классов.

1 голос
/ 18 февраля 2012

это интересная идея, которая заставила меня немного почесать голову. я не мог найти немедленного решения с поиском в Google, поэтому я немного поиграл с языком. я выдвинул три основные идеи:

  • отслеживайте все загруженные классы и захватывайте новые по мере их поступления
  • использовать схему именования для связи имен файлов с классами
  • использовать своего рода интроспектор для обязательных классов, чтобы они могли зарегистрироваться для последующего включения

я решил, что мне больше всего понравился первый вариант; это не требует от вас структурирования ваших файлов определенным образом или расширения классов для того, чтобы знать, что они потребуются таким образом. Вот элементарная реализация, заимствуя вашу первоначальную структуру:

classes = ObjectSpace.each_object(Class).to_a
Dir[Dir.pwd + '/extensions/*.rb'].each do |file|
  require file
  changed_classes = ObjectSpace.each_object(Class).to_a
  (changed_classes - classes).each do |extension_class|
    MyApp.extensions << extension_class
  end
  classes = changed_classes
end
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...