Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>You're mixing up two distinct Rails feature: <a href="http://guides.rubyonrails.org/layouts_and_rendering.html#using-partials" rel="noreferrer">partials (using <code>render</code>)</a> and <a href="http://guides.rubyonrails.org/layouts_and_rendering.html#understanding-yield" rel="noreferrer">layouts (using <code>yield</code>)</a>.</p> <p>You can add a rails-like version of either (or both) of them to a Haml only program.</p> <h2>Partials</h2> <p>In a rails view, you can use <code>render :partial_name</code> to cause the file <code>_partial_name.html.haml</code> to be rendered at that point in the containing view (actually Rails allows you to use any templating language supported and it will find to correct filename extension to use, but I'll stick to just Haml here). Outside of Rails <code>render</code> isn't available, but it can be added fairly easily.</p> <p>A simple <code>render</code> method would just find the appropriate haml file, render it, and return the html string for inclusion in the parent:</p> <pre class="lang-ruby prettyprint-override"><code>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 </code></pre> <p>The first argument to <code>Haml::Engine.render</code> is a scope object, which we can use to add methods available inside the haml template. It defaults to <code>Object.new</code>. In a simple case like this, however, we can define the <code>render</code> method in the top level, and it will be available in the scope of the Haml template. We simply put our <code>render</code> method in the script before the call to <code>Haml::Engine.new(...).render</code>, and call it like this in our template:</p> <pre class="lang-haml prettyprint-override"><code>!!! %html %head %title Hello %body =render :the_partial </code></pre> <p>Now the file <code>_the_partial.html.haml</code> will appear rendered at the appropriate point of the output.</p> <h3>Local variables</h3> <p>We can take this a step further. Rails allows you to pass in a hash of <a href="http://guides.rubyonrails.org/layouts_and_rendering.html#passing-local-variables" rel="noreferrer">local variables</a> to a partial. Haml will also accept a hash of variables to be passed as local variables, as the second argument to the Haml <code>render</code> method. So if we expand our render method to look like:</p> <pre class="lang-ruby prettyprint-override"><code>def render(partial, locals = {}) Haml::Engine.new(File.read("_#{partial}.html.haml")).render(Object.new, locals) end </code></pre> <p>we can use a partial that looks something like:</p> <pre><code>%p You passed in #{foo} </code></pre> <p>and call it from our template with:</p> <pre class="lang-haml prettyprint-override"><code>%body =render :partial, :foo =&gt; "bar" </code></pre> <p>which will render</p> <pre class="lang-html prettyprint-override"><code>&lt;body&gt; &lt;p&gt;You passed in bar&lt;/p&gt; &lt;/body&gt; </code></pre> <h2>Layouts</h2> <p>In Rails, you can specify a layout for your views, so that all your pages can share the same header, menu area etc. This is done by specifying a layout file, within which you call <code>yield</code> to render the actual view in question. Layouts are slightly more tricky to add to haml, but can still be done.</p> <p>Hamls <code>render</code> method also accepts a block, so a simple solution would be to render the layout file, and pass a block that renders the view file:</p> <pre class="lang-ruby prettyprint-override"><code>Haml::Engine.new(File.read("layout.html.haml")).render do Haml::Engine.new(File.read("view.html.haml")).render end </code></pre> <p>This would give the contents of <code>layout.html.haml</code> rendered with the contents of <code>view.html.haml</code> rendered where the layout file contained <code>=yield</code>.</p> <h3>content_for</h3> <p>Rails is a bit more flexible than that though. It allows you to call <code>yield</code> multiple times in your layout file, naming a specific region in each case, and to specify the contents to be added at each region using the <code>content_for</code> method within your views. So in your layout file:</p> <pre><code>!!! %html %head = yield :title %body =yield </code></pre> <p>and in your view:</p> <pre class="lang-ruby prettyprint-override"><code>-content_for :title do %title Hello %p Here's a paragraph. </code></pre> <p>The way Rails actually works is to render the view part first, storing all the different sections, and then rendering the layout, passing a block that provides the appropriate chunk whenever <code>yield</code> is called in the layout. We can replicate this using a little helper class to provide the <code>content_for</code> method and keep track of the rendered chunks for each region:</p> <pre class="lang-ruby prettyprint-override"><code>class Regions def initialize @regions_hash={} end def content_for(region, &amp;blk) @regions_hash[region] = capture_haml(&amp;blk) end def [](region) @regions_hash[region] end end </code></pre> <p>Here we're using the <a href="http://haml.info/docs/yardoc/Haml/Helpers.html#capture_haml-instance_method" rel="noreferrer"><code>capture_haml</code> method</a> to get the rendered haml without it going direct to the output. Note that this doesn't capture the unnamed part of the view.</p> <p>We can now use our helper class to render the final output.</p> <pre class="lang-rb prettyprint-override"><code>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 </code></pre> <p>Now the variable <code>output</code> contains the final rendered output.</p> <p>Note that the code here doesn't provide all the flexibility that's included with rails, but hopefully it's enough to show you where to start customising Haml to meet your needs. </p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload