Ho cercato il modo "consigliato" per utilizzare gli helper di visualizzazione di Rails (ad esempio link_to
, content_tag
) in una classe plain ruby, ad esempio un presenter. Sembra che ci siano pochissime informazioni su questo fronte e volevo avere un'idea di quello che pensava la comunità di Stack.Modo consigliato per utilizzare gli helper di visualizzazione di Rails in una classe di presentazione
Quindi, le opzioni che abbiamo sono .. (notare sto usando Rails 4, e sono meno preoccupati per le versioni precedenti)
Includere i moduli necessari manualmente
Questo è probabilmente il più pulito modo, poiché sono inclusi solo gli helper necessari. Tuttavia, ho riscontrato che questo metodo non funziona in alcuni casi, poiché il solito contesto di visualizzazione fornito in semplici helper di Rails è configurato per la richiesta corrente. url_for
non saprebbe, ad esempio, la richiesta corrente, quindi l'host potrebbe non corrispondere.
class MyPresenter
include ActionView::Helpers::UrlHelper
include ActionView::Helpers::CaptureHelper
def wrapped_link
content_tag :div, link_to('My link', root_url)
end
end
Uso ActionController::Base.helpers
Da Rails 3, ActionController::Base
ha incluso un metodo helpers
di accedere al contesto vista corrente. Credo che il contesto di visualizzazione fornito da questo metodo sia configurato come sarebbe in un helper di rotaie, ma potrei sbagliarmi. Non c'è davvero alcuna documentazione su questo che sembra preoccupante, ma funziona abbastanza bene nella pratica.
class MyPresenter
def wrapped_link
h.content_tag :div, h.link_to('My link', h.root_url)
end
protected
def h
ActionController::Base.helpers
end
end
Credo che questo contesto di vista può anche essere mescolato con include
, ma i binari visualizzare aiutanti avere centinaia di metodi e ci si sente sporca di includerli tutti indistintamente.
Iniettare contesto vista quando chiama il presentatore
Infine, potremmo passare il contesto di visualizzazione alla classe quando è inizializzato (o alternativamente in un metodo render
)
class MyPresenter
attr_accessor :context
alias_method :h, :context
def initialize(context)
@context = context
end
def wrapped_link
h.content_tag :div, h.link_to('My link', h.root_url)
end
end
class MyController < ApplicationController
def show
# WARNING - `view_context` in a controller creates an object
@presenter = MyPresenter.new(view_context)
end
end
personalmente
I tendono ad inclinarsi verso le ultime due opzioni, ma senza una risposta definitiva dal team Rails (che sono stato in grado di trovare) mi sono sentito un po 'insicuro. Chi meglio chiedere che Stack!
Buon punto sullo stubbing' ActionController: : Base.helpers', non ci avevo pensato. Stilisticamente questa sembra la migliore strada da percorrere, e dopo un po 'di ricerche penso che il migliore (solo) 'view_context' da usare sia quello fornito dal controller o dall'helper che chiama il presentatore. – tombeynon