2009-12-22 5 views
1

J'essaye de créer dynamiquement une classe en utilisant la méthode eval. Cela fonctionne bien sauf pour un petit problème. Comme le montre mon code, je crée la classe Browser dans la classe BrowserFactory. Quand je fais ceci la classe de Browser a un espace de noms ajouté de BrowserFactory. Y a-t-il moyen d'évaluer la classe Browser à partir d'une chaîne sans que l'espace de noms BrowserFactory soit attaché?créer dynamiquement une classe sans espace de noms


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 

Répondre

3

Définition du navigateur (ou :: Navigateur, pour répondre directement à votre question) vous empêche d'appeler votre usine plus d'une fois.

Je recommanderais d'utiliser une classe anonyme. Pas besoin de eval, d'ailleurs, et vous pouvez définir la méthode de classe to_s si vous voulez:

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 
+1

Vous pouvez réellement passer simplement le bloc de configuration pour 'Class.new' plutôt que d'appeler' class_eval' séparément. – Chuck

+0

En effet, encore plus agréable. Merci :-) –

2

changement

class Browser < #{super_class} 

à

class ::Browser < #{super_class} 
0
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 

Voici une petite testsuite:

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 
Questions connexes