Est-ce que Rails Routing Helpers (ie mymodel_path (model)) peut être utilisé dans les modèles?

Disons que j’ai un modèle de Rails appelé Thing. Thing possède un atsortingbut URL qui peut éventuellement être défini sur une URL quelque part sur Internet. Dans le code de vue, j’ai besoin d’une logique qui effectue les opérations suivantes:

     

Cette logique conditionnelle dans la vue est laide. Bien sûr, je pourrais créer une fonction d’aide qui changerait la vue en ceci:

  

Cela résout le problème de verbosité, mais je préférerais vraiment avoir la fonctionnalité dans le modèle lui-même. Dans ce cas, le code de vue serait:

  

Ceci, évidemment, nécessiterait une méthode de lien sur le modèle. Voici ce qu’il devrait contenir:

 def link (self.url.blank?) ? thing_path(self) : self.url end 

Au sharepoint la question, thing_path () est une méthode indéfinie dans le code du modèle. Je suppose qu’il est possible d’introduire des méthodes d’aide dans le modèle, mais comment? Y a-t-il une vraie raison pour laquelle le routage ne fonctionne que sur le contrôleur et affiche les couches de l’application? Je peux penser à de nombreux cas où le code du modèle peut avoir à gérer des URL (intégration avec des systèmes externes, etc.).

Dans les rails 3, 4 et 5, vous pouvez utiliser:

 Rails.application.routes.url_helpers 

par exemple

 Rails.application.routes.url_helpers.posts_path Rails.application.routes.url_helpers.posts_url(:host => "example.com") 

J’ai trouvé la réponse à ma question. Dans le code du modèle, il suffit de mettre:

Pour les rails <= 2:

 include ActionController::UrlWriter 

Pour Rails 3:

 include Rails.application.routes.url_helpers 

thing_path(self) par magie, thing_path(self) retourne l’URL de la chose courante, ou other_model_path(self.association_to_other_model) renvoie une autre URL.

Vous pouvez également trouver l’approche suivante plus propre que d’inclure chaque méthode:

 class Thing delegate :url_helpers, to: 'Rails.application.routes' def url url_helpers.thing_path(self) end end 

Toute logique relative à ce qui est affiché dans la vue doit être déléguée à une méthode d’assistance, car les méthodes du modèle ne concernent que la gestion des données.

Voici ce que vous pourriez faire:

 # In the helper... def link_to_thing(text, thing) (thing.url?) ? link_to(text, thing_path(thing)) : link_to(text, thing.url) end # In the view... <%= link_to_thing("text", @thing) %> 

Bien qu’il y ait peut-être un moyen de garder ce type de logique hors du modèle. Je suis d’accord pour dire que vous ne devriez pas mettre cela dans la vue ( rest mince ) mais à moins que le modèle ne retourne une URL en tant que donnée au contrôleur, les éléments de routage devraient être dans le contrôleur.

(Edit: Oublie mon babble précédent …)

Ok, il pourrait y avoir des situations où vous iriez soit au modèle, soit à une autre URL … Mais je ne pense pas vraiment que cela appartient au modèle, la vue (ou peut-être le modèle) semble plus appropriée.

En ce qui concerne les routes, pour autant que je sache, les routes sont pour les actions dans les contrôleurs (qui utilisent généralement “magiquement” une vue), pas directement aux vues. Le contrôleur doit gérer toutes les demandes, la vue doit présenter les résultats et le modèle doit gérer les données et les transmettre à la vue ou au contrôleur. J’ai entendu beaucoup de gens ici parler de routes vers des modèles (au point que je commence presque à le faire), mais si je comprends bien: les routes vont aux contrôleurs. Bien sûr, de nombreux contrôleurs sont des contrôleurs pour un modèle et sont souvent appelés sController (par exemple, “UsersController” est le contrôleur du modèle “User”).

Si vous trouvez que vous écrivez de mauvaises quantités de logique dans une vue, essayez de déplacer la logique à un endroit plus approprié. la logique de demande et de communication interne appartient probablement au contrôleur, la logique liée aux données peut être placée dans le modèle (mais pas la logique d’affichage, qui inclut les balises de liaison, etc.) et la logique