2012-05-14 19 views
14

Estoy escribiendo una joya con la que me gustaría trabajar y sin el entorno de Rails.Configuración de configuración al escribir una gema

tengo una clase Configuration para permitir la configuración de la gema:

module NameChecker 
    class Configuration 
    attr_accessor :api_key, :log_level 

    def initialize 
     self.api_key = nil 
     self.log_level = 'info' 
    end 
    end 

    class << self 
    attr_accessor :configuration 
    end 

    def self.configure 
    self.configuration ||= Configuration.new 
    yield(configuration) if block_given? 
    end 
end 

Esto puede ahora ser utilizado de esta manera:

NameChecker.configure do |config| 
    config.api_key = 'dfskljkf' 
end 

Sin embargo, no parecen ser capaces de acceso mis variables de configuración de entre las otras clases en mi gema. Por ejemplo, cuando configuro la joya en mi spec_helper.rb así:

# spec/spec_helper.rb 
require "name_checker" 

NameChecker.configure do |config| 
    config.api_key = 'dfskljkf' 
end 

y referencia la configuración de mi código:

# lib/name_checker/net_checker.rb 
module NameChecker 
    class NetChecker 
    p NameChecker.configuration.api_key 
    end 
end 

consigo un error indefinido método:

`<class:NetChecker>': undefined method `api_key' for nil:NilClass (NoMethodError) 

¿Qué pasa con mi código?

+1

He aquí un artículo sobre la configuración de las gemas para otros que puedan estar interesados: http: // robots .thoughtbot.com/mygem-configure-block – Rimian

Respuesta

17

Prueba refactorización a:

def self.configuration 
    @configuration ||= Configuration.new 
end 

def self.configure 
    yield(configuration) if block_given? 
end 
-2

El problema principal es que ha aplicado demasiada indirección. ¿Por qué no acaba de hacer

module NameChecker 
    class << self 
    attr_accessor :api_key, :log_level 
    end 
end 

y listo? También podría anular los dos lectores generados justo después de modo que garanticen la presencia del medio ambiente que necesita ...

module NameChecker 
    class << self 
    attr_accessor :api_key, :log_level 

    def api_key 
     raise "NameChecker really needs is't api_key set to work" unless @api_key 
     @api_key 
    end 

    DEFAULT_LOG_LEVEL = 'info' 

    def log_level 
     @log_level || DEFAULT_LOG_LEVEL 
    end 

    end 
end 

Ahora, el problema real (técnica) es que se está definiendo una clase llamada y NetChecker al definirlo, intenta imprimir el valor devuelto de la llamada api_key en un objeto Configuration supuesto (por lo que está violando la ley de Demeter aquí). Esto falla, porque está definiendo NetChecker antes de que alguien realmente haya tenido tiempo de definir cualquier configuración. Entonces, de hecho, está solicitando api_key antes de que se haya llamado al método configure en NameChecker, por lo que tiene nil en su configuration ivar.

Mi consejo sería eliminar la manipulación excesiva y vuelve a intentarlo ;-)

+1

El objetivo de la clase 'Configuration' es permitir que la gema se configure con un bloque de configuración. Creo que esta es la forma estándar de configurar gemas. También creo que es un patrón agradable en general. Pero sí, lo que dices sobre el "problema técnico" tiene sentido, así que gracias por eso. Finalmente, en mi defensa, ¡la violación de Demeter fue ideada en aras de la brevedad de la pregunta! –

+0

El patrón de bloques de configuración es totalmente opcional y proviene de Rails, no es un patrón que todos se adhieren. Es solo que Rails tiene algunas cosas que tienen que suceder dentro de un bloque de configuración cuando todo está siendo iniciado, principalmente para evitar que Rails cargue demasiados códigos (es por eso que lo hacen en un bloque especial). – Julik

+0

El problema aquí no es sobre ingeniería (o violar la ley de demeter). Es un problema de qué código se ejecuta primero. Si ejecuta todo el código OP en un solo archivo, funciona bien. El error ocurre cuando 'NameChecker.configuration.api_key' se ejecuta antes de que se complete el objeto de configuración. – eremzeit

Cuestiones relacionadas