Utilizzo di Rails 3, esiste un modo per utilizzare link_to helper o qualsiasi altro helper per tale argomento all'interno del modello?Visualizza helper link_to in Classe di modello
risposta
Ci sono alcuni motivi per cui è necessario collegare link a un modello. Sì, @andy, è una violazione di MVC, ma ciò non significa che dovresti ottenere punti per non rispondere alla domanda.
@schwabsauce, è più facile di così. La prima riga non è nemmeno strettamente necessaria se lo si fa in un inizializzatore o qualcosa del genere. La stessa cosa funziona per .sanitize e .raw e un intero carico di altre fantastiche funzioni.
ActionView::Base.send(:include, Rails.application.routes.url_helpers)
ActionController::Base.helpers.link_to(whatever)
Se si desidera utilizzare autopaths si può avere a che fare questo all'interno del vostro link_to:
Rails.application.routes.url_helpers.page_path(@page)
Non senza hackery.
Se si ritiene che sia necessario il modello link_to
in un modello, è probabile che violare alcuni principi dello Model-View-Controller architecture.
Un modello deve essere un luogo per dati e business logic, ma la generazione di collegamenti è quasi certamente un lavoro per il controller o la vista (o, in particolare Rails, in una classe helper).
Grazie. Spostate le cose per vedere l'helper. Tutto va bene adesso. – Krule
Ci sono buoni motivi per utilizzare gli helper nei modelli. Ma più che altro, se hai intenzione di offrire un'opinione, almeno offri una soluzione nel caso in cui ci abbiano pensato. È possibile che qualcuno con 2k rep abbia la testa dritta. –
ho avuto questo lavoro con le seguenti inclusioni:
include ActionView::Helpers::UrlHelper
include ActionController::UrlFor
include Rails.application.routes.url_helpers
cattr_accessor :controller
def controller; self.class.controller; end
def request; controller.request; end
Poi nel mio controller ho popolato l'attributo (creando un controller da zero richiede una notevole quantità di dati negli argomenti cancelletto).
Lead.controller = self
fwiw, la documentazione di Rails apre la strada a questa soluzione. I documenti per ActionDispatch :: Routing :: UrlFor sottolineano che "Suggerimento: se devi generare URL dai tuoi modelli o da qualche altra posizione, allora ActionController :: UrlFor è quello che stai cercando." Quindi quando includi quel file che offre come messaggio di errore: raise "Per utilizzare #url_for, devi includere esplicitamente helper di routing." "Ad esempio,' include Rails.application.routes.url_helpers " Quindi penso che questo è accettabile dalle convenzioni Rails - a volte questo è il modo migliore/luogo migliore per generare un collegamento :) – schwabsauce
Sì, ad esempio, se il modello gestisce l'autorizzazione di pagamento a un terzo, gateway offsite e deve generare URL di ritorno/annullamento torna alla app. – hoffmanc
essere molto attenti seguendo i consigli delineato nel post di Chuck se si sta facendo questo in Rails 3.2. 1. Sembrerebbe che questo approccio non sia un modo sicuro per includere il link_to helper nelle classi non-view in Rails 3.2.1. C'è un modo più sicuro (che funziona per noi in ogni caso) delineato di seguito.
Quando abbiamo utilizzato l'approccio nel post di Chuck in una delle nostre classi, ha finito per avere conseguenze molto spinose e difficili da debugare. Ha finito per causare effetti collaterali/bug che si sono presentati solo in circostanze molto specifiche (e rare).
Il problema, per quanto possiamo dire, è che questa linea:
ActionView::Base.send(:include, Rails.application.routes.url_helpers)
sta dicendo ActionView::Base
per includere il Rails.application.routes.url_helpers
, che a quanto pare ActionView::Base
fa già per conto suo. Avere incluso la url_helpers
una seconda volta, sembra causare la reinizializzazione dello stato dei percorsi (@_routes nelle classi che hanno incluso il modulo ActionDispatch :: Routing :: UrlFor).
questo porta a apparentemente casuale e inspiegabile "metodo non definito 'url_for' per nil: NilClass" eccezioni in viste che tentano di chiamare, direttamente o indirettamente, il metodo url_for dopoActionView::Base
ha incluso la url_helpers
la seconda volta.
La soluzione che ha funzionato per noi era invece di dire ActionView::Base
per includere il url_helpers
ancora una volta, è sufficiente includere il modulo UrlHelper
te, ovunque si potrebbe averne bisogno.
Poi, quando è necessario utilizzare link_to e avere accesso al percorso si può semplicemente fare questo (login_path supponendo che è valido per la vostra applicazione):
include ActionView::Helpers::UrlHelper
...
link = link_to('here', Rails.application.routes.url_helpers.login_path)
C'è voluto un tempo molto lungo e un bel po ' di grattarsi la testa per rintracciare i bug causati dalla doppia inclusione e volevo solo avvertire gli altri di fare attenzione nel modificare il comportamento delle classi base di Rails.
Grazie per averlo condiviso! Sono felice che tu abbia trovato un modo migliore! –
One-liner: 'include ActionView :: Helpers :: UrlHelper' – karlingen
@karlingen - omettendo il riferimento a' Rails.application.routes ... 'può portare al messaggio" gli argomenti passati a url_for non possono essere gestiti. richiedere percorsi o fornire la propria implementazione " – Del
link_to aiutante, MVC violazione
Cosa Andy ha detto,
se si sta generando HTML nel modello probabilmente bisogno di prendere un lungo sguardo grande a quello che si sta facendo e perché.
URL aiutanti
URL d'altra parte spesso tornare utile al di fuori del codice di view-controller, in tutti i tipi di servizi/form/api/... classi per esempio, anche nei modelli se dovere.
Sì, Rails.application.routes.url_helpers è un modulo, ma questo non significa che si dovrebbe solo includere ovunque o cose divertenti avrà inizio accadendo come Gary dirla:
https://www.destroyallsoftware.com/blog/2011/one-base-class-to-rule-them-all
Cosa si può fare è:
delegate :url_helpers, :to => 'Rails.application.routes'
e quindi utilizzare, per esempio
url_helpers.home_url
Questa domanda è stata posta qualche tempo fa e in quel momento il consiglio di @ andy mi ha aiutato a risolvere questo problema. Tuttavia, hai ragione nel senso che non risponde alla domanda reale. – Krule