динамически создавать класс без пространства имен - PullRequest
1 голос
/ 22 декабря 2009

Я пытаюсь динамически создать класс, используя метод eval. Работает нормально, за исключением одной маленькой проблемы. Как показывает мой код, я создаю класс Browser внутри класса BrowserFactory. Когда я делаю это, класс Browser имеет добавленное пространство имен BrowserFactory. Есть ли способ оценить класс Browser по строке без присоединенного пространства имен BrowserFactory?


class BrowserFactory
  def self.create_browser(browser)
    super_class = nil
    case browser
    when 'IE'
      require 'watir'
      super_class = 'Watir::IE'
    when 'celerity'
      require 'celerity'
      super_class = 'Celerity::Browser'
    end

    raise StandardError.new("Browser '#{browser}' is not currentlys supported") if super_class.nil?

    eval <<EOS
class Browser < #{super_class}
include Singleton
include BrowserModification
end
EOS

    return Browser.instance
  end

end

Ответы [ 3 ]

3 голосов
/ 22 декабря 2009

Определение Browser (или :: Browser, чтобы напрямую ответить на ваш вопрос) не позволит вам звонить на фабрику более одного раза.

Я бы рекомендовал использовать анонимный класс. Нет необходимости в eval, кстати, и вы можете определить метод класса to_s, если хотите:

class BrowserFactory
  def self.create_browser(browser)
    super_class = case browser
    when 'IE'
      require 'watir'
      Watir::IE
    when 'celerity'
      require 'celerity'
      Celerity::Browser
    else
      raise StandardError.new("Browser '#{browser}' is not currentlys supported")
    end

    klass = Class.new(super_class) do
      include Singleton
      include BrowserModification
      def self.to_s
        "Modified#{superclass}"
      end
    end
    klass.instance
  end
end
2 голосов
/ 22 декабря 2009

Изменение

class Browser < #{super_class}

до

class ::Browser < #{super_class}
0 голосов
/ 18 мая 2010
def BrowserFactory(browser)
  case browser
  when 'IE'
    require 'watir'
    Watir::IE
  when 'celerity'
    require 'celerity'
    Celerity::Browser
  else
    raise ArgumentError, "Browser '#{browser}' is not currently supported"
  end.new.extend(BrowserModification)
end

Вот небольшой набор тестов:

module Watir; class IE; def to_s; 'IE' end end end
module Celerity; class Browser; def to_s; 'Celerity' end end end

module BrowserModification; def to_s; "Modified#{super}" end end

require 'test/unit'
class TestBrowserFactory < Test::Unit::TestCase
  def test_that_celerity_responds_as_modified_celerity
    assert_equal 'ModifiedCelerity', BrowserFactory('celerity').to_s
  end
  def test_that_internet_explorer_responds_as_modified_internet_explorer
    assert_equal 'ModifiedIE', BrowserFactory('IE').to_s
  end
  def test_that_an_invalid_browser_raises_an_exception
    assert_raise ArgumentError do BrowserFactory('xyz') end
  end
end
...