2013-11-15 8 views
10

Attualmente sto eseguendo alcuni calcoli nel mio punto di vista, che è una brutta cosa, naturalmente:Rails - spostare i calcoli dalle mie visualizzazioni?

<% categories.each do |c| %> 
    .... 
    <%= c.transactions.sum("amount_cents") %> 
    .... 
<% end %> 

Sto ricercando modi che mi aiuteranno a refactoring la questione di cui sopra.

Una cosa è quello di spostare il calcolo per il mio controller

@category_sum = @transaction.sum("amount_cents") 

che è probabilmente una soluzione migliore, ma si sa. Non perfetto.

Poiché ho molti utenti, non vedo come posso spostare la logica della calcolatrice nel mio modello. Quindi penso che potrei aver bisogno di usare una nuova classe, creare una serie di metodi (somma, media, ecc.) E usarli nelle viste? Sono sulla buona strada? Sarò grato per qualsiasi consiglio su come ristrutturare il mio codice e progettare e implementare questa classe.

+0

è possibile creare un metodo di supporto che restituisce html dall'oggetto c? e quindi iniettare il risultato dall'helper con .html sicuro? – ant

risposta

9

Un mezzo per isolare la logica di visualizzazione è utilizzare i relatori.

Un presentatore permette di fare qualcosa di simile:

<% categories.each do |c| %> 
    .... 
    <% present c do |category| %> 
    <%= category.transaction_sum %> 
    <% end %> 
    .... 
<% end %> 

Devi quindi una classe di presentatore in app/presenters/category_presenter.rb:

class CategoryPresenter < BasePresenter 
    presents :category 

    def transaction_sum 
    category.transactions.sum("amount_cents") 
    end 
end 

Naturalmente, è meglio utilizzato se si dispone di molti metodi quel presentatore (ma una volta che si inizia a ridurre la logica di visualizzazione, è veloce riempire i presentatori).

L'implementazione utilizzata qui si basa su quanto descritto in this pro railscast. L'idea di base è semplicemente quella di avere un helper #present che inferisca un nome di classe basato sulla classe dell'oggetto, carichi e inizializzi la classe del presentatore corretta.

Un'altra alternativa popolare è utilizzare drapper, che utilizzano il concetto di decoratore, ma un presentatore è fondamentalmente un decoratore.

+0

grande idea uomo! ;) – apneadiving

+0

Lo so, un bravo ragazzo me l'ha dimostrato;) –

+0

Mi ci sono voluti un paio di giorni per imparare, ma ne è valsa la pena! Grazie per questa risposta. –

2

L'odore di codice principale che viene visualizzato si chiama the law of Demeter (che, come molte "leggi" di programmazione, dovresti pensarlo più come una "linea guida di Demeter").

Ciò che è possibile fare è spostare la fase di calcolo effettiva in un metodo sulla categoria, ad es.

class Category < ActiveRecord::Base 
    def transaction_amount 
    transactions.sum("amount_cents") 
    end 
end 

<% categories.each do |c| %> 
    .... 
    <%= c.transaction_amount %> 
    .... 
<% end %> 

Tecnicamente parlando il calcolo viene ancora eseguita durante il rendering la vista, ma la logica per come che riassume importo viene calcolato non è più all'interno della vista stessa. Tutto ciò che interessa ora è che può inviare il messaggio transaction_amount agli oggetti categoria. Questo lascia anche spazio per l'aggiunta di una cache per le somme, o per l'interruzione del passaggio dei record effettivi, ma invece per passare oggetti statici (che non sono modelli ActiveRecord) che escono da una parte di codice che esegue la somma in un modo più efficiente.

Problemi correlati