Ist das Einfügen von Präsentationslogik in den Controller eine gute Vorgehensweise in Ruby?
-
12-12-2019 - |
Frage
Einige Empfehlungen [1] schlagen vor, dass Sie verwenden
<%= current_user.welcome_message %>
statt
<% if current_user.admin? %>
<%= current_user.admin_welcome_message %>
<% else %>
<%= current_user.user_welcome_message %>
<% end %>
Das Problem ist jedoch, dass Sie die Entscheidungslogik irgendwo in Ihrem Code haben müssen.
Mein Verständnis setzt die Entscheidung in template
ist besser als controller
da es Ihren Controller sauberer macht.Ist es richtig?
Gibt es einen besseren Weg, damit umzugehen?
Lösung
Meiner Meinung nach gehört der Text nicht in eine Ansicht, wenn sich nur der Text ändert.Wenn Sie die Seite neu strukturieren mussten, ist dies die Präsentationslogik.Dies sind nur Daten, die anders sind.
Andere Tipps
Sie sind nicht die ersten, die sich das fragen.Wenn Ansichten und Controller wenig bis gar keine Logik haben sollten und das Modell präsentationsunabhängig sein sollte, wohin gehört die Präsentationslogik?
Es stellt sich heraus, dass wir eine alte Technik namens verwenden können dekorateur muster.Die Idee ist, Ihr Modellobjekt mit einer anderen Klasse zu umschließen, die Ihre Präsentationslogik enthält.Diese Wrapper-Klasse wird als Dekorator.Der Dekorateur abstrahiert die Logik von Ihrer Ansicht, während Ihre Modelle von ihrer Präsentation isoliert bleiben.
Draper ist ein ausgezeichnetes Juwel, das hilft, Dekorateure zu definieren.
Der von Ihnen angegebene Beispielcode könnte folgendermaßen abstrahiert werden:
Übergeben Sie einen Dekorateur an die Ansicht mit @user = UserDecorator.new current_user
in Ihrem Controller.
Ihr Dekorateur könnte wie folgt aussehen.
class UserDecorator
decorates :user
def welcome_message
if user.admin?
"Welcome back, boss"
else
"Welcome, #{user.first_name}"
end
end
end
Und Ihre Ansicht würde einfach enthalten @user.welcome_message
Beachten Sie, dass das Modell selbst nicht die Logik zum Erstellen der Nachrichten enthält.Stattdessen umschließt der Dekorateur das Modell und übersetzt Modelldaten in eine darstellbare Form.
Hoffe das hilft!
Ich würde dafür einen Helfer benutzen.Angenommen, Sie müssen die Begrüßungsnachricht basierend auf einem Gebietsschema übersetzen.
In der app/helper/user_helper.rb
schreiben
module UserHelper
def welcome_message(user)
if user.admin?
I18n.t("admin_welcome_message", :name => user.name)
else
I18n.t("user_welcome_message", :name => user.name)
end
end
end
und aus deiner Sicht kannst du dann einfach schreiben
<%= welcome_message(user) %>
Beachten Sie, dass der Dekorateur / Präsentator einen wirklich sauberen objektorientierten Ansatz bietet, aber imho ist die Verwendung eines Helfers viel einfacher und ausreichend.
Nein, du willst nicht jeder bedingungen überhaupt in der Benutzerklasse noch im Controller.Der Sinn dieses Beispiels im Blogpost besteht darin, auf Polymorphismus zu verweisen, nur auf gutes altmodisches OO-Design.
# in application_controller for example
def current_user
if signed_in?
User.find(session[:user_id])
else
Guest.new
end
end
#app/models/user.rb
class User
def welcome_message
"hello #{name}"
end
end
#app/models/guest.rb
class Guest
def welcome_message
"welcome newcomer"
end
end
...du hast die Idee.
Erstellen Sie nur einen Dekorateur, der als Präsentator fungiert, anstatt Ihr Modell mit reinen Präsentationsmethoden zu verunreinigen:
require 'delegate'
class UserPresenter < SimpleDelegator
def welcome_message
"hello #{name}"
end
end
Und jetzt current_user
sieht so aus:
# application_controller
def current_user
if signed_in?
UserPresenter.new(User.find(session[:user_id]))
else
Guest.new
end
end
Dekorieren Sie das Benutzermodell und fügen Sie die welcome_message direkt hinzu.Ja, dies kann irgendwann eine Art bedingte Anweisung beinhalten.
http://robots.thoughtbot.com/post/14825364877/evaluating-alternative-decorator-implementations-in
Ich denke, Sie sollten sich die Railscasts-Episode über Moderatoren ansehen, um die Antwort zu erhalten.
Logik in der Ansicht ist schwer zu pflegen, wir sollten die Geschäftslogik in das Modell und die gesamte Ansichtslogik in Helfer einfügen.
Wenn Sie möchten, dass Ihr Code objektorientiert ist, verwenden Sie Dekoratoren (objektorientierte Art der Helfer)
Bestes Beispiel : https://github.com/jcasimir/draper
Geben Sie den Code ein, der definiert current_user.welcome_message
in _app / Helfer / application_helper .rb_ , es wird dann von jeder Ansicht zugänglich sein, die mit dem gerenderten Anwendung Layout.
Eine andere Möglichkeit besteht darin, eine zu definieren benutzerdefinierte Hilfsmodul, eines, das nicht unbedingt einer bestimmten Ansicht oder einem bestimmten Controller zugeordnet ist (siehe das Video, das ich unten verlinkt habe), und include
es in den Modulen der Ansicht / Controller, in denen Sie diese Funktionalität haben möchten.
Das ist nicht etwas, das schwarz und weiß ist.Aber nach dem, was Sie beschrieben haben, klingt es so, als wäre dies Code, der aufdringlich ist, um in Ihrem application_controller zu bleiben.rb und es ist kein Code mit Funktionalität, der seinen eigenen Controller rechtfertigt, die effektivste und effizienteste Option könnte darin bestehen, ein benutzerdefiniertes Hilfsmodul zu erstellen und es in die Helfer aufzunehmen, die Sie für diese Funktionalität benötigen.Das heißt, dies ist letztendlich ein Urteilsspruch, den der Designer der Anwendung (dh. Sie) muss sich entscheiden.
Hier ist ein guter Artikel, der Hilfsmodule von umreißt Mai, 2011
Hier es ist ein RailsCast-Entwurf benutzerdefinierte Hilfsmodule (z.B.benutzerdefiniert wie in Modulen, die nicht unbedingt einem bestimmten Controller oder einer bestimmten Ansicht zugeordnet sind).Kurz, süß und auf den Punkt.
Sie können eine Hilfsmethode für dieses Zeug definieren.Ich denke nicht, dass es eine gute Idee ist, Begrüßungssätze in einem Modell zu machen, aber auch in der Steuerung.Aber Sie sollten versuchen, Ihre Ansichten vom Code sauber zu machen, und wenn Sie dafür Helfer verwenden können, sollten Sie dies tun.
Eine gute Praxis wäre, echte zu haben View
instances.Rails-Parodie von MVP (es gibt einen Unterschied, schau es dir an) scheint leider so zu tun, als wären Ansichten Vorlagen.Das ist falsch.
Ansichten sollen die Präsentationslogik in MVC- und MVC-inspirierten Mustern enthalten.Sie sollen auch mehrere Vorlagen manipulieren und entscheiden, welche Vorlagen verwendet werden sollen, um den Status und die Informationen aus der Modellebene darzustellen (ja, das Modell ist eine Ebene, keine ORM-Instanz).
Also, um die Frage zu beantworten: Präsentationslogik hat in Controllern keinen Platz.