Mettere logica di presentazione in controller è una buona pratica in Ruby?
-
12-12-2019 - |
Domanda
Qualche raccomandazione [1] consigliamo di utilizzare
<%= current_user.welcome_message %>
invece di
<% if current_user.admin? %>
<%= current_user.admin_welcome_message %>
<% else %>
<%= current_user.user_welcome_message %>
<% end %>
Ma il problema è che si deve la decisione di logica da qualche parte nel codice.
La mia comprensione è messa la decisione in template
è meglio controller
come rendere il vostro controller più pulito.È corretto?
Ci sono il modo migliore per gestire questa situazione?
Soluzione
A mio parere, se il testo è l'unica cosa che cambia, non appartiene a una vista.Se avevi bisogno di ristrutturare la pagina, questa è la logica di presentazione.Questo, questo è solo i dati sono diversi.
Altri suggerimenti
Non sei il primo a chiederlo. Se le viste e i controller dovrebbero avere poco a nessuna logica, e il modello dovrebbe essere agnostico di presentazione, dove appartiene la logica di presentazione?
si scopre che possiamo usare una vecchia tecnica chiamata Decorator Pattern . L'idea è di avvolgere l'oggetto modello con un'altra classe che contiene la tua logica di presentazione. Questa classe wrapper è chiamata il decoratore . Il decoratore abstrae la logica dalla tua vista, pur mantenendo i tuoi modelli isolati dalla loro presentazione.
Draper è un gemma eccellente che aiuta a definire decorati.
Il codice di esempio che hai dato potrebbe essere astratto come SO:
Passa un decoratore alla vista con @user = UserDecorator.new current_user
nel tuo controller.
Il tuo decoratore potrebbe sembrare sotto.
.
class UserDecorator
decorates :user
def welcome_message
if user.admin?
"Welcome back, boss"
else
"Welcome, #{user.first_name}"
end
end
end
E la tua opinione contiene semplicemente @user.welcome_message
Si noti che il modello stesso non contiene la logica per creare i messaggi. Invece, il decoratore avvolge il modello e traduce i dati del modello in una forma presentabile.
Spero che questo aiuti!
Userei un aiutante per questo.Supponiamo che tu debba tradurre il messaggio di benvenuto, in base ad alcuni locali.
nel app/helper/user_helper.rb
scrivere
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
.
E nella tua vista puoi semplicemente scrivere
<%= welcome_message(user) %>
.
Nota che il decoratore / Presenter offre un approccio orientato all'oggetto davvero pulito, ma IMHO usando un aiutante è molto più semplice e sufficiente.
No, non si desidera qualsiasi condizionale in tutto la classe utente né il controller.Il punto di quell'esempio sul post del blog è quello di fare riferimento al polimorfismo, solo un buon design OO vecchio stile.
.
# 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
... Hai l'idea.
Solo, invece di festeggiare il tuo modello con metodi di sola presentazione, creare un decoratore che funge da presentatore:
.
require 'delegate'
class UserPresenter < SimpleDelegator
def welcome_message
"hello #{name}"
end
end
E ora current_user
sembra così:
.# application_controller
def current_user
if signed_in?
UserPresenter.new(User.find(session[:user_id]))
else
Guest.new
end
end
Decorare il modello utente e aggiungi direttamente il welcome_message.Sì, questo può coinvolgere una specie di dichiarazione condizionale ad un certo punto.
http://robots.Thishtbot.com/post/14825364877 / Valutazione-Alternative-Decorator-Implementazioni-in
Penso che dovresti guardare l'episodio di railscasts su presentatori per la risposta.
Logica Nella vista è difficile da mantenere, dovremmo inserire la logica aziendale nel modello e tutta la logica di visualizzazione di Guardi.
Se vuoi che il tuo codice sia in modo orientato all'oggetto, fare uso di decoratori (modo orientato all'oggetto di aiuto)
Miglior esempio: https://github.com/jcasimir/dreper
Inserire il codice di definizione current_user.welcome_message
in _app/helpers/application_helper.rb_, che sarà quindi accessibile da qualsiasi visualizzazione rendering con il applicazione il layout.
Un'altra opzione è quella di definire un personalizzato helper module, che non è necessariamente associato ad un dato o di un controller (Vedi il video che ho linkato qui sotto), e include
in moduli della view/controller si desidera avere quella funzionalità.
Questo non è qualcosa che è in bianco e nero.Ma, da quello che hai descritto sembra che questo è il codice che è invadente a bastone in application_controller.rb e non è il codice di funzionalità che lo giustifica proprio controller, il più efficace ed efficiente opzione potrebbe essere quella di creare un custom helper module nel aiutanti si desidera avere quella funzionalità.Detto questo, è, in definitiva, un giudizio di appello che il progettista dell'applicazione (es. si) deve decidere.
Qui è un buon articolo che illustra helper moduli da Maggio, 2011
Qui è un RailsCast delineando personalizzato helper moduli (es.come personalizzato in moduli non necessariamente associato ad un determinato controller o vista).Breve, dolce e al punto.
È possibile definire il metodo dell helper per quella roba.Non penso che sia una buona idea fare una gradita frasi in un modello, ma anche nel controller.Ma dovresti provare a farti vedere le viste dal codice e se puoi usare gli aiutanti per questo, dovresti.
Una buona pratica sarebbe avere istanze reali View
.Rails parodia di MVP (c'è la differenza, cercava) Sfortunatamente sembra fingere che le opinioni siano modelli.Questo è sbagliato.
Le viste dovrebbero contenere la logica di presentazione nei modelli MVC e MVC.Dovrebbero anche manipolare più modelli e prendere una decisione su cui i modelli impiegano per rappresentare lo stato e le informazioni dallo strato modello (Sì, il modello è un livello non è un'istanza ORM).
Quindi, per rispondere alla domanda: La logica di presentazione non ha posto nei controller.