2010-05-12 11 views
5

ho nel mio modello:Informazioni sul pattern del presenter nelle guide. è un modo migliore per farlo?

def presenter 
    @presenter ||= ProfilePresenter.new(self) 
    @presenter 
end 

Il ProfilePresenter è una classe che ha metodi come, get_link(), get_img_url (dimensione), get_sex(), get_relationship_status() e altri metodi che non hanno a che fare con il modello, nemmeno con il controller ma viene utilizzato più volte nella vista.

Così ora li usano in questo modo:

Profile.presenter.get_link 
# or 
Profile.presenter.get_img_url('thumb') # returns the path of the image. is not used to make a db query 

Sincerelly Credo di aver perso il vero concetto di presentatori .. ma questo è quello che sto cercando di archiviare, come può essere chiamato questo?

risposta

16

Normalmente questo genere di cose viene gestita tramite metodi helper, come ad esempio:

def profile_link(profile) 
    profile.link ? content_tag(:a, h(profile.name), :href => profile.link) : 'No profile' 
end 

E 'un peccato non si può sovrapporre a metodi di supporto in stile presentatore che si estendono un modello in fase di visualizzazione. Devono essere chiamati in modo procedurale con un parametro, tipo di anti-OO.

L'approccio di Presenter non è completamente supportato nell'area Rails MVC perché è necessario associare una vista per poter accedere ai vari metodi di supporto necessari per il rendering corretto del contenuto, oltre alle informazioni sulla sessione che possono influire sulla presentazione .

Un approccio più robusto potrebbe essere quello di fare qualcosa di simile:

class ProfilePresenter 
    def initialize(view, profile) 
    @profile = profile 
    @view = view 

    yield(self) if (block_given?) 
    end 

    def link 
    @profile.link ? @view.content_tag(:a, @view.h(profile.name), :href => @profile.link) : 'No profile' 
    end 

    def method_missing(*args) 
    @profile.send(*args) 
    end 
end 

Questo si presentava nella vista come qualcosa di simile:

<% ProfilePresenter.new(self, @profile) do |profile| %> 
<div><%= profile.link %> 
<% end %> 

È possibile semplificare la chiamata a questo facendo un aiutante metodo che fa qualcosa di leggermente pazzo come:

def presenter_for(model) 
    "#{model.class}Presenter".constantize.new(self, model) do |presenter| 
    yield(presenter) if (block_given?) 
    end 
end 

Questo significa che hai un modo molto più semplice call:

<% presenter_for(@profile) do |profile| %> 
<div><%= profile.link %> 
<% end %> 
+0

Questo è un approccio molto bello. Pulito. Stai usando qualcosa di simile ora? – nathanvda

+0

Non è più semplice da usare: "@ profile.presenter.get_url" ed è pronto per partire? oppure potrebbe essere più compresso come: "@ profile.pr.get_url". Questo perché non uso così tanto nei loop ma in altre cose quindi l'uso sarebbe: "presenter_for (@profile) .get_url" –

+0

@nathanvda Ho usato approcci come questo prima con i wrapper, anche se non hanno seguito il Modello presentatore da vicino. Questa è una tecnica per collegare i mondi Modello e Vista. – tadman

Problemi correlati