2009-09-26 7 views
5

Disons que j'ai une classe singleton comme ceci:Comment ajouter des méthodes de classe pratique pour une classe Singleton en rubis

class Settings 
    include Singleton 

    def timeout 
    # lazy-load timeout from config file, or whatever 
    end 
end 

Maintenant, si je veux savoir ce délai d'attente à utiliser je dois écrire quelque chose comme:

Settings.instance.timeout 

mais je préfère que réduis à

Settings.timeout 

Une façon évidente de faire ce travail consisterait à modifier le œuvre mise à des paramètres:

class Settings 
    include Singleton 

    def self.timeout 
    instance.timeout 
    end 

    def timeout 
    # lazy-load timeout from config file, or whatever 
    end 
end 

Cela fonctionne, mais il serait assez fastidieux d'écrire manuellement une méthode de classe pour chaque méthode d'instance. C'est du rubis, il doit y avoir une façon intelligente et intelligente de faire cela.

Répondre

10

Une façon de le faire est comme ceci:

require 'singleton' 
class Settings 
    include Singleton 

    # All instance methods will be added as class methods 
    def self.method_added(name) 
    instance_eval %Q{ 
     def #{name} 
     instance.send '#{name}' 
     end 
    } 
    end 


    def timeout 
    # lazy-load timeout from config file, or whatever 
    end 
end 

Settings.instance.timeout 
Settings.timeout 

Si vous voulez un contrôle à grain plus fin sur les méthodes de déléguer, vous pouvez utiliser des techniques de délégation:

require 'singleton' 
require 'forwardable' 
class Settings 
    include Singleton 
    extend SingleForwardable 

    # More fine grained control on specifying what methods exactly 
    # to be class methods 
    def_delegators :instance,:timeout,:foo#, other methods 

    def timeout 
    # lazy-load timeout from config file, or whatever 
    end 

    def foo 
    # some other stuff 
    end 

end 

Settings.timeout 

Settings.foo 

autre côté, je recommande d'utiliser des modules si la fonctionnalité prévue est limitée au comportement, une telle solution serait:

module Settings 
    extend self 

    def timeout 
    # lazy-load timeout from config file, or whatever 
    end 

end 

Settings.timeout 
+1

Impressionnant répondre. Dans mon cas particulier SingleForwardable est exactement ce que je cherchais. Merci! –

Questions connexes