web-dev-qa-db-fra.com

Rails: afficher la vue depuis le contrôleur extérieur

J'essaie de créer une chaîne HTML en utilisant une vue. Je voudrais rendre ceci d'une classe qui n'est pas un contrôleur. Comment utiliser le moteur de rendu Rails en dehors d'un contrôleur? Semblable à la façon dont ActionMailer fait?

Merci!

19
prajo

Rails 5 supporte maintenant cela d'une manière beaucoup plus pratique qui gère la création d'une requête et autres tâches en coulisses:

rendered_string = ApplicationController.render(
  template: 'users/show',
  assigns: { user: @user }
)

Cela restitue app/views/users/show.html.erb et définit la variable d'instance @user de sorte que vous n'ayez pas besoin de modifier votre modèle. Il utilise automatiquement la disposition spécifiée dans ApplicationController (application.html.erb par défaut). 

Le test montre une poignée d'options et d'approches supplémentaires.

36
coreyward

Vous pouvez utiliser ActionView :: Base pour y parvenir.

view = ActionView::Base.new(ActionController::Base.view_paths, {})
view.render(file: 'template.html.erb')

Le ActionView :: Base initialize prend:

  1. Un contexte, représentant les chemins de recherche de modèles
  2. Un hash assigns, fournissant les variables pour le template

Si vous souhaitez inclure des aides, vous pouvez utiliser class_eval pour les inclure:

view.class_eval do
  include ApplicationHelper
  # any other custom helpers can be included here
end
31
cweston

Il n'est pas nécessaire de surcharger votre application avec trop de gemmes. Comme nous le savons, ERB est déjà inclus dans votre application Rails.

@jdf = JDF.new
@job = ERB.new(File.read(Rails.root + "app/views/entries/job.xml.erb"))
result =  @job.result(binding)

Ci-dessus, un extrait de code d'une application sur laquelle je travaille. 

  • @jdf est un objet à évaluer dans la vue erb
  • Dans mon cas, je devais rendre xml.
  • result est une chaîne à enregistrer ou à envoyer où bon vous semble.
4
Jesse

Techniquement, ActionMailer est une implémentation de AbstractController::Base dans la sous-classe. Si vous souhaitez implémenter vous-même cette fonctionnalité, vous voudrez probablement également hériter de AbstractController::Base.

Il y a un bon article de blog ici: https://www.amberbit.com/blog/2011/12/27/render-views-and-partials-outside-controllers-in-Rails-3/ ça explique les étapes nécessaires.

1
locriani

"J'essaie de créer une chaîne HTML en utilisant une vue." - Si vous voulez dire que vous êtes dans le contexte d'un modèle de vue, utilisez simplement une méthode d'assistance ou restituez un rendu partiel.

Si vous êtes dans un autre "Plain Old Ruby Object", gardez à l'esprit que vous êtes libre d'utiliser directement le module ERB:

erb = ERB.new("path/to/template")
result = erb.result(binding)

L'astuce consiste à obtenir cet objet 'obligatoire' qui donne le contexte du code dans le modèle. ActionController et d'autres classes Rails l'exposent gratuitement, mais je n'ai pas trouvé de référence qui explique d'où il provient.

http://www.Ruby-doc.org/stdlib-2.2.0/libdoc/erb/rdoc/ERB.html#method-i-result

0
vpsz

Pour référence future, j'ai fini par trouver Ce petit bijou pratique qui en fait un jeu d'enfant:

https://github.com/yappbox/render_anywhere

0
prajo

Il est préférable de rendre la vue à l’aide d’un contrôleur, comme c’est à quoi ils servent, et then le convertir en chaîne, car c’est là votre objectif ultime.

require 'open-uri'
html = open(url, &:read)
0
steven_noble