Rails Anti-Patterns in Modellen – und wie man sie behebt
Rails fördert eine saubere Trennung von Belangen (Separation of Concerns), aber es ist leicht, Logik in die falsche Schicht durchsickern zu lassen. Das Modell soll Geschäftsregeln und Domänenverhalten kapseln, dennoch enden viele Anwendungen mit überladenen Controllern, aufgeblähten Ansichten (Views) oder übermäßig komplexen Modellen. Nachfolgend finden Sie gängige Anti-Patterns in Rails-Modellen und deren Lösungen mit Codebeispielen.
1. Ansichtslogik (View Logic) gehört in das Modell
Ein häufiger Fehler besteht darin, bedingte Geschäftslogik direkt in die Views einzufügen.
Schlecht:
<% if @order.total > 100 %>
<p>Premium-Bestellung</p>
<% end %>
Besser: Verschieben Sie die Regel in das Modell.
class Order < ApplicationRecord
def premium?
total > 100
end
end
<% if @order.premium? %>
<p>Premium-Bestellung</p>
<% end %>
2. Callbacks, die zu viel tun
Callbacks sind nützlich, aber ihr übermäßiger Einsatz verbirgt wichtiges Verhalten.
Schlecht:
class User < ApplicationRecord
after_create :send_welcome_email
def send_welcome_email
Mailer.welcome(self).deliver_now
end
end
Besser: Extraktion in ein Service-Objekt.
class UserSignup
def self.call(user)
Mailer.welcome(user).deliver_now
end
end
user = User.create!(params)
UserSignup.call(user)
3. SQL in Controllern
Anfragelogik verstopft Controller und streut Geschäftsregeln.
Schlecht:
@active_users = User.where("last_login > ?", 30.days.ago)
Besser: Verwenden Sie einen Scope im Modell.
class User < ApplicationRecord
scope :recently_active, -> { where("last_login > ?", 30.days.ago) }
end
@active_users = User.recently_active
4. Serialisierte Attribute anstelle von Tabellen
Das Entleeren von Hashes in [serialize](https://api.rubyonrails.org/classes/ActiveModel/Serialization.html)-Spalten erschwert das Abfragen.
Schlecht:
class User < ApplicationRecord
serialize :preferences, Hash
end
Besser: Normalisierung mit einer Erweiterung (Association).
class Preference < ApplicationRecord
belongs_to :user
end
class User < ApplicationRecord
has_many :preferences
end
5. Missbrauch der Single Table Inheritance (STI)
STI zwingt voneinander unabhängige Unterklassen in eine Tabelle, oft mit vielen NULL-Spalten.
Schlecht:
class Payment < ApplicationRecord; end
class CreditCardPayment < Payment; end
class BankTransferPayment < Payment; end
Besser: Verwenden Sie Polymorphismus oder Komposition.
class Payment < ApplicationRecord
belongs_to :payable, polymorphic: true
end
class CreditCard < ApplicationRecord
has_many :payments, as: :payable
end
Dieser Beitrag wurde von dem Buch Rails AntiPatterns: Best Practice Ruby on Rails Refactoring von Chad Pytel und Tammer Saleh inspiriert. Wenn Sie das gesamte Buch lesen möchten, finden Sie es auf Amazon: Rails AntiPatterns
Wenn Sie das Buch über diesen Amazon-Link kaufen, kann ich eine kleine Provision ohne zusätzliche Kosten für Sie verdienen — danke für die Unterstützung dieses Inhalts.
Wichtigste Erkenntnisse
- Verschieben Sie Geschäftsregeln in Modelle (nicht in Views oder Controller).
- Verwenden Sie Service-Objekte, wenn Callbacks zu viel verstecken.
- Halten Sie SQL in Scopes, vermeiden Sie verstreute Anfragen.
- Normalisieren Sie Datenstrukturen, vermeiden Sie serialisierte Blobs.
- Vermeiden Sie den Missbrauch von STI; bevorzugen Sie polymorphes oder kompositorisches Design.
Durch das Refactoring dieser Anti-Patterns bleiben Ihre Modelle ausdrucksstark, Ihre Controller schlank und Ihre Views sauber.