2010-05-20 7 views
5

Cela semble avoir une réponse simple, mais après beaucoup de temps sur Google et SO je ne peux pas le trouver. Il pourrait être un cas de manquer les bons mots-clés.Rails: garder DRY avec des modèles ActiveRecord qui partagent des attributs complexes similaires

Dans mon application RoR, j'ai plusieurs modèles qui partagent un type spécifique d'attribut de chaîne qui a une fonctionnalité de validation spéciale et d'autres. L'exemple similaire le plus proche auquel je peux penser est une chaîne qui représente une URL. Cela conduit à beaucoup de duplication dans les modèles (et encore plus de duplication dans les tests unitaires), mais je ne suis pas sûr de savoir comment le rendre plus SEC.

Je peux penser à plusieurs directions possibles ...

  1. créer un plug-in le long des lignes du plugin « validates_url_format_of », mais cela ne ferait que rendre les SECS
  2. validations
  3. donnent cette spéciale chaîne son propre modèle, mais cela semble très solution lourde
  4. créer une classe ruby ​​pour cette chaîne spéciale, mais comment puis-je obtenir ActiveRecord pour associer cette classe avec l'attribut modèle qui est une chaîne dans la db

numéro 3 semble le plus raisonnable, mais je ne peux pas comprendre comment étendre ActiveRecord pour gérer quoi que ce soit d'autre que les types de données de base. Des pointeurs?

Enfin, s'il y a un moyen de faire cela, où placeriez-vous dans la hiérarchie de dossiers la nouvelle classe qui n'est pas un modèle?

Merci beaucoup.

MISE À JOUR:

Une solution potentielle à l'aide de Matt suggestion mixin ci-dessous (et en utilisant l'exemple d'URL). Notez que ceci est plus proche du pseudo-code que du vrai rubis et est destiné à transmettre le principe plutôt que la syntaxe parfaite.

Tout d'abord, créez un url mixin:

module Url 
    def url_well_formed? 
    [...] 
    end 

    def url_live? 
    [...] 
    end 
end 

Et dans un modèle Site, comprennent ce module:

Class Site < ActiveRecord:Base 
    include Url 

    validate :url_well_formed? 
end 

Et quand je dois vérifier que le site à l'adresse est en direct, faire ...

if site.url_live? 
    [...] 
end 

La chose que cela ne résout pas est comment faire t L'unité teste DRY. Si j'ai un autre modèle, disons Page, qui utilise également le mixin Url, il aura besoin d'un ensemble de tests unitaires dupliqués pour l'URL. Bien sûr, je pourrais les mettre dans une aide, mais cela semble désordonné.

Existe-t-il une solution plus fondamentale, ou est-ce aussi bon?

Répondre

2

Vous pouvez créer un module avec toutes les méthodes courantes et importer le module? Google pour mixins.

+0

Merci Matt. Je peux voir comment les mixins vont me prendre une partie du chemin (rendant les modèles eux-mêmes assez secs). Maintenant, je me demande comment je peux aussi rendre les tests unitaires SEC, mais c'est probablement une question plus générale autour de la mise en correspondance des tests unitaires avec les modules. – Greg

6

Créer un modèle abstrait:

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

vos modèles Hérite du modèle abstrait:

class User < CommonBase 
end 

class Post < CommonBase 
end 
+0

Merci KandadaBoggu. Peut-on créer un test unitaire qui correspond à un modèle abstrait? Et une question organisationnelle: où mettriez-vous cela? – Greg

+1

L'appel abstrait ci-dessus doit être: 'self.abstract_class = true' – tjmcewan

Questions connexes