27 votes

Utilisation de layouts dans des fichiers HAML indépendamment de Rails

Mon objectif final est de créer plusieurs fichiers HTML statiques pour les transmettre à d'autres personnes.

Mais pour mon flux de travail, j'aimerais avoir HAML comme fichiers source de base. Ce faisant, j'espère pouvoir assécher le processus, du moins de mon côté.

J'ai maintenant beaucoup de pages qui vont finalement partager une mise en page commune, et je me demande comment incorporer les mises en page.

Voici mon code actuel :

./compile.rb

#!/usr/bin/env ruby

require 'rubygems'
require 'rake'
require 'haml'

FileList.new('./src/*.html.haml').each do |filename|
  if filename =~ /([^\/]+)\.haml$/
    File.open($1, 'w') do |f|
      f.write Haml::Engine.new(File.read(filename)).render
    end
  end
end

./src/layout.html.haml

!!!
%html
  %head
    %title Yay
  %body
    = yield

./src/home.html.haml

= render :layout => 'header' do
  %p This is awesome

Maintenant, il est clair que cela ne fonctionne pas parce que la méthode render n'est pas définie dans le contexte de Rails, mais j'espère que cela montre bien ce que j'essaie de faire.

Des suggestions ?

61voto

matt Points 33799

Vous mélangez deux fonctionnalités distinctes de Rails : partiels (en utilisant render ) y les mises en page (en utilisant yield ) .

Vous pouvez ajouter une version sur rails de l'un ou l'autre (ou des deux) d'entre eux à un programme uniquement Haml.

Partiels

Dans une vue de rails, vous pouvez utiliser render :partial_name pour que le fichier _partial_name.html.haml pour qu'il soit rendu à ce moment-là dans la vue qui le contient (en fait, Rails vous permet d'utiliser n'importe quel langage de templating supporté et il trouvera l'extension de nom de fichier correcte à utiliser, mais je m'en tiendrai ici à Haml). En dehors de Rails render n'est pas disponible, mais elle peut être ajoutée assez facilement.

Un simple render trouverait simplement le fichier haml approprié, le rendrait et renverrait la chaîne html à inclure dans le parent :

def render(partial)
  # assuming we want to keep the rails practice of prefixing file names
  # of partials with "_"
  Haml::Engine.new(File.read("_#{partial}.html.haml")).render
end

Le premier argument de Haml::Engine.render est un objet scope, que nous pouvons utiliser pour ajouter des méthodes disponibles dans le template haml. La valeur par défaut est Object.new . Cependant, dans un cas simple comme celui-ci, nous pouvons définir l'élément render dans le niveau supérieur, et elle sera disponible dans la portée du modèle Haml. Nous mettons simplement notre render dans le script avant l'appel à la méthode Haml::Engine.new(...).render et l'appeler comme ceci dans notre modèle :

!!!
%html
  %head
    %title Hello
  %body
    =render :the_partial

Maintenant, le fichier _the_partial.html.haml apparaîtra rendu à l'endroit approprié de la sortie.

Variables locales

Nous pouvons aller plus loin. Rails vous permet de passer un hash de variables locales à un partiel. Haml accepte aussi un hash de variables à passer comme variables locales, comme deuxième argument de la méthode Haml render méthode. Donc si nous étendons notre méthode de rendu pour qu'elle ressemble à :

def render(partial, locals = {})
  Haml::Engine.new(File.read("_#{partial}.html.haml")).render(Object.new, locals)
end

nous pouvons utiliser un partiel qui ressemble à quelque chose comme :

%p You passed in #{foo}

et l'appeler depuis notre modèle avec :

%body
  =render :partial, :foo => "bar"

qui rendra

<body>
  <p>You passed in bar</p>
</body>

Mises en page

Dans Rails, vous pouvez spécifier une mise en page pour vos vues, afin que toutes vos pages puissent partager le même en-tête, zone de menu, etc. Pour ce faire, vous devez spécifier un fichier de mise en page, dans lequel vous appelez les éléments suivants yield pour rendre la vue réelle en question. Les mises en page sont un peu plus délicates à ajouter à haml, mais c'est toujours possible.

Hamls render accepte également un bloc, de sorte qu'une solution simple serait d'effectuer le rendu du fichier de mise en page et de passer un bloc qui effectue le rendu du fichier de vue :

Haml::Engine.new(File.read("layout.html.haml")).render do
  Haml::Engine.new(File.read("view.html.haml")).render
end

Cela donnerait le contenu de layout.html.haml rendu avec le contenu de view.html.haml a rendu l'endroit où se trouve le fichier de mise en page =yield .

contenu_pour

Rails est cependant un peu plus flexible que cela. Il vous permet d'appeler yield plusieurs fois dans votre fichier de mise en page, en nommant une région spécifique dans chaque cas, et pour spécifier le contenu à ajouter à chaque région à l'aide de l'élément content_for dans vos vues. Donc, dans votre fichier de mise en page :

!!!
%html
  %head
    = yield :title
  %body
    =yield

et dans votre vue :

-content_for :title do
  %title Hello
%p
  Here's a paragraph.

La façon dont Rails fonctionne réellement est de rendre d'abord la partie vue, en stockant toutes les différentes sections, puis de rendre la mise en page, en passant un bloc qui fournit le morceau approprié chaque fois que yield est appelé dans la mise en page. Nous pouvons reproduire cela en utilisant une petite classe d'aide qui fournit le code de l'élément content_for et garder la trace des morceaux rendus pour chaque région :

class Regions  
  def initialize
    @regions_hash={}
  end

  def content_for(region, &blk)  
    @regions_hash[region] = capture_haml(&blk)
  end

  def [](region)
    @regions_hash[region]
  end
end

Ici, nous utilisons le capture_haml méthode pour obtenir le rendu de haml sans qu'il aille directement à la sortie. Notez que cela ne capture pas la partie non nommée de la vue.

Nous pouvons maintenant utiliser notre classe d'aide pour rendre le résultat final.

regions = Regions.new
unnamed = Haml::Engine.new(File.read("view_named.html.haml")).render(regions)

output = Haml::Engine.new(File.read("layout_named.html.haml")).render do |region|
  region ? regions[region] : unnamed
end

Maintenant, la variable output contient la sortie finale rendue.

Notez que le code présenté ici ne fournit pas toute la flexibilité incluse dans rails, mais nous espérons qu'il est suffisant pour vous montrer où commencer à personnaliser Haml pour répondre à vos besoins.

4voto

Victor Moroz Points 4689
content = Haml::Engine.new(content_haml).render(
  Object.new, 
  :local_var_1 => ..., 
  :local_var_2 => ...
)

Haml::Engine.new(layout_haml).render(Object.new, :content => content)

layout.haml

!!!
%html
  %head
    %title
  %body
    = content

Vous pouvez également utiliser les variables d'instance de Object.new (remplacer par un objet significatif) dans haml je crois.

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