2009-05-09 9 views
16

Los rieles método Array#to_sentence permite lo siguiente:métodos Rieles Redefiniendo

['a', 'b', 'c'].to_sentence # gives: "a, b, and c" 

Me gustaría extender este método para permitir que se tome un bloque, por lo que se puede hacer algo como lo siguiente (donde la gente es un conjunto de objetos persona, que tienen el atributo name):

people.to_sentence { |person| person.name } 
# => "Bill, John, and Mark" 

no tengo un problema con escribir el método de extensión. Pero no puedo averiguar dónde ponerlo. Las extensiones del núcleo de Rails se cargan en algún lugar en las profundidades de ActiveSupport. Mi necesidad es un lugar donde el código definido por el usuario siempre se carga y se precarga (antes de cualquier código de aplicación).

Respuesta

23

Crear config/initializers/super_to_sentence.rb. Todos los archivos en este directorio se cargan después de que se haya cargado Rails, por lo que tendrá la posibilidad de anular la definición de Array#to_sentence de Rails.

Para el código que desee cargar antes de que se cargue Rails, agréguelo al config/environment.rb.

+0

como se mencionó, agregue todas sus extensiones personalizadas a un archivo config/initializers/*. Rb – cpjolicoeur

+0

Gracias. Lo verificará. – dcw

14

me gusta hacer esto:

# config/initializers/app.rb 
Dir[File.join(Rails.root, "lib", "core_ext", "*.rb")].each {|l| require l } 

# lib/core_ext/array.rb 
class Array 
    def to_sentence_with_block(*args, &block) 
    if block_given? 
     # do something... 
     # to_sentence_without_block(*args) perhaps? 
    else 
     to_sentence_without_block(*args) 
    end 
    end 
    alias_method_chain :to_sentence, :block 
end 
+0

Gracias. Por cierto, creo que es una buena práctica recordar la defn anterior, es decir, agregar un "alias old_to_sentence to_sentence" antes de la defn del nuevo método y su aliasing. – dcw

14

Creo que esta es una idea horrible. ¿Por qué no acaba de escribir

people.collect { |person| person.name }.to_sentence 

Esto es casi igual y no confundir a otras personas la lectura de su código (como usted en 2 años)

+2

Y ahora, se vuelve aún más corto: 'people.map (&: name) .to_sentence' – sawa

1

sólo la búsqueda en la web, que parece ser una buena práctica consiste en añadir en lib/

así que si quieres extender alguna clase de rubí (en mi caso, DateTime), sólo hay que poner el código en .rb y luego en config/environment.rb:

config.after_initialize do 
    require "lib/super_datetime.rb" 
    end 

mi super_datetime.rb se parece a esto (código de http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/140184):

class DateTime 
    def days_in_month 
    self::class.civil(year, month, -1).day 
    end 
    alias dim days_in_month 
    def weekdays 
    (1..dim).to_a 
    end 
end 

reiniciar el servidor y usted tendrá acceso al nuevo método para todos los objetos DateTime.

Cuestiones relacionadas