50 votes

Afficher l'assistant link_to dans la classe Model

En utilisant Rails 3, y a-t-il un moyen d'utiliser link_to helper, ou n'importe quel assistant à l'intérieur du modèle?

86voto

Chuck Vose Points 3235

Il ya quelques raisons qui vous pouvez avoir besoin de link_to dans un modèle. Oui, @andy, c'est une violation de la MVC, mais cela ne signifie pas que vous devriez obtenir des points pour ne pas répondre à la question.

@schwabsauce, il est plus facile que cela. La première ligne n'est pas encore strictement nécessaire si vous le faites dans un initialiseur ou quelque chose. Même chose travaille .désinfecter et .raw et un tas d'autres impressionnant de fonctions.

ActionView::Base.send(:include, Rails.application.routes.url_helpers)
ActionController::Base.helpers.link_to(whatever)

Si vous souhaitez utiliser autopaths vous pourriez avoir à faire ce à l'intérieur de votre link_to:

Rails.application.routes.url_helpers.page_path(@page)

32voto

rantler Points 369

Soyez très prudent en suivant les conseils décrits dans le Mandrin de la poste si vous ne le faites pas dans les Rails 3.2.1 . Il semble comme si cette approche n'est pas une bonne façon de le faire, y compris la link_to aide dans le non-affichage de classes dans les Rails 3.2.1. Il y a un moyen plus sûr (qui travaille pour nous en tout cas) décrites ci-dessous.

Lorsque nous avons utilisé l'approche de Chuck poste dans l'une de nos classes, il a fini par avoir très troublant et difficile à déboguer les conséquences. Il a fini par causer des effets secondaires / bugs que seuls de très spécifique (et rare), les circonstances.

Le problème, aussi loin que nous pouvons dire, c'est que cette ligne:

ActionView::Base.send(:include, Rails.application.routes.url_helpers)

Dit ActionView::Base d'inclure l' Rails.application.routes.url_helpersqui ActionView::Base apparemment déjà fait sur son propre. Avoir incluent l' url_helpers un deuxième temps, semble provoquer une ré-initialisation de l'état des routes (@_routes dans les classes qui ont inclus la ActionDispatch::Routage::UrlFor module).

Cela conduit à apparemment aléatoire et inexpliquée "undefined method 'url_for' for nil:NilClass" exceptions dans des vues tenter d'appel, directement ou indirectement, la url_for méthode après l' ActionView::Base a inclus l' url_helpers la deuxième fois.

La solution qui a fonctionné pour nous a été lieu de raconter ActionView::Base d'inclure l' url_helpers de nouveau, il suffit d'inclure l' UrlHelper module vous-même où vous pourriez en avoir besoin.

Puis, quand vous avez besoin d'utiliser link_to et d'avoir accès au chemin d'accès, vous pouvez simplement le faire (en supposant que login_path est valable pour votre application):

include ActionView::Helpers::UrlHelper
...
link = link_to('here', Rails.application.routes.url_helpers.login_path)

Il nous a fallu un temps très long et beaucoup de casse-tête pour traquer les bugs causés par le double inclure et je voulais juste avertir les autres d'être prudent lors de peaufiner le comportement des Rails classes de base.

5voto

schwabsauce Points 129

Je travaille avec les inclusions suivantes:

 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
 

Ensuite, dans mon contrôleur, j'ai renseigné l'attribut (la création d'un contrôleur à partir de zéro nécessite une quantité importante de données dans le hachage des arguments).

 Lead.controller = self
 

3voto

bbozo Points 2090

link_to helper, MVC violation

Ce que Andy a dit,

si vous êtes à la génération de code HTML, dans le modèle, vous avez probablement besoin de prendre un grand temps d'observer ce que vous faites et pourquoi.

URL aides

Url d'autre part est souvent utile en dehors de la vue-contrôleur de code, dans tous les types de services/forme/api/... classes par exemple, même dans les modèles si vous devez.

Oui, Rails.application.les itinéraires.url_helpers est un module, mais cela ne signifie pas que vous devez simplement l'inclure et où de drôles de choses vont commencer à se produire en tant que Gary a dit:

https://www.destroyallsoftware.com/blog/2011/one-base-class-to-rule-them-all

Ce que vous pouvez faire est:

    delegate :url_helpers, :to => 'Rails.application.routes'

et puis l'utilisation, par exemple

    url_helpers.home_url

-8voto

Andy Lindeman Points 7213

Pas sans piratage.

Si vous pensez avoir besoin de link_to dans un modèle, vous enfreignez probablement certains principes de l' architecture Model-View-Controller .

Un modèle doit constituer un emplacement pour les données et la logique métier, mais la génération de liens est presque certainement un travail pour le contrôleur ou la vue (ou, en particulier pour Rails, dans une classe d'assistance).

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X