2010-05-20 8 views
5

Dies scheint wie es eine einfache Antwort haben sollte, aber nach viel Zeit auf Google und SO kann ich es nicht finden. Es könnte ein Fall sein, dass die richtigen Schlüsselwörter fehlen.Rails: halten DRY mit ActiveRecord-Modellen, die ähnliche komplexe Attribute teilen

In meiner RoR-Anwendung habe ich mehrere Modelle, die eine bestimmte Art von String-Attribut teilen, die spezielle Validierung und andere Funktionalität hat. Das ähnlichste Beispiel, das ich mir vorstellen kann, ist eine Zeichenfolge, die eine URL darstellt.

Dies führt zu vielen Duplizierungen in den Modellen (und noch mehr Duplizierung in den Komponententests), aber ich bin nicht sicher, wie man es DRYER macht.

ich von mehreren möglichen Richtungen denken kann ...

  1. ein Plugin nach dem Vorbild der „validates_url_format_of“ Plugin erstellen, aber das würde nur machen das Validierungen DRY
  2. dieses besondere geben string sein eigenes Modell, aber das scheint wie eine sehr schwere Lösung
  3. erstellen Sie eine Ruby-Klasse für diese spezielle Zeichenfolge, aber wie bekomme ich ActiveRecord, um diese Klassezuordnenmit dem Modell-Attribute, das eine Zeichenfolge in dem db

Nummer 3 scheint die vernünftigste Active ist, aber ich kann nicht herausfinden, wie zu erweitern, etwas anderes als die Basisdatentypen zu handhaben. Irgendwelche Zeiger?

Schließlich, wenn es eine Möglichkeit gibt, dies zu tun, wo in der Ordnerhierarchie würden Sie die neue Klasse, die kein Modell ist?

Vielen Dank.

UPDATE:

Eine mögliche Lösung unter Matts mixin Vorschlag mit (und dem URL-Beispiel verwenden). Beachten Sie, dass dies näher an psuedocode als an echtem Ruby liegt und eher das Prinzip als die perfekte Syntax vermitteln soll.

Erstellen Sie zunächst eine url mixin:

module Url 
    def url_well_formed? 
    [...] 
    end 

    def url_live? 
    [...] 
    end 
end 

Und in einem Site Modell, um diesen Modul:

Class Site < ActiveRecord:Base 
    include Url 

    validate :url_well_formed? 
end 

Und wenn ich, dass die Website unter der URL überprüfen muß, ist zu leben, tun ...

if site.url_live? 
    [...] 
end 

Die Sache, die das nicht löst, ist, wie man t macht Die Einheit testet DRY. Wenn ich ein anderes Modell verwende, z. B. Page, das auch das Url Mixin verwendet, benötigt es immer noch einen doppelten Satz von Komponententests für die URL. Natürlich könnte ich diese in einen Helfer stecken, aber das scheint chaotisch.

Gibt es eine grundlegendere Lösung, oder ist das so gut wie es geht?

Antwort

2

Sie könnten ein Modul mit allen gängigen Methoden erstellen und das Modul importieren? Google für mixins.

+0

Dank Matt. Ich kann sehen, wie Mixins mir einen Teil des Weges bringen (die Modelle selbst ziemlich trocken machen). Jetzt frage ich mich, wie ich die Unit-Tests auch DRY machen kann, aber das ist wahrscheinlich eine allgemeinere Frage, wenn Unit-Tests auf Module abgebildet werden. – Greg

6

ein abstraktes Modell erstellen:

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

Ihre Modelle aus dem abstrakten Modell Inherit:

class User < CommonBase 
end 

class Post < CommonBase 
end 
+0

Danke KandadaBoggu. Kann man einen Komponententest erstellen, der einem abstrakten Modell entspricht? Und eine organisatorische Frage: Wo würdest du das hinstellen? – Greg

+1

Der obige abstrakte Aufruf sollte lauten: 'self.abstract_class = true' – tjmcewan