mirror of
https://github.com/flipstone/orville.git
synced 2024-10-05 16:17:17 +03:00
Adds guide for how to add Orville your application stack
This commit is contained in:
parent
58eee51209
commit
16c6ecad11
1
.gitignore
vendored
1
.gitignore
vendored
@ -34,3 +34,4 @@ orville-docsite/site-builder/_site
|
||||
|
||||
# Ignore directories created by samples
|
||||
orville-docsite/samples/getting-started/orville-getting-started
|
||||
orville-docsite/samples/adding-orville-new-readert/src
|
||||
|
@ -36,7 +36,7 @@
|
||||
|
||||
<h3>How-To Guides</h3>
|
||||
|
||||
<a href="./how-tos/how-to-add-orville-to-your-application-monad.html">How To Add Orville to Your Application Monad (Upcoming)</a>
|
||||
<a href="./how-tos/how-to-add-orville-to-your-application-monad.html">How To Add Orville to Your Application Monad</a>
|
||||
|
||||
<a href="./how-tos/how-to-marshall-a-haskell-record.html">How To Marshall a Haskell Record (Upcoming)</a>
|
||||
|
||||
|
@ -36,7 +36,7 @@
|
||||
|
||||
<h3>How-To Guides</h3>
|
||||
|
||||
<a href="../how-tos/how-to-add-orville-to-your-application-monad.html">How To Add Orville to Your Application Monad (Upcoming)</a>
|
||||
<a href="../how-tos/how-to-add-orville-to-your-application-monad.html">How To Add Orville to Your Application Monad</a>
|
||||
|
||||
<a href="../how-tos/how-to-marshall-a-haskell-record.html">How To Marshall a Haskell Record (Upcoming)</a>
|
||||
|
||||
|
@ -36,7 +36,7 @@
|
||||
|
||||
<h3>How-To Guides</h3>
|
||||
|
||||
<a href="../how-tos/how-to-add-orville-to-your-application-monad.html">How To Add Orville to Your Application Monad (Upcoming)</a>
|
||||
<a href="../how-tos/how-to-add-orville-to-your-application-monad.html">How To Add Orville to Your Application Monad</a>
|
||||
|
||||
<a href="../how-tos/how-to-marshall-a-haskell-record.html">How To Marshall a Haskell Record (Upcoming)</a>
|
||||
|
||||
|
@ -36,7 +36,7 @@
|
||||
|
||||
<h3>How-To Guides</h3>
|
||||
|
||||
<a href="../how-tos/how-to-add-orville-to-your-application-monad.html">How To Add Orville to Your Application Monad (Upcoming)</a>
|
||||
<a href="../how-tos/how-to-add-orville-to-your-application-monad.html">How To Add Orville to Your Application Monad</a>
|
||||
|
||||
<a href="../how-tos/how-to-marshall-a-haskell-record.html">How To Marshall a Haskell Record (Upcoming)</a>
|
||||
|
||||
|
@ -36,7 +36,7 @@
|
||||
|
||||
<h3>How-To Guides</h3>
|
||||
|
||||
<a href="../how-tos/how-to-add-orville-to-your-application-monad.html">How To Add Orville to Your Application Monad (Upcoming)</a>
|
||||
<a href="../how-tos/how-to-add-orville-to-your-application-monad.html">How To Add Orville to Your Application Monad</a>
|
||||
|
||||
<a href="../how-tos/how-to-marshall-a-haskell-record.html">How To Marshall a Haskell Record (Upcoming)</a>
|
||||
|
||||
|
@ -4,7 +4,7 @@
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="x-ua-compatible" content="ie=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>Orville - How To Add Orville to Your Application Monad (Upcoming)</title>
|
||||
<title>Orville - How To Add Orville to Your Application Monad</title>
|
||||
<link rel="stylesheet" href="../css/syntax.css" />
|
||||
<link rel="stylesheet" href="../css/default.css" />
|
||||
</head>
|
||||
@ -36,7 +36,7 @@
|
||||
|
||||
<h3>How-To Guides</h3>
|
||||
|
||||
<a href="../how-tos/how-to-add-orville-to-your-application-monad.html">How To Add Orville to Your Application Monad (Upcoming)</a>
|
||||
<a href="../how-tos/how-to-add-orville-to-your-application-monad.html">How To Add Orville to Your Application Monad</a>
|
||||
|
||||
<a href="../how-tos/how-to-marshall-a-haskell-record.html">How To Marshall a Haskell Record (Upcoming)</a>
|
||||
|
||||
@ -72,10 +72,290 @@
|
||||
</section>
|
||||
|
||||
<main role="main">
|
||||
<h1>How To Add Orville to Your Application Monad (Upcoming)</h1>
|
||||
<h1>How To Add Orville to Your Application Monad</h1>
|
||||
<article>
|
||||
<section>
|
||||
<p>Coming Soon</p>
|
||||
<p>This guide will show you how to add Orville to your already existing
|
||||
application monad in the simplest way possible. It relies on the <code>mtl</code> package
|
||||
in addition to <code>orville-postgresql</code>, so you should make sure these packages are
|
||||
in your package dependencies in either your <code>.cabal</code> or <code>package.yaml</code> file.</p>
|
||||
<p>The file listing below shows a simple, minimal application with its own
|
||||
<code>Application</code> monad. Your application is certainly more complicated than this,
|
||||
but you can think of the <code>IO</code> type below being whatever base monad or monad
|
||||
transformer stack you already have in place.</p>
|
||||
<div class="codeblock-label">
|
||||
Main.hs (Before) : haskell
|
||||
</div>
|
||||
<div class="sourceCode" id="cb1"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="ot">{-# LANGUAGE GeneralizedNewtypeDeriving #-}</span></span>
|
||||
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a><span class="kw">module</span> <span class="dt">Main</span></span>
|
||||
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a> ( main</span>
|
||||
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a> ) <span class="kw">where</span></span>
|
||||
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a></span>
|
||||
<span id="cb1-6"><a href="#cb1-6" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="kw">qualified</span> <span class="dt">Control.Monad.IO.Class</span> <span class="kw">as</span> <span class="dt">MIO</span></span>
|
||||
<span id="cb1-7"><a href="#cb1-7" aria-hidden="true" tabindex="-1"></a></span>
|
||||
<span id="cb1-8"><a href="#cb1-8" aria-hidden="true" tabindex="-1"></a><span class="kw">newtype</span> <span class="dt">Application</span> a <span class="ot">=</span></span>
|
||||
<span id="cb1-9"><a href="#cb1-9" aria-hidden="true" tabindex="-1"></a> <span class="dt">Application</span> (<span class="dt">IO</span> a)</span>
|
||||
<span id="cb1-10"><a href="#cb1-10" aria-hidden="true" tabindex="-1"></a> <span class="kw">deriving</span></span>
|
||||
<span id="cb1-11"><a href="#cb1-11" aria-hidden="true" tabindex="-1"></a> ( <span class="dt">Functor</span></span>
|
||||
<span id="cb1-12"><a href="#cb1-12" aria-hidden="true" tabindex="-1"></a> , <span class="dt">Applicative</span></span>
|
||||
<span id="cb1-13"><a href="#cb1-13" aria-hidden="true" tabindex="-1"></a> , <span class="dt">Monad</span></span>
|
||||
<span id="cb1-14"><a href="#cb1-14" aria-hidden="true" tabindex="-1"></a> , <span class="dt">MIO.MonadIO</span></span>
|
||||
<span id="cb1-15"><a href="#cb1-15" aria-hidden="true" tabindex="-1"></a> )</span>
|
||||
<span id="cb1-16"><a href="#cb1-16" aria-hidden="true" tabindex="-1"></a></span>
|
||||
<span id="cb1-17"><a href="#cb1-17" aria-hidden="true" tabindex="-1"></a><span class="ot">runApplication ::</span> <span class="dt">Application</span> a <span class="ot">-></span> <span class="dt">IO</span> a</span>
|
||||
<span id="cb1-18"><a href="#cb1-18" aria-hidden="true" tabindex="-1"></a>runApplication (<span class="dt">Application</span> io) <span class="ot">=</span></span>
|
||||
<span id="cb1-19"><a href="#cb1-19" aria-hidden="true" tabindex="-1"></a> io</span>
|
||||
<span id="cb1-20"><a href="#cb1-20" aria-hidden="true" tabindex="-1"></a></span>
|
||||
<span id="cb1-21"><a href="#cb1-21" aria-hidden="true" tabindex="-1"></a><span class="ot">myApplication ::</span> <span class="dt">Application</span> ()</span>
|
||||
<span id="cb1-22"><a href="#cb1-22" aria-hidden="true" tabindex="-1"></a>myApplication <span class="ot">=</span></span>
|
||||
<span id="cb1-23"><a href="#cb1-23" aria-hidden="true" tabindex="-1"></a> MIO.liftIO <span class="op">.</span> <span class="fu">putStrLn</span> <span class="op">$</span> <span class="st">"Hello Application"</span></span>
|
||||
<span id="cb1-24"><a href="#cb1-24" aria-hidden="true" tabindex="-1"></a></span>
|
||||
<span id="cb1-25"><a href="#cb1-25" aria-hidden="true" tabindex="-1"></a><span class="ot">main ::</span> <span class="dt">IO</span> ()</span>
|
||||
<span id="cb1-26"><a href="#cb1-26" aria-hidden="true" tabindex="-1"></a>main <span class="ot">=</span></span>
|
||||
<span id="cb1-27"><a href="#cb1-27" aria-hidden="true" tabindex="-1"></a> runApplication myApplication</span></code></pre></div>
|
||||
<p>We’re going to add a new <code>ReaderT</code> transformer to the innards of the
|
||||
<code>Application</code> newtype to hold Orville’s <code>OrvilleState</code> parameter. We’ll have to
|
||||
import the <code>Control.Monad.Reader</code> module (from the <code>mtl</code> package) and the
|
||||
<code>Orville.PostgreSQL</code> module (from the <code>orville-postgresql</code>) package to
|
||||
reference these types.</p>
|
||||
<div class="codeblock-label">
|
||||
Main.hs : diff
|
||||
</div>
|
||||
<div class="sourceCode" id="cb2"><pre class="sourceCode diff"><code class="sourceCode diff"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="kw">*** Main.hs (Old)</span></span>
|
||||
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a><span class="kw">--- Main.hs (New)</span></span>
|
||||
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a><span class="dt">***************</span></span>
|
||||
<span id="cb2-4"><a href="#cb2-4" aria-hidden="true" tabindex="-1"></a><span class="dt">*** 5,10 ****</span></span>
|
||||
<span id="cb2-5"><a href="#cb2-5" aria-hidden="true" tabindex="-1"></a> </span>
|
||||
<span id="cb2-6"><a href="#cb2-6" aria-hidden="true" tabindex="-1"></a> import qualified Control.Monad.IO.Class as MIO</span>
|
||||
<span id="cb2-7"><a href="#cb2-7" aria-hidden="true" tabindex="-1"></a> </span>
|
||||
<span id="cb2-8"><a href="#cb2-8" aria-hidden="true" tabindex="-1"></a> newtype Application a =</span>
|
||||
<span id="cb2-9"><a href="#cb2-9" aria-hidden="true" tabindex="-1"></a><span class="st">! Application (IO a)</span></span>
|
||||
<span id="cb2-10"><a href="#cb2-10" aria-hidden="true" tabindex="-1"></a> deriving</span>
|
||||
<span id="cb2-11"><a href="#cb2-11" aria-hidden="true" tabindex="-1"></a><span class="dt">--- 5,12 ----</span></span>
|
||||
<span id="cb2-12"><a href="#cb2-12" aria-hidden="true" tabindex="-1"></a> </span>
|
||||
<span id="cb2-13"><a href="#cb2-13" aria-hidden="true" tabindex="-1"></a><span class="va">+ import qualified Control.Monad.Reader as Reader</span></span>
|
||||
<span id="cb2-14"><a href="#cb2-14" aria-hidden="true" tabindex="-1"></a> import qualified Control.Monad.IO.Class as MIO</span>
|
||||
<span id="cb2-15"><a href="#cb2-15" aria-hidden="true" tabindex="-1"></a><span class="va">+ import qualified Orville.PostgreSQL as O</span></span>
|
||||
<span id="cb2-16"><a href="#cb2-16" aria-hidden="true" tabindex="-1"></a> </span>
|
||||
<span id="cb2-17"><a href="#cb2-17" aria-hidden="true" tabindex="-1"></a> newtype Application a =</span>
|
||||
<span id="cb2-18"><a href="#cb2-18" aria-hidden="true" tabindex="-1"></a><span class="va">! Application (Reader.ReaderT O.OrvilleState IO a)</span></span>
|
||||
<span id="cb2-19"><a href="#cb2-19" aria-hidden="true" tabindex="-1"></a> deriving</span></code></pre></div>
|
||||
<p>This new <code>ReaderT</code> context adds the internal state that Orville needs to do its
|
||||
job. In order to use functions from the Orville package directly in your monad
|
||||
it will need to provide instances for the three typeclasses that make up a
|
||||
complete Orville monad - <code>MonadOrville</code>, <code>MonadOrvilleControl</code> and
|
||||
<code>HasOrvilleState</code>. Luckily, it’s a simple matter of adding these three
|
||||
typeclasses the the deriving list for <code>Application</code>. If you’re not using
|
||||
<code>GHC2021</code> you’ll need the <code>GeneralizedNewtypeDeriving</code> language extension, as
|
||||
in the example in this guide.</p>
|
||||
<div class="codeblock-label">
|
||||
Main.hs : diff
|
||||
</div>
|
||||
<div class="sourceCode" id="cb3"><pre class="sourceCode diff"><code class="sourceCode diff"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a><span class="kw">*** Main.hs (Old)</span></span>
|
||||
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a><span class="kw">--- Main.hs (New)</span></span>
|
||||
<span id="cb3-3"><a href="#cb3-3" aria-hidden="true" tabindex="-1"></a><span class="dt">***************</span></span>
|
||||
<span id="cb3-4"><a href="#cb3-4" aria-hidden="true" tabindex="-1"></a><span class="dt">*** 16,17 ****</span></span>
|
||||
<span id="cb3-5"><a href="#cb3-5" aria-hidden="true" tabindex="-1"></a><span class="dt">--- 16,20 ----</span></span>
|
||||
<span id="cb3-6"><a href="#cb3-6" aria-hidden="true" tabindex="-1"></a> , MIO.MonadIO</span>
|
||||
<span id="cb3-7"><a href="#cb3-7" aria-hidden="true" tabindex="-1"></a><span class="va">+ , O.MonadOrville</span></span>
|
||||
<span id="cb3-8"><a href="#cb3-8" aria-hidden="true" tabindex="-1"></a><span class="va">+ , O.MonadOrvilleControl</span></span>
|
||||
<span id="cb3-9"><a href="#cb3-9" aria-hidden="true" tabindex="-1"></a><span class="va">+ , O.HasOrvilleState</span></span>
|
||||
<span id="cb3-10"><a href="#cb3-10" aria-hidden="true" tabindex="-1"></a> )</span></code></pre></div>
|
||||
<p>Somewhere in your code you’ll have a function similar to this example’s
|
||||
<code>runApplication</code> function. It needs to be updated to expect a <code>ConnectionPool</code>
|
||||
argument. We’ll use the connection pool to build a fresh new <code>OrvilleState</code> for
|
||||
our <code>Reader</code> context. Then we can use <code>runReaderT</code> resolve the <code>ReaderT</code> layer
|
||||
we added to our stack and get back whatever monad type was there before we
|
||||
added Orville. In this case that’s just the <code>IO</code> type. This means
|
||||
<code>runApplication</code> will return the same type that it returned befored we added
|
||||
Orville, it just requires the <code>ConnectionPool</code> parameter to do its job now.</p>
|
||||
<div class="codeblock-label">
|
||||
Main.hs : diff
|
||||
</div>
|
||||
<div class="sourceCode" id="cb4"><pre class="sourceCode diff"><code class="sourceCode diff"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a><span class="kw">*** Main.hs (Old)</span></span>
|
||||
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a><span class="kw">--- Main.hs (New)</span></span>
|
||||
<span id="cb4-3"><a href="#cb4-3" aria-hidden="true" tabindex="-1"></a><span class="dt">***************</span></span>
|
||||
<span id="cb4-4"><a href="#cb4-4" aria-hidden="true" tabindex="-1"></a><span class="dt">*** 21,25 ****</span></span>
|
||||
<span id="cb4-5"><a href="#cb4-5" aria-hidden="true" tabindex="-1"></a> </span>
|
||||
<span id="cb4-6"><a href="#cb4-6" aria-hidden="true" tabindex="-1"></a><span class="st">! runApplication :: Application a -> IO a</span></span>
|
||||
<span id="cb4-7"><a href="#cb4-7" aria-hidden="true" tabindex="-1"></a><span class="st">! runApplication (Application io) =</span></span>
|
||||
<span id="cb4-8"><a href="#cb4-8" aria-hidden="true" tabindex="-1"></a><span class="st">! io</span></span>
|
||||
<span id="cb4-9"><a href="#cb4-9" aria-hidden="true" tabindex="-1"></a> </span>
|
||||
<span id="cb4-10"><a href="#cb4-10" aria-hidden="true" tabindex="-1"></a><span class="dt">--- 21,31 ----</span></span>
|
||||
<span id="cb4-11"><a href="#cb4-11" aria-hidden="true" tabindex="-1"></a> </span>
|
||||
<span id="cb4-12"><a href="#cb4-12" aria-hidden="true" tabindex="-1"></a><span class="va">! runApplication :: O.ConnectionPool -> Application a -> IO a</span></span>
|
||||
<span id="cb4-13"><a href="#cb4-13" aria-hidden="true" tabindex="-1"></a><span class="va">! runApplication pool (Application reader) =</span></span>
|
||||
<span id="cb4-14"><a href="#cb4-14" aria-hidden="true" tabindex="-1"></a><span class="va">! let</span></span>
|
||||
<span id="cb4-15"><a href="#cb4-15" aria-hidden="true" tabindex="-1"></a><span class="va">! orvilleState =</span></span>
|
||||
<span id="cb4-16"><a href="#cb4-16" aria-hidden="true" tabindex="-1"></a><span class="va">! O.newOrvilleState</span></span>
|
||||
<span id="cb4-17"><a href="#cb4-17" aria-hidden="true" tabindex="-1"></a><span class="va">! O.defaultErrorDetailLevel</span></span>
|
||||
<span id="cb4-18"><a href="#cb4-18" aria-hidden="true" tabindex="-1"></a><span class="va">! pool</span></span>
|
||||
<span id="cb4-19"><a href="#cb4-19" aria-hidden="true" tabindex="-1"></a><span class="va">! in</span></span>
|
||||
<span id="cb4-20"><a href="#cb4-20" aria-hidden="true" tabindex="-1"></a><span class="va">! Reader.runReaderT reader orvilleState</span></span>
|
||||
<span id="cb4-21"><a href="#cb4-21" aria-hidden="true" tabindex="-1"></a> </span></code></pre></div>
|
||||
<p>Since we added a parameter to <code>runApplication</code>, we need to go to each place
|
||||
it’s called and pass a <code>ConnectionPool</code> parameter now. In this guide that’s
|
||||
just a single place in the <code>main</code> function. We’ll use <code>createConnectionPool</code> as
|
||||
normal to make the pool we want to use.</p>
|
||||
<div class="codeblock-label">
|
||||
Main.hs : diff
|
||||
</div>
|
||||
<div class="sourceCode" id="cb5"><pre class="sourceCode diff"><code class="sourceCode diff"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a><span class="kw">*** Main.hs (Old)</span></span>
|
||||
<span id="cb5-2"><a href="#cb5-2" aria-hidden="true" tabindex="-1"></a><span class="kw">--- Main.hs (New)</span></span>
|
||||
<span id="cb5-3"><a href="#cb5-3" aria-hidden="true" tabindex="-1"></a><span class="dt">***************</span></span>
|
||||
<span id="cb5-4"><a href="#cb5-4" aria-hidden="true" tabindex="-1"></a><span class="dt">*** 36,38 ****</span></span>
|
||||
<span id="cb5-5"><a href="#cb5-5" aria-hidden="true" tabindex="-1"></a> main :: IO ()</span>
|
||||
<span id="cb5-6"><a href="#cb5-6" aria-hidden="true" tabindex="-1"></a><span class="st">! main =</span></span>
|
||||
<span id="cb5-7"><a href="#cb5-7" aria-hidden="true" tabindex="-1"></a><span class="st">! runApplication myApplication</span></span>
|
||||
<span id="cb5-8"><a href="#cb5-8" aria-hidden="true" tabindex="-1"></a><span class="dt">--- 36,48 ----</span></span>
|
||||
<span id="cb5-9"><a href="#cb5-9" aria-hidden="true" tabindex="-1"></a> main :: IO ()</span>
|
||||
<span id="cb5-10"><a href="#cb5-10" aria-hidden="true" tabindex="-1"></a><span class="va">! main = do</span></span>
|
||||
<span id="cb5-11"><a href="#cb5-11" aria-hidden="true" tabindex="-1"></a><span class="va">! pool <-</span></span>
|
||||
<span id="cb5-12"><a href="#cb5-12" aria-hidden="true" tabindex="-1"></a><span class="va">! O.createConnectionPool</span></span>
|
||||
<span id="cb5-13"><a href="#cb5-13" aria-hidden="true" tabindex="-1"></a><span class="va">! O.ConnectionOptions</span></span>
|
||||
<span id="cb5-14"><a href="#cb5-14" aria-hidden="true" tabindex="-1"></a><span class="va">! { O.connectionString = "host=localhost user=postgres password=postgres"</span></span>
|
||||
<span id="cb5-15"><a href="#cb5-15" aria-hidden="true" tabindex="-1"></a><span class="va">! , O.connectionNoticeReporting = O.DisableNoticeReporting</span></span>
|
||||
<span id="cb5-16"><a href="#cb5-16" aria-hidden="true" tabindex="-1"></a><span class="va">! , O.connectionPoolStripes = O.OneStripePerCapability</span></span>
|
||||
<span id="cb5-17"><a href="#cb5-17" aria-hidden="true" tabindex="-1"></a><span class="va">! , O.connectionPoolLingerTime = 10</span></span>
|
||||
<span id="cb5-18"><a href="#cb5-18" aria-hidden="true" tabindex="-1"></a><span class="va">! , O.connectionPoolMaxConnections = O.MaxConnectionsPerStripe 1</span></span>
|
||||
<span id="cb5-19"><a href="#cb5-19" aria-hidden="true" tabindex="-1"></a><span class="va">! }</span></span>
|
||||
<span id="cb5-20"><a href="#cb5-20" aria-hidden="true" tabindex="-1"></a><span class="va">! </span></span>
|
||||
<span id="cb5-21"><a href="#cb5-21" aria-hidden="true" tabindex="-1"></a><span class="va">! runApplication pool myApplication</span></span></code></pre></div>
|
||||
<p>Our <code>Application</code> monad is now fully equipped to run Orville operations! To
|
||||
show it works, let’s add a <code>messages</code> table and update the <code>myApplication</code>
|
||||
logic to insert and retrieve a simple greeting message.</p>
|
||||
<div class="codeblock-label">
|
||||
Main.hs : diff
|
||||
</div>
|
||||
<div class="sourceCode" id="cb6"><pre class="sourceCode diff"><code class="sourceCode diff"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true" tabindex="-1"></a><span class="kw">*** Main.hs (Old)</span></span>
|
||||
<span id="cb6-2"><a href="#cb6-2" aria-hidden="true" tabindex="-1"></a><span class="kw">--- Main.hs (New)</span></span>
|
||||
<span id="cb6-3"><a href="#cb6-3" aria-hidden="true" tabindex="-1"></a><span class="dt">***************</span></span>
|
||||
<span id="cb6-4"><a href="#cb6-4" aria-hidden="true" tabindex="-1"></a><span class="dt">*** 7,8 ****</span></span>
|
||||
<span id="cb6-5"><a href="#cb6-5" aria-hidden="true" tabindex="-1"></a><span class="dt">--- 7,9 ----</span></span>
|
||||
<span id="cb6-6"><a href="#cb6-6" aria-hidden="true" tabindex="-1"></a> import qualified Control.Monad.IO.Class as MIO</span>
|
||||
<span id="cb6-7"><a href="#cb6-7" aria-hidden="true" tabindex="-1"></a><span class="va">+ import qualified Data.Text as T</span></span>
|
||||
<span id="cb6-8"><a href="#cb6-8" aria-hidden="true" tabindex="-1"></a> import qualified Orville.PostgreSQL as O</span>
|
||||
<span id="cb6-9"><a href="#cb6-9" aria-hidden="true" tabindex="-1"></a><span class="dt">***************</span></span>
|
||||
<span id="cb6-10"><a href="#cb6-10" aria-hidden="true" tabindex="-1"></a><span class="dt">*** 31,35 ****</span></span>
|
||||
<span id="cb6-11"><a href="#cb6-11" aria-hidden="true" tabindex="-1"></a> </span>
|
||||
<span id="cb6-12"><a href="#cb6-12" aria-hidden="true" tabindex="-1"></a> myApplication :: Application ()</span>
|
||||
<span id="cb6-13"><a href="#cb6-13" aria-hidden="true" tabindex="-1"></a><span class="st">! myApplication =</span></span>
|
||||
<span id="cb6-14"><a href="#cb6-14" aria-hidden="true" tabindex="-1"></a><span class="st">! MIO.liftIO . putStrLn $ "Hello Application"</span></span>
|
||||
<span id="cb6-15"><a href="#cb6-15" aria-hidden="true" tabindex="-1"></a> </span>
|
||||
<span id="cb6-16"><a href="#cb6-16" aria-hidden="true" tabindex="-1"></a><span class="dt">--- 32,44 ----</span></span>
|
||||
<span id="cb6-17"><a href="#cb6-17" aria-hidden="true" tabindex="-1"></a> </span>
|
||||
<span id="cb6-18"><a href="#cb6-18" aria-hidden="true" tabindex="-1"></a><span class="va">+ messagesTable :: O.TableDefinition O.NoKey T.Text T.Text</span></span>
|
||||
<span id="cb6-19"><a href="#cb6-19" aria-hidden="true" tabindex="-1"></a><span class="va">+ messagesTable =</span></span>
|
||||
<span id="cb6-20"><a href="#cb6-20" aria-hidden="true" tabindex="-1"></a><span class="va">+ O.mkTableDefinitionWithoutKey</span></span>
|
||||
<span id="cb6-21"><a href="#cb6-21" aria-hidden="true" tabindex="-1"></a><span class="va">+ "messages"</span></span>
|
||||
<span id="cb6-22"><a href="#cb6-22" aria-hidden="true" tabindex="-1"></a><span class="va">+ (O.marshallField id (O.unboundedTextField "message"))</span></span>
|
||||
<span id="cb6-23"><a href="#cb6-23" aria-hidden="true" tabindex="-1"></a><span class="va">+ </span></span>
|
||||
<span id="cb6-24"><a href="#cb6-24" aria-hidden="true" tabindex="-1"></a> myApplication :: Application ()</span>
|
||||
<span id="cb6-25"><a href="#cb6-25" aria-hidden="true" tabindex="-1"></a><span class="va">! myApplication = do</span></span>
|
||||
<span id="cb6-26"><a href="#cb6-26" aria-hidden="true" tabindex="-1"></a><span class="va">! O.insertEntity messagesTable (T.pack "Hello Orville")</span></span>
|
||||
<span id="cb6-27"><a href="#cb6-27" aria-hidden="true" tabindex="-1"></a><span class="va">! messages <- O.findEntitiesBy messagesTable mempty</span></span>
|
||||
<span id="cb6-28"><a href="#cb6-28" aria-hidden="true" tabindex="-1"></a><span class="va">! MIO.liftIO . print $ messages</span></span>
|
||||
<span id="cb6-29"><a href="#cb6-29" aria-hidden="true" tabindex="-1"></a> </span></code></pre></div>
|
||||
<p>Finally, we’ll equip our application with automatic migrations using Orville’s
|
||||
<code>Orville.PostgreSQL.Automigration</code> module so that the <code>messages</code> table will be
|
||||
created before we try to access it.</p>
|
||||
<div class="codeblock-label">
|
||||
Main.hs : diff
|
||||
</div>
|
||||
<div class="sourceCode" id="cb7"><pre class="sourceCode diff"><code class="sourceCode diff"><span id="cb7-1"><a href="#cb7-1" aria-hidden="true" tabindex="-1"></a><span class="kw">*** Main.hs (Old)</span></span>
|
||||
<span id="cb7-2"><a href="#cb7-2" aria-hidden="true" tabindex="-1"></a><span class="kw">--- Main.hs (New)</span></span>
|
||||
<span id="cb7-3"><a href="#cb7-3" aria-hidden="true" tabindex="-1"></a><span class="dt">***************</span></span>
|
||||
<span id="cb7-4"><a href="#cb7-4" aria-hidden="true" tabindex="-1"></a><span class="dt">*** 9,10 ****</span></span>
|
||||
<span id="cb7-5"><a href="#cb7-5" aria-hidden="true" tabindex="-1"></a><span class="dt">--- 9,11 ----</span></span>
|
||||
<span id="cb7-6"><a href="#cb7-6" aria-hidden="true" tabindex="-1"></a> import qualified Orville.PostgreSQL as O</span>
|
||||
<span id="cb7-7"><a href="#cb7-7" aria-hidden="true" tabindex="-1"></a><span class="va">+ import qualified Orville.PostgreSQL.AutoMigration as AutoMigration</span></span>
|
||||
<span id="cb7-8"><a href="#cb7-8" aria-hidden="true" tabindex="-1"></a> </span>
|
||||
<span id="cb7-9"><a href="#cb7-9" aria-hidden="true" tabindex="-1"></a><span class="dt">***************</span></span>
|
||||
<span id="cb7-10"><a href="#cb7-10" aria-hidden="true" tabindex="-1"></a><span class="dt">*** 44,45 ****</span></span>
|
||||
<span id="cb7-11"><a href="#cb7-11" aria-hidden="true" tabindex="-1"></a><span class="dt">--- 45,51 ----</span></span>
|
||||
<span id="cb7-12"><a href="#cb7-12" aria-hidden="true" tabindex="-1"></a> </span>
|
||||
<span id="cb7-13"><a href="#cb7-13" aria-hidden="true" tabindex="-1"></a><span class="va">+ schema :: [AutoMigration.SchemaItem]</span></span>
|
||||
<span id="cb7-14"><a href="#cb7-14" aria-hidden="true" tabindex="-1"></a><span class="va">+ schema =</span></span>
|
||||
<span id="cb7-15"><a href="#cb7-15" aria-hidden="true" tabindex="-1"></a><span class="va">+ [ AutoMigration.SchemaTable messagesTable</span></span>
|
||||
<span id="cb7-16"><a href="#cb7-16" aria-hidden="true" tabindex="-1"></a><span class="va">+ ]</span></span>
|
||||
<span id="cb7-17"><a href="#cb7-17" aria-hidden="true" tabindex="-1"></a><span class="va">+ </span></span>
|
||||
<span id="cb7-18"><a href="#cb7-18" aria-hidden="true" tabindex="-1"></a> main :: IO ()</span>
|
||||
<span id="cb7-19"><a href="#cb7-19" aria-hidden="true" tabindex="-1"></a><span class="dt">***************</span></span>
|
||||
<span id="cb7-20"><a href="#cb7-20" aria-hidden="true" tabindex="-1"></a><span class="dt">*** 56,57 ****</span></span>
|
||||
<span id="cb7-21"><a href="#cb7-21" aria-hidden="true" tabindex="-1"></a><span class="dt">--- 62,64 ----</span></span>
|
||||
<span id="cb7-22"><a href="#cb7-22" aria-hidden="true" tabindex="-1"></a> </span>
|
||||
<span id="cb7-23"><a href="#cb7-23" aria-hidden="true" tabindex="-1"></a><span class="va">+ runApplication pool (AutoMigration.autoMigrateSchema AutoMigration.defaultOptions schema)</span></span>
|
||||
<span id="cb7-24"><a href="#cb7-24" aria-hidden="true" tabindex="-1"></a> runApplication pool myApplication</span></code></pre></div>
|
||||
<p>That’s it! That completes this guide about how to add Orville to your existing
|
||||
application monad. To wrap things up, here’s the final listing of <code>Main.hs</code>
|
||||
with all the changes we made.</p>
|
||||
<div class="codeblock-label">
|
||||
Main.hs (After) : haskell
|
||||
</div>
|
||||
<div class="sourceCode" id="cb8"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb8-1"><a href="#cb8-1" aria-hidden="true" tabindex="-1"></a><span class="ot">{-# LANGUAGE GeneralizedNewtypeDeriving #-}</span></span>
|
||||
<span id="cb8-2"><a href="#cb8-2" aria-hidden="true" tabindex="-1"></a><span class="kw">module</span> <span class="dt">Main</span></span>
|
||||
<span id="cb8-3"><a href="#cb8-3" aria-hidden="true" tabindex="-1"></a> ( main</span>
|
||||
<span id="cb8-4"><a href="#cb8-4" aria-hidden="true" tabindex="-1"></a> ) <span class="kw">where</span></span>
|
||||
<span id="cb8-5"><a href="#cb8-5" aria-hidden="true" tabindex="-1"></a></span>
|
||||
<span id="cb8-6"><a href="#cb8-6" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="kw">qualified</span> <span class="dt">Control.Monad.Reader</span> <span class="kw">as</span> <span class="dt">Reader</span></span>
|
||||
<span id="cb8-7"><a href="#cb8-7" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="kw">qualified</span> <span class="dt">Control.Monad.IO.Class</span> <span class="kw">as</span> <span class="dt">MIO</span></span>
|
||||
<span id="cb8-8"><a href="#cb8-8" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="kw">qualified</span> <span class="dt">Data.Text</span> <span class="kw">as</span> <span class="dt">T</span></span>
|
||||
<span id="cb8-9"><a href="#cb8-9" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="kw">qualified</span> <span class="dt">Orville.PostgreSQL</span> <span class="kw">as</span> <span class="dt">O</span></span>
|
||||
<span id="cb8-10"><a href="#cb8-10" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="kw">qualified</span> <span class="dt">Orville.PostgreSQL.AutoMigration</span> <span class="kw">as</span> <span class="dt">AutoMigration</span></span>
|
||||
<span id="cb8-11"><a href="#cb8-11" aria-hidden="true" tabindex="-1"></a></span>
|
||||
<span id="cb8-12"><a href="#cb8-12" aria-hidden="true" tabindex="-1"></a><span class="kw">newtype</span> <span class="dt">Application</span> a <span class="ot">=</span></span>
|
||||
<span id="cb8-13"><a href="#cb8-13" aria-hidden="true" tabindex="-1"></a> <span class="dt">Application</span> (<span class="dt">Reader.ReaderT</span> <span class="dt">O.OrvilleState</span> <span class="dt">IO</span> a)</span>
|
||||
<span id="cb8-14"><a href="#cb8-14" aria-hidden="true" tabindex="-1"></a> <span class="kw">deriving</span></span>
|
||||
<span id="cb8-15"><a href="#cb8-15" aria-hidden="true" tabindex="-1"></a> ( <span class="dt">Functor</span></span>
|
||||
<span id="cb8-16"><a href="#cb8-16" aria-hidden="true" tabindex="-1"></a> , <span class="dt">Applicative</span></span>
|
||||
<span id="cb8-17"><a href="#cb8-17" aria-hidden="true" tabindex="-1"></a> , <span class="dt">Monad</span></span>
|
||||
<span id="cb8-18"><a href="#cb8-18" aria-hidden="true" tabindex="-1"></a> , <span class="dt">MIO.MonadIO</span></span>
|
||||
<span id="cb8-19"><a href="#cb8-19" aria-hidden="true" tabindex="-1"></a> , <span class="dt">O.MonadOrville</span></span>
|
||||
<span id="cb8-20"><a href="#cb8-20" aria-hidden="true" tabindex="-1"></a> , <span class="dt">O.MonadOrvilleControl</span></span>
|
||||
<span id="cb8-21"><a href="#cb8-21" aria-hidden="true" tabindex="-1"></a> , <span class="dt">O.HasOrvilleState</span></span>
|
||||
<span id="cb8-22"><a href="#cb8-22" aria-hidden="true" tabindex="-1"></a> )</span>
|
||||
<span id="cb8-23"><a href="#cb8-23" aria-hidden="true" tabindex="-1"></a></span>
|
||||
<span id="cb8-24"><a href="#cb8-24" aria-hidden="true" tabindex="-1"></a><span class="ot">runApplication ::</span> <span class="dt">O.ConnectionPool</span> <span class="ot">-></span> <span class="dt">Application</span> a <span class="ot">-></span> <span class="dt">IO</span> a</span>
|
||||
<span id="cb8-25"><a href="#cb8-25" aria-hidden="true" tabindex="-1"></a>runApplication pool (<span class="dt">Application</span> reader) <span class="ot">=</span></span>
|
||||
<span id="cb8-26"><a href="#cb8-26" aria-hidden="true" tabindex="-1"></a> <span class="kw">let</span></span>
|
||||
<span id="cb8-27"><a href="#cb8-27" aria-hidden="true" tabindex="-1"></a> orvilleState <span class="ot">=</span></span>
|
||||
<span id="cb8-28"><a href="#cb8-28" aria-hidden="true" tabindex="-1"></a> O.newOrvilleState</span>
|
||||
<span id="cb8-29"><a href="#cb8-29" aria-hidden="true" tabindex="-1"></a> O.defaultErrorDetailLevel</span>
|
||||
<span id="cb8-30"><a href="#cb8-30" aria-hidden="true" tabindex="-1"></a> pool</span>
|
||||
<span id="cb8-31"><a href="#cb8-31" aria-hidden="true" tabindex="-1"></a> <span class="kw">in</span></span>
|
||||
<span id="cb8-32"><a href="#cb8-32" aria-hidden="true" tabindex="-1"></a> Reader.runReaderT reader orvilleState</span>
|
||||
<span id="cb8-33"><a href="#cb8-33" aria-hidden="true" tabindex="-1"></a></span>
|
||||
<span id="cb8-34"><a href="#cb8-34" aria-hidden="true" tabindex="-1"></a><span class="ot">messagesTable ::</span> <span class="dt">O.TableDefinition</span> <span class="dt">O.NoKey</span> <span class="dt">T.Text</span> <span class="dt">T.Text</span></span>
|
||||
<span id="cb8-35"><a href="#cb8-35" aria-hidden="true" tabindex="-1"></a>messagesTable <span class="ot">=</span></span>
|
||||
<span id="cb8-36"><a href="#cb8-36" aria-hidden="true" tabindex="-1"></a> O.mkTableDefinitionWithoutKey</span>
|
||||
<span id="cb8-37"><a href="#cb8-37" aria-hidden="true" tabindex="-1"></a> <span class="st">"messages"</span></span>
|
||||
<span id="cb8-38"><a href="#cb8-38" aria-hidden="true" tabindex="-1"></a> (O.marshallField <span class="fu">id</span> (O.unboundedTextField <span class="st">"message"</span>))</span>
|
||||
<span id="cb8-39"><a href="#cb8-39" aria-hidden="true" tabindex="-1"></a></span>
|
||||
<span id="cb8-40"><a href="#cb8-40" aria-hidden="true" tabindex="-1"></a><span class="ot">myApplication ::</span> <span class="dt">Application</span> ()</span>
|
||||
<span id="cb8-41"><a href="#cb8-41" aria-hidden="true" tabindex="-1"></a>myApplication <span class="ot">=</span> <span class="kw">do</span></span>
|
||||
<span id="cb8-42"><a href="#cb8-42" aria-hidden="true" tabindex="-1"></a> O.insertEntity messagesTable (T.pack <span class="st">"Hello Orville"</span>)</span>
|
||||
<span id="cb8-43"><a href="#cb8-43" aria-hidden="true" tabindex="-1"></a> messages <span class="ot"><-</span> O.findEntitiesBy messagesTable <span class="fu">mempty</span></span>
|
||||
<span id="cb8-44"><a href="#cb8-44" aria-hidden="true" tabindex="-1"></a> MIO.liftIO <span class="op">.</span> <span class="fu">print</span> <span class="op">$</span> messages</span>
|
||||
<span id="cb8-45"><a href="#cb8-45" aria-hidden="true" tabindex="-1"></a></span>
|
||||
<span id="cb8-46"><a href="#cb8-46" aria-hidden="true" tabindex="-1"></a><span class="ot">schema ::</span> [<span class="dt">AutoMigration.SchemaItem</span>]</span>
|
||||
<span id="cb8-47"><a href="#cb8-47" aria-hidden="true" tabindex="-1"></a>schema <span class="ot">=</span></span>
|
||||
<span id="cb8-48"><a href="#cb8-48" aria-hidden="true" tabindex="-1"></a> [ <span class="dt">AutoMigration.SchemaTable</span> messagesTable</span>
|
||||
<span id="cb8-49"><a href="#cb8-49" aria-hidden="true" tabindex="-1"></a> ]</span>
|
||||
<span id="cb8-50"><a href="#cb8-50" aria-hidden="true" tabindex="-1"></a></span>
|
||||
<span id="cb8-51"><a href="#cb8-51" aria-hidden="true" tabindex="-1"></a><span class="ot">main ::</span> <span class="dt">IO</span> ()</span>
|
||||
<span id="cb8-52"><a href="#cb8-52" aria-hidden="true" tabindex="-1"></a>main <span class="ot">=</span> <span class="kw">do</span></span>
|
||||
<span id="cb8-53"><a href="#cb8-53" aria-hidden="true" tabindex="-1"></a> pool <span class="ot"><-</span></span>
|
||||
<span id="cb8-54"><a href="#cb8-54" aria-hidden="true" tabindex="-1"></a> O.createConnectionPool</span>
|
||||
<span id="cb8-55"><a href="#cb8-55" aria-hidden="true" tabindex="-1"></a> <span class="dt">O.ConnectionOptions</span></span>
|
||||
<span id="cb8-56"><a href="#cb8-56" aria-hidden="true" tabindex="-1"></a> { O.connectionString <span class="ot">=</span> <span class="st">"host=localhost user=postgres password=postgres"</span></span>
|
||||
<span id="cb8-57"><a href="#cb8-57" aria-hidden="true" tabindex="-1"></a> , O.connectionNoticeReporting <span class="ot">=</span> <span class="dt">O.DisableNoticeReporting</span></span>
|
||||
<span id="cb8-58"><a href="#cb8-58" aria-hidden="true" tabindex="-1"></a> , O.connectionPoolStripes <span class="ot">=</span> <span class="dt">O.OneStripePerCapability</span></span>
|
||||
<span id="cb8-59"><a href="#cb8-59" aria-hidden="true" tabindex="-1"></a> , O.connectionPoolLingerTime <span class="ot">=</span> <span class="dv">10</span></span>
|
||||
<span id="cb8-60"><a href="#cb8-60" aria-hidden="true" tabindex="-1"></a> , O.connectionPoolMaxConnections <span class="ot">=</span> <span class="dt">O.MaxConnectionsPerStripe</span> <span class="dv">1</span></span>
|
||||
<span id="cb8-61"><a href="#cb8-61" aria-hidden="true" tabindex="-1"></a> }</span>
|
||||
<span id="cb8-62"><a href="#cb8-62" aria-hidden="true" tabindex="-1"></a></span>
|
||||
<span id="cb8-63"><a href="#cb8-63" aria-hidden="true" tabindex="-1"></a> runApplication pool (AutoMigration.autoMigrateSchema AutoMigration.defaultOptions schema)</span>
|
||||
<span id="cb8-64"><a href="#cb8-64" aria-hidden="true" tabindex="-1"></a> runApplication pool myApplication</span></code></pre></div>
|
||||
</section>
|
||||
</article>
|
||||
|
||||
|
@ -36,7 +36,7 @@
|
||||
|
||||
<h3>How-To Guides</h3>
|
||||
|
||||
<a href="../how-tos/how-to-add-orville-to-your-application-monad.html">How To Add Orville to Your Application Monad (Upcoming)</a>
|
||||
<a href="../how-tos/how-to-add-orville-to-your-application-monad.html">How To Add Orville to Your Application Monad</a>
|
||||
|
||||
<a href="../how-tos/how-to-marshall-a-haskell-record.html">How To Marshall a Haskell Record (Upcoming)</a>
|
||||
|
||||
|
@ -36,7 +36,7 @@
|
||||
|
||||
<h3>How-To Guides</h3>
|
||||
|
||||
<a href="../how-tos/how-to-add-orville-to-your-application-monad.html">How To Add Orville to Your Application Monad (Upcoming)</a>
|
||||
<a href="../how-tos/how-to-add-orville-to-your-application-monad.html">How To Add Orville to Your Application Monad</a>
|
||||
|
||||
<a href="../how-tos/how-to-marshall-a-haskell-record.html">How To Marshall a Haskell Record (Upcoming)</a>
|
||||
|
||||
|
@ -36,7 +36,7 @@
|
||||
|
||||
<h3>How-To Guides</h3>
|
||||
|
||||
<a href="../how-tos/how-to-add-orville-to-your-application-monad.html">How To Add Orville to Your Application Monad (Upcoming)</a>
|
||||
<a href="../how-tos/how-to-add-orville-to-your-application-monad.html">How To Add Orville to Your Application Monad</a>
|
||||
|
||||
<a href="../how-tos/how-to-marshall-a-haskell-record.html">How To Marshall a Haskell Record (Upcoming)</a>
|
||||
|
||||
|
@ -36,7 +36,7 @@
|
||||
|
||||
<h3>How-To Guides</h3>
|
||||
|
||||
<a href="../how-tos/how-to-add-orville-to-your-application-monad.html">How To Add Orville to Your Application Monad (Upcoming)</a>
|
||||
<a href="../how-tos/how-to-add-orville-to-your-application-monad.html">How To Add Orville to Your Application Monad</a>
|
||||
|
||||
<a href="../how-tos/how-to-marshall-a-haskell-record.html">How To Marshall a Haskell Record (Upcoming)</a>
|
||||
|
||||
|
@ -36,7 +36,7 @@
|
||||
|
||||
<h3>How-To Guides</h3>
|
||||
|
||||
<a href="./how-tos/how-to-add-orville-to-your-application-monad.html">How To Add Orville to Your Application Monad (Upcoming)</a>
|
||||
<a href="./how-tos/how-to-add-orville-to-your-application-monad.html">How To Add Orville to Your Application Monad</a>
|
||||
|
||||
<a href="./how-tos/how-to-marshall-a-haskell-record.html">How To Marshall a Haskell Record (Upcoming)</a>
|
||||
|
||||
|
@ -36,7 +36,7 @@
|
||||
|
||||
<h3>How-To Guides</h3>
|
||||
|
||||
<a href="../how-tos/how-to-add-orville-to-your-application-monad.html">How To Add Orville to Your Application Monad (Upcoming)</a>
|
||||
<a href="../how-tos/how-to-add-orville-to-your-application-monad.html">How To Add Orville to Your Application Monad</a>
|
||||
|
||||
<a href="../how-tos/how-to-marshall-a-haskell-record.html">How To Marshall a Haskell Record (Upcoming)</a>
|
||||
|
||||
|
@ -36,7 +36,7 @@
|
||||
|
||||
<h3>How-To Guides</h3>
|
||||
|
||||
<a href="../how-tos/how-to-add-orville-to-your-application-monad.html">How To Add Orville to Your Application Monad (Upcoming)</a>
|
||||
<a href="../how-tos/how-to-add-orville-to-your-application-monad.html">How To Add Orville to Your Application Monad</a>
|
||||
|
||||
<a href="../how-tos/how-to-marshall-a-haskell-record.html">How To Marshall a Haskell Record (Upcoming)</a>
|
||||
|
||||
|
@ -36,7 +36,7 @@
|
||||
|
||||
<h3>How-To Guides</h3>
|
||||
|
||||
<a href="../how-tos/how-to-add-orville-to-your-application-monad.html">How To Add Orville to Your Application Monad (Upcoming)</a>
|
||||
<a href="../how-tos/how-to-add-orville-to-your-application-monad.html">How To Add Orville to Your Application Monad</a>
|
||||
|
||||
<a href="../how-tos/how-to-marshall-a-haskell-record.html">How To Marshall a Haskell Record (Upcoming)</a>
|
||||
|
||||
|
@ -36,7 +36,7 @@
|
||||
|
||||
<h3>How-To Guides</h3>
|
||||
|
||||
<a href="../how-tos/how-to-add-orville-to-your-application-monad.html">How To Add Orville to Your Application Monad (Upcoming)</a>
|
||||
<a href="../how-tos/how-to-add-orville-to-your-application-monad.html">How To Add Orville to Your Application Monad</a>
|
||||
|
||||
<a href="../how-tos/how-to-marshall-a-haskell-record.html">How To Marshall a Haskell Record (Upcoming)</a>
|
||||
|
||||
|
@ -36,7 +36,7 @@
|
||||
|
||||
<h3>How-To Guides</h3>
|
||||
|
||||
<a href="../how-tos/how-to-add-orville-to-your-application-monad.html">How To Add Orville to Your Application Monad (Upcoming)</a>
|
||||
<a href="../how-tos/how-to-add-orville-to-your-application-monad.html">How To Add Orville to Your Application Monad</a>
|
||||
|
||||
<a href="../how-tos/how-to-marshall-a-haskell-record.html">How To Marshall a Haskell Record (Upcoming)</a>
|
||||
|
||||
|
@ -0,0 +1,19 @@
|
||||
*** Main.hs (Old)
|
||||
--- Main.hs (New)
|
||||
***************
|
||||
*** 5,10 ****
|
||||
|
||||
import qualified Control.Monad.IO.Class as MIO
|
||||
|
||||
newtype Application a =
|
||||
! Application (IO a)
|
||||
deriving
|
||||
--- 5,12 ----
|
||||
|
||||
+ import qualified Control.Monad.Reader as Reader
|
||||
import qualified Control.Monad.IO.Class as MIO
|
||||
+ import qualified Orville.PostgreSQL as O
|
||||
|
||||
newtype Application a =
|
||||
! Application (Reader.ReaderT O.OrvilleState IO a)
|
||||
deriving
|
@ -0,0 +1,10 @@
|
||||
*** Main.hs (Old)
|
||||
--- Main.hs (New)
|
||||
***************
|
||||
*** 16,17 ****
|
||||
--- 16,20 ----
|
||||
, MIO.MonadIO
|
||||
+ , O.MonadOrville
|
||||
+ , O.MonadOrvilleControl
|
||||
+ , O.HasOrvilleState
|
||||
)
|
@ -0,0 +1,21 @@
|
||||
*** Main.hs (Old)
|
||||
--- Main.hs (New)
|
||||
***************
|
||||
*** 21,25 ****
|
||||
|
||||
! runApplication :: Application a -> IO a
|
||||
! runApplication (Application io) =
|
||||
! io
|
||||
|
||||
--- 21,31 ----
|
||||
|
||||
! runApplication :: O.ConnectionPool -> Application a -> IO a
|
||||
! runApplication pool (Application reader) =
|
||||
! let
|
||||
! orvilleState =
|
||||
! O.newOrvilleState
|
||||
! O.defaultErrorDetailLevel
|
||||
! pool
|
||||
! in
|
||||
! Reader.runReaderT reader orvilleState
|
||||
|
@ -0,0 +1,21 @@
|
||||
*** Main.hs (Old)
|
||||
--- Main.hs (New)
|
||||
***************
|
||||
*** 36,38 ****
|
||||
main :: IO ()
|
||||
! main =
|
||||
! runApplication myApplication
|
||||
--- 36,48 ----
|
||||
main :: IO ()
|
||||
! main = do
|
||||
! pool <-
|
||||
! O.createConnectionPool
|
||||
! O.ConnectionOptions
|
||||
! { O.connectionString = "host=localhost user=postgres password=postgres"
|
||||
! , O.connectionNoticeReporting = O.DisableNoticeReporting
|
||||
! , O.connectionPoolStripes = O.OneStripePerCapability
|
||||
! , O.connectionPoolLingerTime = 10
|
||||
! , O.connectionPoolMaxConnections = O.MaxConnectionsPerStripe 1
|
||||
! }
|
||||
!
|
||||
! runApplication pool myApplication
|
@ -0,0 +1,29 @@
|
||||
*** Main.hs (Old)
|
||||
--- Main.hs (New)
|
||||
***************
|
||||
*** 7,8 ****
|
||||
--- 7,9 ----
|
||||
import qualified Control.Monad.IO.Class as MIO
|
||||
+ import qualified Data.Text as T
|
||||
import qualified Orville.PostgreSQL as O
|
||||
***************
|
||||
*** 31,35 ****
|
||||
|
||||
myApplication :: Application ()
|
||||
! myApplication =
|
||||
! MIO.liftIO . putStrLn $ "Hello Application"
|
||||
|
||||
--- 32,44 ----
|
||||
|
||||
+ messagesTable :: O.TableDefinition O.NoKey T.Text T.Text
|
||||
+ messagesTable =
|
||||
+ O.mkTableDefinitionWithoutKey
|
||||
+ "messages"
|
||||
+ (O.marshallField id (O.unboundedTextField "message"))
|
||||
+
|
||||
myApplication :: Application ()
|
||||
! myApplication = do
|
||||
! O.insertEntity messagesTable (T.pack "Hello Orville")
|
||||
! messages <- O.findEntitiesBy messagesTable mempty
|
||||
! MIO.liftIO . print $ messages
|
||||
|
@ -0,0 +1,24 @@
|
||||
*** Main.hs (Old)
|
||||
--- Main.hs (New)
|
||||
***************
|
||||
*** 9,10 ****
|
||||
--- 9,11 ----
|
||||
import qualified Orville.PostgreSQL as O
|
||||
+ import qualified Orville.PostgreSQL.AutoMigration as AutoMigration
|
||||
|
||||
***************
|
||||
*** 44,45 ****
|
||||
--- 45,51 ----
|
||||
|
||||
+ schema :: [AutoMigration.SchemaItem]
|
||||
+ schema =
|
||||
+ [ AutoMigration.SchemaTable messagesTable
|
||||
+ ]
|
||||
+
|
||||
main :: IO ()
|
||||
***************
|
||||
*** 56,57 ****
|
||||
--- 62,64 ----
|
||||
|
||||
+ runApplication pool (AutoMigration.autoMigrateSchema AutoMigration.defaultOptions schema)
|
||||
runApplication pool myApplication
|
@ -0,0 +1,33 @@
|
||||
cabal-version: 2.2
|
||||
|
||||
name: adding-orville-new-readert
|
||||
version: 0.1.0.0
|
||||
-- synopsis:
|
||||
-- description:
|
||||
homepage: https://github.com/flipstone/adding-orville-new-readert#readme
|
||||
license: BSD-3-Clause
|
||||
author: Flipstone Technology Partners, Inc
|
||||
maintainer: maintainers@flipstone.com
|
||||
copyright:
|
||||
category: sample
|
||||
build-type: Simple
|
||||
|
||||
executable adding-orville-new-readert
|
||||
hs-source-dirs: src
|
||||
main-is: Main.hs
|
||||
default-language: Haskell2010
|
||||
|
||||
build-depends: base >= 4.7 && < 5,
|
||||
mtl,
|
||||
orville-postgresql,
|
||||
text
|
||||
|
||||
ghc-options: -Wall
|
||||
-Wcompat
|
||||
-Widentities
|
||||
-Wincomplete-record-updates
|
||||
-Wincomplete-uni-patterns
|
||||
-Wmissing-export-lists
|
||||
-Wmissing-home-modules
|
||||
-Wpartial-fields
|
||||
-Wredundant-constraints
|
@ -0,0 +1 @@
|
||||
["Hello Orville"]
|
8
orville-docsite/samples/adding-orville-new-readert/mkdiffs.sh
Executable file
8
orville-docsite/samples/adding-orville-new-readert/mkdiffs.sh
Executable file
@ -0,0 +1,8 @@
|
||||
#!/usr/bin/env bash
|
||||
DIFF_OPTS=(-C 1 --label 'Main.hs (Old)' --label 'Main.hs (New)')
|
||||
diff "${DIFF_OPTS[@]}" snapshots/Main-1.hs snapshots/Main-2.hs > 1-add-readert.patch
|
||||
diff "${DIFF_OPTS[@]}" snapshots/Main-2.hs snapshots/Main-3.hs > 2-add-orville-typeclasses.patch
|
||||
diff "${DIFF_OPTS[@]}" snapshots/Main-3.hs snapshots/Main-4.hs > 3-update-runApplication.patch
|
||||
diff "${DIFF_OPTS[@]}" snapshots/Main-4.hs snapshots/Main-5.hs > 4-update-main.patch
|
||||
diff "${DIFF_OPTS[@]}" snapshots/Main-5.hs snapshots/Main-6.hs > 5-add-table.patch
|
||||
diff "${DIFF_OPTS[@]}" snapshots/Main-6.hs snapshots/Main-7.hs > 6-add-migrations.patch
|
25
orville-docsite/samples/adding-orville-new-readert/run.sh
Normal file
25
orville-docsite/samples/adding-orville-new-readert/run.sh
Normal file
@ -0,0 +1,25 @@
|
||||
# SNIPPET: hidden
|
||||
set -e
|
||||
service postgresql start
|
||||
# SNIPPET: hidden
|
||||
patch --output=snapshots/Main-2.hs snapshots/Main-1.hs 1-add-readert.patch
|
||||
patch --output=snapshots/Main-3.hs snapshots/Main-2.hs 2-add-orville-typeclasses.patch
|
||||
patch --output=snapshots/Main-4.hs snapshots/Main-3.hs 3-update-runApplication.patch
|
||||
patch --output=snapshots/Main-5.hs snapshots/Main-4.hs 4-update-main.patch
|
||||
patch --output=snapshots/Main-6.hs snapshots/Main-5.hs 5-add-table.patch
|
||||
patch --output=snapshots/Main-7.hs snapshots/Main-6.hs 6-add-migrations.patch
|
||||
mkdir -p src
|
||||
cp snapshots/Main-7.hs src/Main.hs
|
||||
# SNIPPET: buildAndExecute
|
||||
stack build
|
||||
# SNIPPET: hidden
|
||||
expected=$(cat expected-output.txt)
|
||||
actual=$(stack exec adding-orville-new-readert)
|
||||
|
||||
if [ "$expected" = "$actual" ]; then
|
||||
echo "Output matches expected"
|
||||
else
|
||||
echo "Expected output to be: $expected"
|
||||
echo "But it was actually : $actual"
|
||||
exit 1
|
||||
fi;
|
@ -0,0 +1,27 @@
|
||||
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
|
||||
module Main
|
||||
( main
|
||||
) where
|
||||
|
||||
import qualified Control.Monad.IO.Class as MIO
|
||||
|
||||
newtype Application a =
|
||||
Application (IO a)
|
||||
deriving
|
||||
( Functor
|
||||
, Applicative
|
||||
, Monad
|
||||
, MIO.MonadIO
|
||||
)
|
||||
|
||||
runApplication :: Application a -> IO a
|
||||
runApplication (Application io) =
|
||||
io
|
||||
|
||||
myApplication :: Application ()
|
||||
myApplication =
|
||||
MIO.liftIO . putStrLn $ "Hello Application"
|
||||
|
||||
main :: IO ()
|
||||
main =
|
||||
runApplication myApplication
|
@ -0,0 +1,29 @@
|
||||
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
|
||||
module Main
|
||||
( main
|
||||
) where
|
||||
|
||||
import qualified Control.Monad.Reader as Reader
|
||||
import qualified Control.Monad.IO.Class as MIO
|
||||
import qualified Orville.PostgreSQL as O
|
||||
|
||||
newtype Application a =
|
||||
Application (Reader.ReaderT O.OrvilleState IO a)
|
||||
deriving
|
||||
( Functor
|
||||
, Applicative
|
||||
, Monad
|
||||
, MIO.MonadIO
|
||||
)
|
||||
|
||||
runApplication :: Application a -> IO a
|
||||
runApplication (Application io) =
|
||||
io
|
||||
|
||||
myApplication :: Application ()
|
||||
myApplication =
|
||||
MIO.liftIO . putStrLn $ "Hello Application"
|
||||
|
||||
main :: IO ()
|
||||
main =
|
||||
runApplication myApplication
|
@ -0,0 +1,32 @@
|
||||
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
|
||||
module Main
|
||||
( main
|
||||
) where
|
||||
|
||||
import qualified Control.Monad.Reader as Reader
|
||||
import qualified Control.Monad.IO.Class as MIO
|
||||
import qualified Orville.PostgreSQL as O
|
||||
|
||||
newtype Application a =
|
||||
Application (Reader.ReaderT O.OrvilleState IO a)
|
||||
deriving
|
||||
( Functor
|
||||
, Applicative
|
||||
, Monad
|
||||
, MIO.MonadIO
|
||||
, O.MonadOrville
|
||||
, O.MonadOrvilleControl
|
||||
, O.HasOrvilleState
|
||||
)
|
||||
|
||||
runApplication :: Application a -> IO a
|
||||
runApplication (Application io) =
|
||||
io
|
||||
|
||||
myApplication :: Application ()
|
||||
myApplication =
|
||||
MIO.liftIO . putStrLn $ "Hello Application"
|
||||
|
||||
main :: IO ()
|
||||
main =
|
||||
runApplication myApplication
|
@ -0,0 +1,38 @@
|
||||
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
|
||||
module Main
|
||||
( main
|
||||
) where
|
||||
|
||||
import qualified Control.Monad.Reader as Reader
|
||||
import qualified Control.Monad.IO.Class as MIO
|
||||
import qualified Orville.PostgreSQL as O
|
||||
|
||||
newtype Application a =
|
||||
Application (Reader.ReaderT O.OrvilleState IO a)
|
||||
deriving
|
||||
( Functor
|
||||
, Applicative
|
||||
, Monad
|
||||
, MIO.MonadIO
|
||||
, O.MonadOrville
|
||||
, O.MonadOrvilleControl
|
||||
, O.HasOrvilleState
|
||||
)
|
||||
|
||||
runApplication :: O.ConnectionPool -> Application a -> IO a
|
||||
runApplication pool (Application reader) =
|
||||
let
|
||||
orvilleState =
|
||||
O.newOrvilleState
|
||||
O.defaultErrorDetailLevel
|
||||
pool
|
||||
in
|
||||
Reader.runReaderT reader orvilleState
|
||||
|
||||
myApplication :: Application ()
|
||||
myApplication =
|
||||
MIO.liftIO . putStrLn $ "Hello Application"
|
||||
|
||||
main :: IO ()
|
||||
main =
|
||||
runApplication myApplication
|
@ -0,0 +1,48 @@
|
||||
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
|
||||
module Main
|
||||
( main
|
||||
) where
|
||||
|
||||
import qualified Control.Monad.Reader as Reader
|
||||
import qualified Control.Monad.IO.Class as MIO
|
||||
import qualified Orville.PostgreSQL as O
|
||||
|
||||
newtype Application a =
|
||||
Application (Reader.ReaderT O.OrvilleState IO a)
|
||||
deriving
|
||||
( Functor
|
||||
, Applicative
|
||||
, Monad
|
||||
, MIO.MonadIO
|
||||
, O.MonadOrville
|
||||
, O.MonadOrvilleControl
|
||||
, O.HasOrvilleState
|
||||
)
|
||||
|
||||
runApplication :: O.ConnectionPool -> Application a -> IO a
|
||||
runApplication pool (Application reader) =
|
||||
let
|
||||
orvilleState =
|
||||
O.newOrvilleState
|
||||
O.defaultErrorDetailLevel
|
||||
pool
|
||||
in
|
||||
Reader.runReaderT reader orvilleState
|
||||
|
||||
myApplication :: Application ()
|
||||
myApplication =
|
||||
MIO.liftIO . putStrLn $ "Hello Application"
|
||||
|
||||
main :: IO ()
|
||||
main = do
|
||||
pool <-
|
||||
O.createConnectionPool
|
||||
O.ConnectionOptions
|
||||
{ O.connectionString = "host=localhost user=postgres password=postgres"
|
||||
, O.connectionNoticeReporting = O.DisableNoticeReporting
|
||||
, O.connectionPoolStripes = O.OneStripePerCapability
|
||||
, O.connectionPoolLingerTime = 10
|
||||
, O.connectionPoolMaxConnections = O.MaxConnectionsPerStripe 1
|
||||
}
|
||||
|
||||
runApplication pool myApplication
|
@ -0,0 +1,57 @@
|
||||
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
|
||||
module Main
|
||||
( main
|
||||
) where
|
||||
|
||||
import qualified Control.Monad.Reader as Reader
|
||||
import qualified Control.Monad.IO.Class as MIO
|
||||
import qualified Data.Text as T
|
||||
import qualified Orville.PostgreSQL as O
|
||||
|
||||
newtype Application a =
|
||||
Application (Reader.ReaderT O.OrvilleState IO a)
|
||||
deriving
|
||||
( Functor
|
||||
, Applicative
|
||||
, Monad
|
||||
, MIO.MonadIO
|
||||
, O.MonadOrville
|
||||
, O.MonadOrvilleControl
|
||||
, O.HasOrvilleState
|
||||
)
|
||||
|
||||
runApplication :: O.ConnectionPool -> Application a -> IO a
|
||||
runApplication pool (Application reader) =
|
||||
let
|
||||
orvilleState =
|
||||
O.newOrvilleState
|
||||
O.defaultErrorDetailLevel
|
||||
pool
|
||||
in
|
||||
Reader.runReaderT reader orvilleState
|
||||
|
||||
messagesTable :: O.TableDefinition O.NoKey T.Text T.Text
|
||||
messagesTable =
|
||||
O.mkTableDefinitionWithoutKey
|
||||
"messages"
|
||||
(O.marshallField id (O.unboundedTextField "message"))
|
||||
|
||||
myApplication :: Application ()
|
||||
myApplication = do
|
||||
O.insertEntity messagesTable (T.pack "Hello Orville")
|
||||
messages <- O.findEntitiesBy messagesTable mempty
|
||||
MIO.liftIO . print $ messages
|
||||
|
||||
main :: IO ()
|
||||
main = do
|
||||
pool <-
|
||||
O.createConnectionPool
|
||||
O.ConnectionOptions
|
||||
{ O.connectionString = "host=localhost user=postgres password=postgres"
|
||||
, O.connectionNoticeReporting = O.DisableNoticeReporting
|
||||
, O.connectionPoolStripes = O.OneStripePerCapability
|
||||
, O.connectionPoolLingerTime = 10
|
||||
, O.connectionPoolMaxConnections = O.MaxConnectionsPerStripe 1
|
||||
}
|
||||
|
||||
runApplication pool myApplication
|
@ -0,0 +1,64 @@
|
||||
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
|
||||
module Main
|
||||
( main
|
||||
) where
|
||||
|
||||
import qualified Control.Monad.Reader as Reader
|
||||
import qualified Control.Monad.IO.Class as MIO
|
||||
import qualified Data.Text as T
|
||||
import qualified Orville.PostgreSQL as O
|
||||
import qualified Orville.PostgreSQL.AutoMigration as AutoMigration
|
||||
|
||||
newtype Application a =
|
||||
Application (Reader.ReaderT O.OrvilleState IO a)
|
||||
deriving
|
||||
( Functor
|
||||
, Applicative
|
||||
, Monad
|
||||
, MIO.MonadIO
|
||||
, O.MonadOrville
|
||||
, O.MonadOrvilleControl
|
||||
, O.HasOrvilleState
|
||||
)
|
||||
|
||||
runApplication :: O.ConnectionPool -> Application a -> IO a
|
||||
runApplication pool (Application reader) =
|
||||
let
|
||||
orvilleState =
|
||||
O.newOrvilleState
|
||||
O.defaultErrorDetailLevel
|
||||
pool
|
||||
in
|
||||
Reader.runReaderT reader orvilleState
|
||||
|
||||
messagesTable :: O.TableDefinition O.NoKey T.Text T.Text
|
||||
messagesTable =
|
||||
O.mkTableDefinitionWithoutKey
|
||||
"messages"
|
||||
(O.marshallField id (O.unboundedTextField "message"))
|
||||
|
||||
myApplication :: Application ()
|
||||
myApplication = do
|
||||
O.insertEntity messagesTable (T.pack "Hello Orville")
|
||||
messages <- O.findEntitiesBy messagesTable mempty
|
||||
MIO.liftIO . print $ messages
|
||||
|
||||
schema :: [AutoMigration.SchemaItem]
|
||||
schema =
|
||||
[ AutoMigration.SchemaTable messagesTable
|
||||
]
|
||||
|
||||
main :: IO ()
|
||||
main = do
|
||||
pool <-
|
||||
O.createConnectionPool
|
||||
O.ConnectionOptions
|
||||
{ O.connectionString = "host=localhost user=postgres password=postgres"
|
||||
, O.connectionNoticeReporting = O.DisableNoticeReporting
|
||||
, O.connectionPoolStripes = O.OneStripePerCapability
|
||||
, O.connectionPoolLingerTime = 10
|
||||
, O.connectionPoolMaxConnections = O.MaxConnectionsPerStripe 1
|
||||
}
|
||||
|
||||
runApplication pool (AutoMigration.autoMigrateSchema AutoMigration.defaultOptions schema)
|
||||
runApplication pool myApplication
|
@ -0,0 +1,69 @@
|
||||
# This file was automatically generated by 'stack init'
|
||||
#
|
||||
# Some commonly used options have been documented as comments in this file.
|
||||
# For advanced use and comprehensive documentation of the format, please see:
|
||||
# https://docs.haskellstack.org/en/stable/yaml_configuration/
|
||||
|
||||
# Resolver to choose a 'specific' stackage snapshot or a compiler version.
|
||||
# A snapshot resolver dictates the compiler version and the set of packages
|
||||
# to be used for project dependencies. For example:
|
||||
#
|
||||
# resolver: lts-21.13
|
||||
# resolver: nightly-2023-09-24
|
||||
# resolver: ghc-9.6.2
|
||||
#
|
||||
# The location of a snapshot can be provided as a file or url. Stack assumes
|
||||
# a snapshot provided as a file might change, whereas a url resource does not.
|
||||
#
|
||||
# resolver: ./custom-snapshot.yaml
|
||||
# resolver: https://example.com/snapshots/2023-01-01.yaml
|
||||
resolver: lts-21.19
|
||||
system-ghc: true
|
||||
install-ghc: false
|
||||
|
||||
# User packages to be built.
|
||||
# Various formats can be used as shown in the example below.
|
||||
#
|
||||
# packages:
|
||||
# - some-directory
|
||||
# - https://example.com/foo/bar/baz-0.0.2.tar.gz
|
||||
# subdirs:
|
||||
# - auto-update
|
||||
# - wai
|
||||
packages:
|
||||
- .
|
||||
# Dependency packages to be pulled from upstream that are not in the resolver.
|
||||
# These entries can reference officially published versions as well as
|
||||
# forks / in-progress versions pinned to a git hash. For example:
|
||||
#
|
||||
# extra-deps:
|
||||
# - acme-missiles-0.3
|
||||
# - git: https://github.com/commercialhaskell/stack.git
|
||||
# commit: e7b331f14bcffb8367cd58fbfc8b40ec7642100a
|
||||
#
|
||||
extra-deps:
|
||||
- orville-postgresql-1.0.0.0
|
||||
|
||||
# Override default flag values for local packages and extra-deps
|
||||
# flags: {}
|
||||
|
||||
# Extra package databases containing global packages
|
||||
# extra-package-dbs: []
|
||||
|
||||
# Control whether we use the GHC we find on the path
|
||||
# system-ghc: true
|
||||
#
|
||||
# Require a specific version of Stack, using version ranges
|
||||
# require-stack-version: -any # Default
|
||||
# require-stack-version: ">=2.13"
|
||||
#
|
||||
# Override the architecture used by Stack, especially useful on Windows
|
||||
# arch: i386
|
||||
# arch: x86_64
|
||||
#
|
||||
# Extra directories used by Stack for building
|
||||
# extra-include-dirs: [/path/to/dir]
|
||||
# extra-lib-dirs: [/path/to/dir]
|
||||
#
|
||||
# Allow a newer minor version of GHC than the snapshot specifies
|
||||
# compiler-check: newer-minor
|
@ -0,0 +1,19 @@
|
||||
# This file was autogenerated by Stack.
|
||||
# You should not edit this file by hand.
|
||||
# For more information, please see the documentation at:
|
||||
# https://docs.haskellstack.org/en/stable/lock_files
|
||||
|
||||
packages:
|
||||
- completed:
|
||||
hackage: orville-postgresql-1.0.0.0@sha256:35e9b9f8bc0bc1ee1847bcb5340fa39bed320f1573099ec16ca394726a50593a,9018
|
||||
pantry-tree:
|
||||
sha256: b8d324f2ad94f12ac419996cc2947ee0c69c5178b2caf13dc92135118602bbd8
|
||||
size: 12020
|
||||
original:
|
||||
hackage: orville-postgresql-1.0.0.0
|
||||
snapshots:
|
||||
- completed:
|
||||
sha256: fb482b8e2d5d061cdda4ba1da2957c012740c893a5ee1c1b99001adae7b1fbe7
|
||||
size: 640046
|
||||
url: https://raw.githubusercontent.com/commercialhaskell/stackage-snapshots/master/lts/21/19.yaml
|
||||
original: lts-21.19
|
@ -1,6 +1,71 @@
|
||||
---
|
||||
title: How To Add Orville to Your Application Monad (Upcoming)
|
||||
title: How To Add Orville to Your Application Monad
|
||||
navOrder: 1
|
||||
---
|
||||
|
||||
Coming Soon
|
||||
This guide will show you how to add Orville to your already existing
|
||||
application monad in the simplest way possible. It relies on the `mtl` package
|
||||
in addition to `orville-postgresql`, so you should make sure these packages are
|
||||
in your package dependencies in either your `.cabal` or `package.yaml` file.
|
||||
|
||||
The file listing below shows a simple, minimal application with its own
|
||||
`Application` monad. Your application is certainly more complicated than this,
|
||||
but you can think of the `IO` type below being whatever base monad or monad
|
||||
transformer stack you already have in place.
|
||||
|
||||
$sample("adding-orville-new-readert/snapshots/Main-1.hs", "filename=Main.hs (Before)")$
|
||||
|
||||
We're going to add a new `ReaderT` transformer to the innards of the
|
||||
`Application` newtype to hold Orville's `OrvilleState` parameter. We'll have to
|
||||
import the `Control.Monad.Reader` module (from the `mtl` package) and the
|
||||
`Orville.PostgreSQL` module (from the `orville-postgresql`) package to
|
||||
reference these types.
|
||||
|
||||
$sample("adding-orville-new-readert/1-add-readert.patch", "filename=Main.hs")$
|
||||
|
||||
This new `ReaderT` context adds the internal state that Orville needs to do its
|
||||
job. In order to use functions from the Orville package directly in your monad
|
||||
it will need to provide instances for the three typeclasses that make up a
|
||||
complete Orville monad - `MonadOrville`, `MonadOrvilleControl` and
|
||||
`HasOrvilleState`. Luckily, it's a simple matter of adding these three
|
||||
typeclasses the the deriving list for `Application`. If you're not using
|
||||
`GHC2021` you'll need the `GeneralizedNewtypeDeriving` language extension, as
|
||||
in the example in this guide.
|
||||
|
||||
$sample("adding-orville-new-readert/2-add-orville-typeclasses.patch", "filename=Main.hs")$
|
||||
|
||||
Somewhere in your code you'll have a function similar to this example's
|
||||
`runApplication` function. It needs to be updated to expect a `ConnectionPool`
|
||||
argument. We'll use the connection pool to build a fresh new `OrvilleState` for
|
||||
our `Reader` context. Then we can use `runReaderT` resolve the `ReaderT` layer
|
||||
we added to our stack and get back whatever monad type was there before we
|
||||
added Orville. In this case that's just the `IO` type. This means
|
||||
`runApplication` will return the same type that it returned befored we added
|
||||
Orville, it just requires the `ConnectionPool` parameter to do its job now.
|
||||
|
||||
$sample("adding-orville-new-readert/3-update-runApplication.patch", "filename=Main.hs")$
|
||||
|
||||
Since we added a parameter to `runApplication`, we need to go to each place
|
||||
it's called and pass a `ConnectionPool` parameter now. In this guide that's
|
||||
just a single place in the `main` function. We'll use `createConnectionPool` as
|
||||
normal to make the pool we want to use.
|
||||
|
||||
$sample("adding-orville-new-readert/4-update-main.patch", "filename=Main.hs")$
|
||||
|
||||
Our `Application` monad is now fully equipped to run Orville operations! To
|
||||
show it works, let's add a `messages` table and update the `myApplication`
|
||||
logic to insert and retrieve a simple greeting message.
|
||||
|
||||
$sample("adding-orville-new-readert/5-add-table.patch", "filename=Main.hs")$
|
||||
|
||||
Finally, we'll equip our application with automatic migrations using Orville's
|
||||
`Orville.PostgreSQL.Automigration` module so that the `messages` table will be
|
||||
created before we try to access it.
|
||||
|
||||
$sample("adding-orville-new-readert/6-add-migrations.patch", "filename=Main.hs")$
|
||||
|
||||
That's it! That completes this guide about how to add Orville to your existing
|
||||
application monad. To wrap things up, here's the final listing of `Main.hs`
|
||||
with all the changes we made.
|
||||
|
||||
$sample("adding-orville-new-readert/snapshots/Main-7.hs", "filename=Main.hs (After)")$
|
||||
|
Loading…
Reference in New Issue
Block a user