5 votes

Inclure les délimiteurs ERB à l'intérieur d'une chaîne dans un bloc ERB

Je travaille sur un guide de style qui affiche le code, ainsi que le résultat. Actuellement, il est structuré de sorte que le code n'ait besoin d'être décrit qu'une seule fois et soit affiché dans ses versions brute et interprétée, comme ceci :

 <% code = <
  #{ image_tag 'image.png' }

PLACE_THE_EXAMPLE_CODE_BETWEEN_THESE_TWO_LINES_EXACTLY_AS_YOU_WANT_IT_TO_APPEAR
%>

<%= raw code %>
<%= content_tag :pre, code, class: "prettyprint linenums" %>

C'est super, et assez facile à maintenir. Le problème vient des aides de rails, comme image_tag dans l'exemple ci-dessus. L'exemple de vue affiche correctement une image dans une div, et l'exemple de code affiche le HTML pertinent. Dans ce cas, le HTML pertinent inclut une balise d'ancre - les résultats de la méthode image_tag, pas l'appel lui-même.

Je préférerais que les exemples de code affichent les méthodes d'aide, plutôt que leurs résultats. Je suis capable de faire fonctionner cela en spécifiant le code de l'exemple dans un fichier, et en rendant ou en lisant le fichier. Je préférerais faire fonctionner cela en spécifiant le code dans une variable, comme ci-dessus, mais je n'arrive pas à obtenir un délimiteur ERB à fonctionner à l'intérieur d'une chaîne à l'intérieur d'un bloc erb. Même le cas le plus simple de <% foo = '<%= bar %>' %> ne fonctionne pas du tout. J'ai essayé de jouer avec la syntaxe (<%% %%> et % % par exemple), en utilisant des détails de la documentation officielle, sans grand succès.

La seule information que j'ai pu trouver sur cette question est ici, en utilisant <%= "<" + "%=" %> link_to <%= image.css_tag.humanize %> <%= "%" + ">" %> %>, qui ne fonctionne pas dans ce cas d'utilisation (si jamais).

Alors, y a-t-il un moyen de spécifier une chaîne qui contient un délimiteur ERB de fin (%>) dans une chaîne ERB, ou suis-je obligé d'utiliser la méthode de lecture de fichier légèrement plus lourde ? Merci !

Édition :

Ce que je voudrais obtenir à la fin est une version fonctionnelle de ceci :

 <%# Code idéalisé - ne fonctionne pas %>
<% code = <
  <% image_tag 'image.png' %>

PLACE_THE_EXAMPLE_CODE_BETWEEN_THESE_TWO_LINES_EXACTLY_AS_YOU_WANT_IT_TO_APPEAR
%>

Donc <%= raw code %> devrait (continuer à) produire :

Et <%= content_tag :pre, code, class: "prettyprint linenums" %> devrait produire :

    <% image_tag 'image.png' %>

Au lieu de ce qu'il fait actuellement lorsqu'on utilise une variable, qui est :

Je veux que les utilisateurs puissent copier l'exemple de code et le coller dans une nouvelle vue, sans avoir à traduire le HTML en arrière dans les aides qui les produisent. Je pense que ce dont j'ai essentiellement besoin est un délimiteur ERB alternatif, de la même manière que ' et " (ou même %q{}) varient pour les chaînes. Il semble que même si le délimiteur ERB final apparaît à l'intérieur d'une chaîne, il est en fait traité comme la fin du bloc. Le cas le plus simple de <% foo = '<%= bar %>' %> démontre un peu ce que je veux accomplir. Dans un générateur, vous pourriez utiliser <% foo = '<%%= bar %>' %> (ou quelque chose de similaire), pour lui dire de ne pas traiter en tant qu'ERB à ce moment-là. Tout fonctionne bien lorsque vous lisez à partir d'un fichier, ou même dans un fichier rb pur (comme un helper), mais il est plus logique de le mettre dans la vue, dans ce cas, car il est destiné à être facilement manipulé par nos designers.

5voto

mu is too short Points 205090

Si je comprends bien, votre vrai problème est que les heredocs se comportent comme des guillemets doubles en ce qui concerne l'interpolation. Donc tout ce dont vous avez besoin est un mécanisme de guillemet qui se comporte comme des guillemets simples. Ruby a beaucoup de mécanismes de guillemets de chaîne, en particulier nous avons %q{...}:

<% code = %q{

  #{ image_tag 'image.png' }

} %>

Vous pouvez utiliser d'autres délimiteurs si vous le souhaitez : %q|...|, %q(...), etc. Il y a toujours un changement bien sûr mais au moins vous n'avez pas à vous soucier des problèmes d'interpolation.

Si vous voulez vraiment utiliser un heredoc, vous pouvez spécifier le terminateur heredoc avec des guillemets et le style de guillemet correspondant s'appliquera au contenu :

<% code = <<'PLACE_THE_EXAMPLE_CODE_BETWEEN_THESE_TWO_LINES_EXACTLY_AS_YOU_WANT_IT_TO_APPEAR'

  #{ image_tag 'image.png' }

PLACE_THE_EXAMPLE_CODE_BETWEEN_THESE_TWO_LINES_EXACTLY_AS_YOU_WANT_IT_TO_APPEAR
%>

Les guillemets simples dans <<'PLACE...' spécifient que les règles de guillemets simples (c'est-à-dire aucune interpolation) s'appliquent au contenu de l'heredoc.


Évidemment, rien de tout cela ne fonctionnera avec les ERB imbriqués comme ceci :

<% code = %q{

  <% ... %>

} %>

car le parseur ERB verra le premier %> comme le délimiteur de clôture pour la partie externe <% code.... Ne vous inquiétez pas, je pense que j'ai un plan qui fonctionnera sans impliquer de piratages grossiers ou trop de travail.

Quelques préliminaires :

En utilisant ce qui précède, vous pouvez ajouter votre propre format de modèle qui est ERB avec un délimiteur différent et vous pouvez faire en sorte que Rails utilise ce nouveau format pour gérer vos sections "spéciales" avant que le traitement ERB normal ne gâche les choses.

Tout d'abord, vous devez connecter Tilt. Si vous regardez lib/tilt/erb.rb dans votre installation Tilt, vous verrez les choses Erubis dans Tilt::ErubisTemplate en bas. Vous devriez pouvoir sous-classer Tilt::ErubisTemplate et fournir un remplacement de prepare qui ajoute, disons, une option :pattern => '' et envoie à la classe mère. Ensuite, enregistrez ceci avec Tilt et Sprockets dans un initialisateur Rails avec quelque chose comme ceci :

Tilt.register(Your::Template::Subclass, 'klerb') # "kl" pour "kludge" :)
Rails.application.assets.register_engine('.klerb', Your::Template::Subclass)

Maintenant votre application devrait être capable de gérer les fichiers .klerb avec comme délimiteurs de modèle. Et vous pouvez également chaîner votre klerb avec erb en utilisant des noms comme pancakes.html.erb.klerb et le fichier passera par klerb avant l'ERB; cela signifie que les modèles comme celui-ci (dans un fichier appelé whatever.html.erb.klerb) :

<% do_normal_erb_stuff %>

feront ce qu'il faut.

Vous auriez besoin d'un helper pour implémenter la fonctionnalité escape_the_erb_as_needed bien sûr; un peu d'expérimentation devrait vous aider à déterminer ce qui doit être échappé et de quelle manière.

Tout cela peut sembler un peu compliqué mais c'est en fait assez simple. J'ai ajouté des étapes de traitement de modèles personnalisées en utilisant Tilt et Sprockets et cela s'est avéré être assez simple à la fin ; trouver quelles choses simples à faire a pris un peu de travail mais j'ai déjà fait ce travail pour vous :

  1. Sous-classe de Tilt::Template, vous l'obtenez en vous appuyant sur Tilt::ErubisTemplate.
  2. Enregistrez avec Tilt en appelant Tilt.register.
  3. Enregistrez avec Sprockets en appelant Rails.application.assets.register_engine.
  4. ...
  5. Profit.

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