2010-05-20 10 views
5

Parece que debería tener una respuesta directa, pero después de mucho tiempo en Google y SO no puedo encontrarlo. Podría ser un caso de perder las palabras clave correctas.Rieles: mantener DRY con modelos ActiveRecord que comparten atributos complejos similares

En mi aplicación RoR tengo varios modelos que comparten un tipo específico de atributo de cadena que tiene una validación especial y otra funcionalidad. El ejemplo similar más cercano en el que puedo pensar es una cadena que representa una URL.

Esto genera mucha duplicación en los modelos (y aún más duplicaciones en las pruebas unitarias), pero no estoy seguro de cómo hacerlo más SECO.

puedo pensar en varias direcciones posibles ...

  1. crear un plugin en el sentido de que el plugin "validates_url_format_of", pero eso sólo haría que las validaciones DRY
  2. dan a este especial encadena su propio modelo, pero esto parece una solución muy
  3. crea una clase de ruby ​​para esta cadena especial, pero ¿cómo obtengo ActiveRecord para asociar esta clase con el atributo de modelo que es una cadena en el PP

Número 3 parece la más razonable, pero no puedo encontrar la manera de extender ActiveRecord para manejar distintos de los tipos de datos base nada. ¿Alguna sugerencia?

Por último, si hay una manera de hacerlo, ¿dónde ubicaría la nueva clase que no es modelo en la jerarquía de carpetas?

Muchas gracias.

ACTUALIZACIÓN:

Una posible solución mediante la sugerencia de Matt mixin a continuación (y utilizando el ejemplo URL). Tenga en cuenta que esto está más cerca de psuedocode que ruby ​​real y está destinado a transmitir la sintaxis de principio en lugar de perfecta.

En primer lugar, crear un url mixin:

module Url 
    def url_well_formed? 
    [...] 
    end 

    def url_live? 
    [...] 
    end 
end 

Y en un modelo Site, incluir este módulo:

Class Site < ActiveRecord:Base 
    include Url 

    validate :url_well_formed? 
end 

Y cuando necesito para comprobar que el sitio en la URL es en vivo, do ...

if site.url_live? 
    [...] 
end 

Lo que esto no resuelve es cómo hacer t La unidad prueba DRY. Si tengo otro modelo, digamos Page, que también usa la mezcla Url, aún necesitará un conjunto duplicado de pruebas de unidad para la URL. Por supuesto, podría poner estos en un ayudante, pero eso parece desordenado.

¿Existe una solución más fundamental o es tan buena como se consigue?

Respuesta

2

Puede crear un módulo con todos los métodos comunes e importar el módulo? Google para mixins.

+0

Gracias Matt. Puedo ver cómo mixins me hará una parte del camino (haciendo que los modelos sean bastante DRY). Ahora me pregunto cómo también puedo hacer que la unidad pruebe DRY, pero esa es probablemente una pregunta más general acerca de las pruebas de unidad de mapeo a los módulos. – Greg

6

Crear un modelo abstracto:

class CommonBase < ActiveRecord::Base 
    self.abstract_class = true # makes the model abstract 
    validate_format_of :url_field, :with => /.../ 
end 

Heredar sus modelos a partir del modelo abstracto:

class User < CommonBase 
end 

class Post < CommonBase 
end 
+0

Gracias KandadaBoggu. ¿Se puede crear una prueba unitaria que se corresponda con un modelo abstracto? Y una pregunta organizativa: ¿dónde pondrías esto? – Greg

+1

La llamada abstracta anterior debe ser: 'self.abstract_class = true' – tjmcewan

Cuestiones relacionadas