Da Rails eine Struktur in Bezug auf MVC bietet, werden natürlich nur die für Sie bereitgestellten Modell-, Ansichts- und Controller-Container verwendet. Die typische Redewendung für Anfänger (und sogar einige fortgeschrittene Programmierer) besteht darin, die gesamte Logik in der App in das Modell (Datenbankklasse), den Controller oder die Ansicht zu packen.
Irgendwann weist jemand auf das Paradigma "Fettmodell, Skinny-Controller" hin, und fortgeschrittene Entwickler entfernen hastig alles von ihren Controllern und werfen es in das Modell, das zu einem neuen Mülleimer für die Anwendungslogik wird.
Dünne Controller sind in der Tat eine gute Idee, aber die Konsequenz - alles in das Modell zu integrieren - ist nicht wirklich der beste Plan.
In Ruby haben Sie einige gute Möglichkeiten, die Dinge modularer zu gestalten. Eine ziemlich beliebte Antwort ist, nur Module zu verwenden (normalerweise versteckt lib
), die Gruppen von Methoden enthalten, und die Module dann in die entsprechenden Klassen aufzunehmen. Dies ist hilfreich, wenn Sie über Funktionskategorien verfügen, die Sie in mehreren Klassen wiederverwenden möchten, die Funktionalität jedoch noch fiktiv an die Klassen gebunden ist.
Denken Sie daran, wenn Sie ein Modul in eine Klasse aufnehmen, werden die Methoden zu Instanzmethoden der Klasse, sodass Sie immer noch eine Klasse mit einer Vielzahl von Methoden erhalten. Sie sind nur gut in mehrere Dateien organisiert.
Diese Lösung kann in einigen Fällen gut funktionieren. In anderen Fällen sollten Sie darüber nachdenken, Klassen in Ihrem Code zu verwenden, die keine Modelle, Ansichten oder Controller sind.
Eine gute Möglichkeit, darüber nachzudenken, ist das "Prinzip der Einzelverantwortung", das besagt, dass eine Klasse für eine einzelne (oder eine kleine Anzahl) von Dingen verantwortlich sein sollte. Ihre Modelle sind dafür verantwortlich, dass Daten aus Ihrer Anwendung in der Datenbank gespeichert werden. Ihre Controller sind dafür verantwortlich, eine Anfrage zu erhalten und eine brauchbare Antwort zurückzugeben.
Wenn Sie Konzepte haben, die nicht genau in diese Felder passen (Persistenz, Anforderungs- / Antwortverwaltung), möchten Sie wahrscheinlich darüber nachdenken, wie Sie die betreffende Idee modellieren würden . Sie können Nichtmodellklassen in App / Klassen oder an einer anderen Stelle speichern und dieses Verzeichnis Ihrem Ladepfad hinzufügen, indem Sie Folgendes tun:
config.load_paths << File.join(Rails.root, "app", "classes")
Wenn Sie Passagier oder JRuby verwenden, möchten Sie wahrscheinlich auch Ihren Pfad zu den eifrigen Ladepfaden hinzufügen:
config.eager_load_paths << File.join(Rails.root, "app", "classes")
Das Fazit ist, dass es an der Zeit ist, Ihre Ruby-Chops zu verbessern und Klassen zu modellieren, die nicht nur die MVC-Klassen sind, die Rails Ihnen standardmäßig zur Verfügung stellt, sobald Sie einen Punkt in Rails erreicht haben, an dem Sie diese Frage stellen.
Update: Diese Antwort gilt für Rails 2.x und höher.
Update : Die Verwendung von Bedenken wurde als neuer Standard in Rails 4 bestätigt .
Es hängt wirklich von der Art des Moduls selbst ab. Normalerweise platziere ich Controller- / Modellerweiterungen in einem Ordner unter der App.
/ lib ist meine bevorzugte Wahl für Allzweckbibliotheken. Ich habe immer einen Projektnamespace in lib, in dem ich alle anwendungsspezifischen Bibliotheken ablege.
Ruby / Rails-Kernerweiterungen finden normalerweise in Konfigurationsinitialisierern statt, sodass Bibliotheken nur einmal auf Rails Boostrap geladen werden.
Für wiederverwendbare Codefragmente erstelle ich häufig (Mikro-) Plugins, damit ich sie in anderen Projekten wiederverwenden kann.
Hilfsdateien enthalten normalerweise Hilfsmethoden und manchmal Klassen, wenn das Objekt von Helfern (z. B. Form Buildern) verwendet werden soll.
Dies ist eine wirklich allgemeine Übersicht. Bitte geben Sie weitere Details zu bestimmten Beispielen an, wenn Sie individuellere Vorschläge erhalten möchten. :) :)
quelle
"riesig" ist ein besorgniserregendes Wort ... ;-)
Wie werden Ihre Controller riesig? Das sollten Sie sich ansehen: Im Idealfall sollten Controller dünn sein. Wenn Sie eine Faustregel aus dem Nichts auswählen, würde ich vorschlagen, dass Ihre Controller wahrscheinlich zu fett sind, wenn Sie regelmäßig mehr als beispielsweise 5 oder 6 Codezeilen pro Controller-Methode (Aktion) haben. Gibt es Duplikate, die in eine Hilfsfunktion oder einen Filter verschoben werden könnten? Gibt es eine Geschäftslogik, die in die Modelle hineingedrückt werden könnte?
Wie werden deine Modelle riesig? Sollten Sie nach Möglichkeiten suchen, um die Anzahl der Verantwortlichkeiten in jeder Klasse zu verringern? Gibt es allgemeine Verhaltensweisen, die Sie in Mixins extrahieren können? Oder Funktionsbereiche, die Sie an Hilfsklassen delegieren können?
EDIT: Ich versuche ein bisschen zu expandieren, hoffentlich nichts zu sehr zu verzerren ...
Helfer: leben in
app/helpers
und werden meistens verwendet, um die Ansicht zu vereinfachen. Sie sind entweder Controller-spezifisch (auch für alle Ansichten dieses Controllers verfügbar) oder allgemein verfügbar (module ApplicationHelper
in application_helper.rb).Filter: Angenommen, Sie haben dieselbe Codezeile in mehreren Aktionen (häufig Abrufen eines Objekts mit
params[:id]
oder ähnlich). Diese Duplizierung kann zuerst zu einer separaten Methode und dann vollständig aus den Aktionen abstrahiert werden, indem ein Filter in der Klassendefinition deklariert wird, zbefore_filter :get_object
. Siehe Abschnitt 6 im ActionController Rails-Handbuch. Lassen Sie die deklarative Programmierung Ihr Freund sein.Das Refactoring von Modellen ist eher eine religiöse Sache. Die Schüler von Onkel Bob schlagen zum Beispiel vor, dass Sie die fünf Gebote von SOLID befolgen . Joel & Jeff empfehlen möglicherweise einen eher "pragmatischen" Ansatz, obwohl sie später etwas versöhnter zu sein schienen . Das Finden einer oder mehrerer Methoden innerhalb einer Klasse, die mit einer klar definierten Teilmenge ihrer Attribute arbeiten, ist eine Möglichkeit, Klassen zu identifizieren, die möglicherweise aus Ihrem von ActiveRecord abgeleiteten Modell überarbeitet wurden.
Rails-Modelle müssen übrigens keine Unterklassen von ActiveRecord :: Base sein. Oder anders ausgedrückt: Ein Modell muss kein Analogon einer Tabelle sein oder sich auf irgendetwas beziehen, das überhaupt gespeichert ist. Noch besser, solange Sie Ihre Datei
app/models
gemäß den Rails-Konventionen benennen (rufen Sie #underscore für den Klassennamen auf, um herauszufinden, wonach Rails suchen wird), findet Rails sie, ohne dassrequire
s erforderlich ist.quelle
Hier ist ein ausgezeichneter Blog-Beitrag über die Umgestaltung der Fettmodelle, die sich aus der "Thin Controller" -Philosophie zu ergeben scheinen:
http://blog.codeclimate.com/blog/2012/10/17/7-ways-to-decompose-fat-activerecord-models/
Die Grundmeldung lautet "Extrahieren Sie keine Mixins aus Fettmodellen". Verwenden Sie stattdessen Serviceklassen. Der Autor stellt hierfür 7 Muster bereit
quelle