2012-08-13 11 views
5

Esta es una forma común de establecer un valor predeterminado en Ruby:Cómo hacer una falsa opción por defecto

class QuietByDefault 
    def initialize(opts = {}) 
    @verbose = opts[:verbose] 
    end 
end 

Esto es un fácil trampa caiga en:

class VerboseNoMatterWhat 
    def initialize(opts = {}) 
    @verbose = opts[:verbose] || true 
    end 
end 

Ésta es una correcta manera de hacerlo:

class VerboseByDefault 
    def initialize(opts = {}) 
    @verbose = opts.include?(:verbose) ? opts[:verbose] : true 
    end 
end 

¿Cuál es la mejor manera/más limpio para codificar VerboseByDefault? (Podría factorizarlo, por supuesto.)

¿Qué patrón se usa ampliamente, si existe, en el código de Ruby en general? ¿ActiveSupport tiene un patrón para esto? (Mínimo es mejor - no necesito un analizador opción de línea de comandos completa.)

Ranting P.S .: No me gusta la asimetría entre el código que maneja un código predeterminado vs true que maneja una opción por defecto false. Un patrón que hace que cambiar entre los dos, sin causar errores, sea algo bueno de ver.

Respuesta

7

Una forma sencilla de hacerlo es mediante el uso del segundo argumento en Hash # ir a buscar

class VerboseByDefault 
    def initialize(opts = {}) 
    @verbose = opts.fetch(:verbose, true) 
    end 
end 

Por defecto complejas, ir a buscar también puede tener un bloque, que se ejecutará si el valor no está en el hash . Ver: http://ruby-doc.org/core-1.9.3/Hash.html#method-i-fetch

+0

¡Muy bien! Yo * puede * haber visto esto antes, pero no lo recuerdo. ¡Gracias! –

1

Lo he visto comúnmente como configurar todos sus valores predeterminados, y luego fusionarlos con los opts. como ...

def initialize(opts = {}) 
    @options = { :verbose => false, :foo => 42 } 
    @options.merge!(opts) 
    # ... 
end 

De esta forma, todas sus opciones se configuran en un solo lugar y solo combina las proporcionadas por el usuario.

+0

Me gusta la idea de comenzar con los valores predeterminados y fusionar en las opciones proporcionadas por el usuario, pero tiene un error en la forma en que el alcance '@ options'! Mira tu "yo". :) –

+0

oh, lo siento, no fue una solución completa :) Lo editaré y lo pondré dentro ... – Doon

0
require 'active_support/core_ext/hash/reverse_merge' 
class VerboseByDefault 
    DEFAULTS = { verbose: true } 
    def initialize(opts = {}) 
    opts.reverse_merge!(DEFAULTS) 
    @verbose = opts[:verbose] 
    end 
end 

Esto no solo es un poco más limpio solo por una opción, pero se vuelve mucho mejor si tiene más opciones. Además, utiliza el mismo patrón para true y false.

Cuestiones relacionadas