Как запустить Proc внутри динамически сгенерированного модуля? - PullRequest
2 голосов
/ 18 июля 2011

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

По существу, пространства имен с ruby ​​могут быть созданы как:

module EIF
  module Core
    module Entities
    #stuff
    end
  end
end

или

module EIF
end

module EIF::Core
end

module EIF::Core::Entities
#some stuff
end

Дело в том, что это честно громоздко. Я хотел что-то похожее на C #, где вы просто определяете пространство имен как:

namespace EIF.Core.Entities
{
  #Some stuff
}

И покончим с этим. Мне удалось получить нечто подобное, используя eval для создания модулей (после сопоставления имени с регулярным выражением)

def namespace(path)
  if path.match(/^([A-Z][a-zA-Z0-9]*)(::[A-Z][a-zA-Z0-9_]*)*$/)
    spaces = path.split("::")
    code = ""
    spaces.each { |m| code << "module #{m}\n" }
    spaces.each { code << "end\n" }
    eval(code)
  else
    raise ArgumentError, "'#{path}' is not a valid namespace"
  end
end

В результате я могу сделать следующее:

namespace "EIF::Core::Entities"
class EIF::Core::Entities::Attirbute
  #class code
end

Теперь наступает следующий шаг. Я хочу использовать блок ruby, чтобы было легче читать, чтобы он выглядел так:

namespace "EIF::Core::Entities" do
  class Attribute
    #class code
  end
end

myAttribute = EIF::Core::Entities::Attribute.new

Проблема в том, что до сих пор единственный метод, который я нашел для создания модулей во время выполнения, - это eval, и когда я пытаюсь вставить блок кода в eval, полученный класс остается в корневом пространстве имен. Я пробовал instance_eval, module_eval и class_eval, и никто по какой-то причине не создал класс в модулях.

Как я могу это сделать? Я бы не хотел сейчас сдаваться.

1 Ответ

2 голосов
/ 18 июля 2011

Готово.

Кажется, что когда вы добавляете класс с помощью module_eval, как в:

My::Namespace.module_eval do
  class MyClass
  end
end

Пространство имен для MyClass разрешается в :: независимо от контекста. Тем не менее, написав:

class self::MyClass

Пространство имен разрешается в текущем объекте пространства имен, поэтому результирующее определение класса будет в My :: Namespace

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

...