2009-05-14 20 views
6

tengo métodos en todos mis modelos que se ven así:métodos globales en el rubí en los modelos de rieles

def formatted_start_date 
    start_date ? start_date.to_s(:date) : nil 
end 

me gustaría tener algo que escribe automáticamente un método como este para cada campo de fecha y hora en cada modelo , ¿Cuál es la mejor manera de hacer esto?

-C

Respuesta

16

Solo tuve que responder a esto, porque es un ejercicio divertido de Ruby.

Agregar métodos a una clase se puede hacer de muchas maneras, pero una de las mejores formas es usar algunas de las funciones de reflexión y evaluación de Ruby.

Cree este archivo en la carpeta lib lib/date_methods.rb

module DateMethods 

    def self.included(klass) 

    # get all dates 
    # Loop through the class's column names 
    # then determine if each column is of the :date type. 
    fields = klass.column_names.select do |k| 
        klass.columns_hash[k].type == :date 
       end 


    # for each of the fields we'll use class_eval to 
    # define the methods. 
    fields.each do |field| 
     klass.class_eval <<-EOF 
     def formatted_#{field} 
      #{field} ? #{field}.to_s(:date) : nil 
     end 

     EOF 
    end 
    end 
end 

Ahora basta con incluir en cualquiera de los modelos que lo necesitan

class CourseSection < ActiveRecord::Base 
    include DateMethods 
end 

Cuando se incluye, el módulo se verá en cualquier Columnas de fecha y genere los métodos formateados por usted.

Aprende cómo funciona este Ruby. Es muy divertido.

Dicho esto, debe preguntarse si es necesario. No creo que sea personal, pero de nuevo, fue divertido escribir.

-b-

+2

¿por qué utilizar recopilar y compactar en la matriz en lugar de seleccionar? –

+1

Tienes razón. .select sería más apropiado aquí. He encontrado momentos en los que .collect.compact es más rápido, incluso cuando parece que no debería serlo, pero en este caso .select es una opción mucho mejor. Gracias por atrapar eso. Me estaba enfocando en hacer las cosas difíciles y me perdí las cosas fáciles. –

+0

+1 cosas interesantes y divertidas. Sería mejor si corrigieras la respuesta (aquí en SO) para incluir los comentarios de Chris. –

11

Se parece más a algo por un ayudante para mí. Prueba esto en la ayuda en su aplicación:

def formatted_date(date) 
    date ? date.to_s(:date) : nil 
end 

El formato no es algo que pertenece realmente en el modelo (por precisamente la razón que has descubierto ... poner dicho código común en todos los modelos es molesto)

Si realmente quieres hacer lo que dices, entonces lo que podrías hacer es poner en parche la superclase ActiveRecord y agregar la función que quieras allí. Entonces estaría disponible para todos sus modelos. ¡Tenga en cuenta que el monopatching puede llevar a un comportamiento y uso impredecibles e indefinidos bajo su propio riesgo! También es bastante hacky :)

class ActiveRecord::Base 
    def formatted_start_date 
     start_date ? start_date.to_s(:date) : nil 
    end 
end 

sólo se adhieren que en alguna parte que se ejecuta antes de cualquier otra cosa en su aplicación será, y que añadirá dinámicamente el método de la clase base de sus modelos, haciendo que esté disponible para su uso .

O podría crear una mezcla para todos sus modelos, pero eso parece un poco exagerado para un solo método.

+1

+1 de mi parte. Estaba escribiendo la misma respuesta ... – tomafro

+0

bien, supongamos que era apropiado poner el formato en el modelo, o que quiero hacer algo más además de formatear con cada campo de fecha en mi aplicación, ¿cómo lo haría? –

+0

sí, pero la parte 'start_date' está codificada aquí, debo hacer esto para todos los campos de fecha en la aplicación, podrían llamarse start_date, end_date, term_date, finish_date, date, etc. ¿Cómo verifico el subclase para todas las columnas de fecha y luego escribe un método dinámico para cada una? –

0

una respuesta a su comentario: se puede extraer código común/funcionalidad en módulos que se incluya en una clase (I belive que se llama mixin?) O se puede ir por las subclases. No creo que la subclase sea el camino a seguir cuando es solo una funcionalidad común la que desea introducir en sus objetos, y no una situación de herencia real.

Eche un vistazo a this for more info on modules and Ruby.

Cuestiones relacionadas