haskellhaskell-snap-frameworkheist

How to use a single per-request computation in multiple splices with Heist?


Say I have a single Heist template with two custom tags <x/> and <y/>. Each tag is bound to a Heist.Compiled.Splice. Now the template is rendered at each GET request for a specific route. How can I have <x/> be replaced by the first value of a pair, <y/> be replaced by the second value of the same pair, but the IO computation returning the pair be run only once per request (and be run only on that route, not on every route because some won't use the template at all)?


Solution

  • Your question is very similar to the Person example in the compiled splices tutorial. You need to create a parent splice which will perform the shared computation. Call it computeXY. Your template would look like this:

    <computeXY>
      <p>The first value is <x/>.</p>
      <p>The second value is <y/>.</p>
    </computeXY>
    

    The computeXY splice would perform the computation and use the runChildrenWith pattern to make the results of that computation available to its children as <x/> and <y/> tags. However, the runChildrenWith pattern works a bit differently with compiled splices. Here's how it would be implemented using the new API functions that have been added since the tutorial was written:

    import Blaze.ByteString.Builder.Char8 (fromText)
    import Heist.Compiled
    
    runtimeTupleComputation = return ("foo", "bar")
    
    splices = [ ("x", fromText . fst)
              , ("y", fromText . snd)
              ]
    
    computeXYSplice = withPureSplices runChildren splices runtimeTupleComputation