git.fiddlerwoaroof.com
Browse code

model: refactor

Ed Langley authored on 30/08/2019 21:33:52
Showing 3 changed files
... ...
@@ -83,7 +83,11 @@
83 83
                 (rutilsx.threading:->>
84 84
                  value
85 85
                  (acons "completed" 'yason:false)
86
-                 (acons "url" (format nil "http://~a:~d/todo/~d" *external-host* *external-port* id)))
86
+                 (acons "url"
87
+                        (format nil "http://~a:~d/todo/~d"
88
+                                ,*external-host*
89
+                                ,*external-port*
90
+                                id)))
87 91
                 :test 'equal))))
88 92
    #+END_SRC
89 93
 
... ...
@@ -95,14 +99,15 @@
95 99
    #+NAME: update-todo
96 100
    #+BEGIN_SRC lisp :tangle no
97 101
      (defun update-todo (id v)
98
-       (setf (todo id)
99
-             (serapeum:merge-tables (or (todo id)
100
-                                        (make-hash-table :test 'equal))
101
-                                    (data-lens.lenses:over *completed-lens*
102
-                                                           'bool-to-yason
103
-                                                           (alexandria:alist-hash-table
104
-                                                            v
105
-                                                            :test 'equal)))))
102
+       (let* ((old-todo (or (todo id)
103
+                            (make-hash-table :test 'equal)))
104
+              (in-hash-table (alexandria:alist-hash-table v :test 'equal))
105
+              (update (data-lens.lenses:over *completed-lens*
106
+                                             'bool-to-yason
107
+                                             in-hash-table)))
108
+         (setf (todo id)
109
+               (serapeum:merge-tables old-todo
110
+                                      update))))
106 111
    #+END_SRC
107 112
 
108 113
 ** Examples
... ...
@@ -3,7 +3,7 @@
3 3
 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
4 4
 <html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
5 5
 <head>
6
-<!-- 2019-08-30 Fri 03:12 -->
6
+<!-- 2019-08-30 Fri 16:33 -->
7 7
 <meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
8 8
 <meta name="viewport" content="width=device-width, initial-scale=1" />
9 9
 <title>TODO backend implementation using CL and fukamachi/ningle</title>
... ...
@@ -300,34 +300,34 @@ for the JavaScript code in this tag.
300 300
 <h2>Table of Contents</h2>
301 301
 <div id="text-table-of-contents">
302 302
 <ul>
303
-<li><a href="#orga4265f9">1. Setup</a></li>
304
-<li><a href="#org39e7a12">2. todo API</a>
303
+<li><a href="#org45f170c">1. Setup</a></li>
304
+<li><a href="#org750f278">2. todo API</a>
305 305
 <ul>
306
-<li><a href="#org6ea07f3">2.1. List-level APIs</a></li>
307
-<li><a href="#org005bb52">2.2. Getting/Replacing a todo</a></li>
308
-<li><a href="#org77d0812">2.3. Adding and modifying todos</a></li>
309
-<li><a href="#org09e92d6">2.4. Examples</a></li>
306
+<li><a href="#org47779f4">2.1. List-level APIs</a></li>
307
+<li><a href="#org57d2aea">2.2. Getting/Replacing a todo</a></li>
308
+<li><a href="#orgbf48fa4">2.3. Adding and modifying todos</a></li>
309
+<li><a href="#org87b91ac">2.4. Examples</a></li>
310 310
 </ul>
311 311
 </li>
312
-<li><a href="#orgf023b98">3. Routing</a>
312
+<li><a href="#org6a09bc1">3. Routing</a>
313 313
 <ul>
314
-<li><a href="#org62738a5">3.1. Routing utilities</a></li>
315
-<li><a href="#org9f65218">3.2. todo routes</a></li>
314
+<li><a href="#org20ffa7f">3.1. Routing utilities</a></li>
315
+<li><a href="#org7bdd028">3.2. todo routes</a></li>
316 316
 </ul>
317 317
 </li>
318
-<li><a href="#org5597baf">4. Source</a>
318
+<li><a href="#orgd46ec32">4. Source</a>
319 319
 <ul>
320
-<li><a href="#org80852ef">4.1. model.lisp source code</a></li>
321
-<li><a href="#orgde4e27d">4.2. routing.lisp source</a></li>
322
-<li><a href="#org76a7993">4.3. main.lisp source</a></li>
320
+<li><a href="#org9c84f34">4.1. model.lisp source code</a></li>
321
+<li><a href="#org76ec19a">4.2. routing.lisp source</a></li>
322
+<li><a href="#org98907a6">4.3. main.lisp source</a></li>
323 323
 </ul>
324 324
 </li>
325 325
 </ul>
326 326
 </div>
327 327
 </div>
328 328
 
329
-<div id="outline-container-orga4265f9" class="outline-2">
330
-<h2 id="orga4265f9"><span class="section-number-2">1</span> Setup</h2>
329
+<div id="outline-container-org45f170c" class="outline-2">
330
+<h2 id="org45f170c"><span class="section-number-2">1</span> Setup</h2>
331 331
 <div class="outline-text-2" id="text-1">
332 332
 <ul class="org-ul">
333 333
 <li><code class="src src-sh">git clone https://github.com/fiddlerwoaroof/data-lens.git ~/quicklisp/local-projects/data-lens</code></li>
... ...
@@ -347,8 +347,8 @@ After this, all the tests <a href="http://www.todobackend.com/specs/index.html?h
347 347
 </div>
348 348
 </div>
349 349
 
350
-<div id="outline-container-org39e7a12" class="outline-2">
351
-<h2 id="org39e7a12"><span class="section-number-2">2</span> todo API</h2>
350
+<div id="outline-container-org750f278" class="outline-2">
351
+<h2 id="org750f278"><span class="section-number-2">2</span> todo API</h2>
352 352
 <div class="outline-text-2" id="text-2">
353 353
 <p>
354 354
 We use a fairly simple structure for our "database": a fset map (a
... ...
@@ -358,8 +358,8 @@ referenced as <code>*todo*</code>, but this is a detail hidden behind the API.
358 358
 </p>
359 359
 </div>
360 360
 
361
-<div id="outline-container-org6ea07f3" class="outline-3">
362
-<h3 id="org6ea07f3"><span class="section-number-3">2.1</span> List-level APIs</h3>
361
+<div id="outline-container-org47779f4" class="outline-3">
362
+<h3 id="org47779f4"><span class="section-number-3">2.1</span> List-level APIs</h3>
363 363
 <div class="outline-text-3" id="text-2-1">
364 364
 <p>
365 365
 These are functions for getting the todo list and clearing
... ...
@@ -368,7 +368,7 @@ and <code>clear-todos</code> for DELETE requests.
368 368
 </p>
369 369
 
370 370
 <div class="org-src-container">
371
-<pre class="src src-lisp" id="orgcdf7e06"><span style="color: #8c8c8c;">(</span><span style="color: #F0DFAF;">defun</span> <span style="color: #8CD0D3;">todos</span> <span style="color: #93a8c6;">()</span>
371
+<pre class="src src-lisp" id="orgc8a4ff2"><span style="color: #8c8c8c;">(</span><span style="color: #F0DFAF;">defun</span> <span style="color: #8CD0D3;">todos</span> <span style="color: #93a8c6;">()</span>
372 372
   <span style="color: #93a8c6;">(</span>gmap:gmap <span style="font-weight: bold;">:seq</span>
373 373
              <span style="color: #b0b1a3;">(</span><span style="color: #F0DFAF;">lambda</span> <span style="color: #97b098;">(</span>_ b<span style="color: #97b098;">)</span>
374 374
                <span style="color: #97b098;">(</span><span style="color: #F0DFAF;">declare</span> <span style="color: #aebed8;">(</span>ignore _<span style="color: #aebed8;">)</span><span style="color: #97b098;">)</span>
... ...
@@ -383,8 +383,8 @@ and <code>clear-todos</code> for DELETE requests.
383 383
 </div>
384 384
 </div>
385 385
 
386
-<div id="outline-container-org005bb52" class="outline-3">
387
-<h3 id="org005bb52"><span class="section-number-3">2.2</span> Getting/Replacing a todo</h3>
386
+<div id="outline-container-org57d2aea" class="outline-3">
387
+<h3 id="org57d2aea"><span class="section-number-3">2.2</span> Getting/Replacing a todo</h3>
388 388
 <div class="outline-text-3" id="text-2-2">
389 389
 <p>
390 390
 This uses lisp's <a href="http://www.lispworks.com/documentation/HyperSpec/Body/05_a.htm">generalized references</a> to abstract away the
... ...
@@ -394,7 +394,7 @@ the GET request for a specific todo by id.
394 394
 </p>
395 395
 
396 396
 <div class="org-src-container">
397
-<pre class="src src-lisp" id="org76060a1"><span style="color: #8c8c8c;">(</span><span style="color: #F0DFAF;">defun</span> <span style="color: #8CD0D3;">todo</span> <span style="color: #93a8c6;">(</span>id<span style="color: #93a8c6;">)</span>
397
+<pre class="src src-lisp" id="org404baac"><span style="color: #8c8c8c;">(</span><span style="color: #F0DFAF;">defun</span> <span style="color: #8CD0D3;">todo</span> <span style="color: #93a8c6;">(</span>id<span style="color: #93a8c6;">)</span>
398 398
   <span style="color: #93a8c6;">(</span><span style="color: #F0DFAF;">let</span> <span style="color: #b0b1a3;">(</span><span style="color: #97b098;">(</span>todo <span style="color: #aebed8;">(</span>fset:@ *todos* id<span style="color: #aebed8;">)</span><span style="color: #97b098;">)</span><span style="color: #b0b1a3;">)</span>
399 399
     todo<span style="color: #93a8c6;">)</span><span style="color: #8c8c8c;">)</span>
400 400
 
... ...
@@ -410,8 +410,8 @@ the GET request for a specific todo by id.
410 410
 </div>
411 411
 </div>
412 412
 
413
-<div id="outline-container-org77d0812" class="outline-3">
414
-<h3 id="org77d0812"><span class="section-number-3">2.3</span> Adding and modifying todos</h3>
413
+<div id="outline-container-orgbf48fa4" class="outline-3">
414
+<h3 id="orgbf48fa4"><span class="section-number-3">2.3</span> Adding and modifying todos</h3>
415 415
 <div class="outline-text-3" id="text-2-3">
416 416
 <p>
417 417
 <code>new-todo</code> is fairly trivial. It's main feature is that it has to
... ...
@@ -421,7 +421,7 @@ properly. <code>new-todo</code> backs POST requests to the root endpoint.
421 421
 </p>
422 422
 
423 423
 <div class="org-src-container">
424
-<pre class="src src-lisp" id="org6d3c13a"><span style="color: #8c8c8c;">(</span><span style="color: #F0DFAF;">defvar</span> <span style="color: #DC8CC3;">*external-host*</span>
424
+<pre class="src src-lisp" id="orgc417af0"><span style="color: #8c8c8c;">(</span><span style="color: #F0DFAF;">defvar</span> <span style="color: #DC8CC3;">*external-host*</span>
425 425
   <span style="color: #D0BF8F;">"localhost"</span><span style="color: #8c8c8c;">)</span>
426 426
 <span style="color: #8c8c8c;">(</span><span style="color: #F0DFAF;">defvar</span> <span style="color: #DC8CC3;">*external-port*</span>
427 427
   5000<span style="color: #8c8c8c;">)</span>
... ...
@@ -433,7 +433,11 @@ properly. <code>new-todo</code> backs POST requests to the root endpoint.
433 433
            <span style="color: #aebed8;">(</span>rutilsx.threading:-&gt;&gt;
434 434
             value
435 435
             <span style="color: #b0b0b3;">(</span>acons <span style="color: #D0BF8F;">"completed"</span> 'yason:false<span style="color: #b0b0b3;">)</span>
436
-            <span style="color: #b0b0b3;">(</span>acons <span style="color: #D0BF8F;">"url"</span> <span style="color: #90a890;">(</span>format nil <span style="color: #D0BF8F;">"http://~a:~d/todo/~d"</span> *external-host* *external-port* id<span style="color: #90a890;">)</span><span style="color: #b0b0b3;">)</span><span style="color: #aebed8;">)</span>
436
+            <span style="color: #b0b0b3;">(</span>acons <span style="color: #D0BF8F;">"url"</span>
437
+                   <span style="color: #90a890;">(</span>format nil <span style="color: #D0BF8F;">"http://~a:~d/todo/~d"</span>
438
+                           *external-host*
439
+                           *external-port*
440
+                           id<span style="color: #90a890;">)</span><span style="color: #b0b0b3;">)</span><span style="color: #aebed8;">)</span>
437 441
            <span style="font-weight: bold;">:test</span> 'equal<span style="color: #97b098;">)</span><span style="color: #b0b1a3;">)</span><span style="color: #93a8c6;">)</span><span style="color: #8c8c8c;">)</span>
438 442
 </pre>
439 443
 </div>
... ...
@@ -446,22 +450,23 @@ todo endpoint for a specific ID.
446 450
 </p>
447 451
 
448 452
 <div class="org-src-container">
449
-<pre class="src src-lisp" id="org417fe1b"><span style="color: #8c8c8c;">(</span><span style="color: #F0DFAF;">defun</span> <span style="color: #8CD0D3;">update-todo</span> <span style="color: #93a8c6;">(</span>id v<span style="color: #93a8c6;">)</span>
450
-  <span style="color: #93a8c6;">(</span>setf <span style="color: #b0b1a3;">(</span>todo id<span style="color: #b0b1a3;">)</span>
451
-        <span style="color: #b0b1a3;">(</span>serapeum:merge-tables <span style="color: #97b098;">(</span>or <span style="color: #aebed8;">(</span>todo id<span style="color: #aebed8;">)</span>
452
-                                   <span style="color: #aebed8;">(</span>make-hash-table <span style="font-weight: bold;">:test</span> 'equal<span style="color: #aebed8;">)</span><span style="color: #97b098;">)</span>
453
-                               <span style="color: #97b098;">(</span>data-lens.lenses:over *completed-lens*
454
-                                                      'bool-to-yason
455
-                                                      <span style="color: #aebed8;">(</span>alexandria:alist-hash-table
456
-                                                       v
457
-                                                       <span style="font-weight: bold;">:test</span> 'equal<span style="color: #aebed8;">)</span><span style="color: #97b098;">)</span><span style="color: #b0b1a3;">)</span><span style="color: #93a8c6;">)</span><span style="color: #8c8c8c;">)</span>
453
+<pre class="src src-lisp" id="orga2be00f"><span style="color: #8c8c8c;">(</span><span style="color: #F0DFAF;">defun</span> <span style="color: #8CD0D3;">update-todo</span> <span style="color: #93a8c6;">(</span>id v<span style="color: #93a8c6;">)</span>
454
+  <span style="color: #93a8c6;">(</span><span style="color: #F0DFAF;">let*</span> <span style="color: #b0b1a3;">(</span><span style="color: #97b098;">(</span>old-todo <span style="color: #aebed8;">(</span>or <span style="color: #b0b0b3;">(</span>todo id<span style="color: #b0b0b3;">)</span>
455
+                       <span style="color: #b0b0b3;">(</span>make-hash-table <span style="font-weight: bold;">:test</span> 'equal<span style="color: #b0b0b3;">)</span><span style="color: #aebed8;">)</span><span style="color: #97b098;">)</span>
456
+         <span style="color: #97b098;">(</span>in-hash-table <span style="color: #aebed8;">(</span>alexandria:alist-hash-table v <span style="font-weight: bold;">:test</span> 'equal<span style="color: #aebed8;">)</span><span style="color: #97b098;">)</span>
457
+         <span style="color: #97b098;">(</span>update <span style="color: #aebed8;">(</span>data-lens.lenses:over *completed-lens*
458
+                                        'bool-to-yason
459
+                                        in-hash-table<span style="color: #aebed8;">)</span><span style="color: #97b098;">)</span><span style="color: #b0b1a3;">)</span>
460
+    <span style="color: #b0b1a3;">(</span>setf <span style="color: #97b098;">(</span>todo id<span style="color: #97b098;">)</span>
461
+          <span style="color: #97b098;">(</span>serapeum:merge-tables old-todo
462
+                                 update<span style="color: #97b098;">)</span><span style="color: #b0b1a3;">)</span><span style="color: #93a8c6;">)</span><span style="color: #8c8c8c;">)</span>
458 463
 </pre>
459 464
 </div>
460 465
 </div>
461 466
 </div>
462 467
 
463
-<div id="outline-container-org09e92d6" class="outline-3">
464
-<h3 id="org09e92d6"><span class="section-number-3">2.4</span> Examples</h3>
468
+<div id="outline-container-org87b91ac" class="outline-3">
469
+<h3 id="org87b91ac"><span class="section-number-3">2.4</span> Examples</h3>
465 470
 <div class="outline-text-3" id="text-2-4">
466 471
 <div class="org-src-container">
467 472
 <pre class="src src-lisp"><span style="color: #8c8c8c;">(</span><span style="color: #F0DFAF;">in-package</span> <span style="font-weight: bold;">:fwoar.todo</span><span style="color: #8c8c8c;">)</span>
... ...
@@ -476,10 +481,10 @@ todo endpoint for a specific ID.
476 481
 </div>
477 482
 
478 483
 <pre class="example">
479
-(#&lt;hash-table "url": "http://localhost:5000/todo/163",
484
+(#&lt;hash-table "url": "http://localhost:5000/todo/175",
480 485
               "title": "get groceries",
481 486
               "completed": YASON:FALSE&gt;
482
- #&lt;hash-table "url": "http://localhost:5000/todo/164",
487
+ #&lt;hash-table "url": "http://localhost:5000/todo/176",
483 488
               "title": "write-better-documentation",
484 489
               "completed": YASON:FALSE&gt;)
485 490
 </pre>
... ...
@@ -488,12 +493,12 @@ todo endpoint for a specific ID.
488 493
 </div>
489 494
 
490 495
 
491
-<div id="outline-container-orgf023b98" class="outline-2">
492
-<h2 id="orgf023b98"><span class="section-number-2">3</span> Routing</h2>
496
+<div id="outline-container-org6a09bc1" class="outline-2">
497
+<h2 id="org6a09bc1"><span class="section-number-2">3</span> Routing</h2>
493 498
 <div class="outline-text-2" id="text-3">
494 499
 </div>
495
-<div id="outline-container-org62738a5" class="outline-3">
496
-<h3 id="org62738a5"><span class="section-number-3">3.1</span> Routing utilities</h3>
500
+<div id="outline-container-org20ffa7f" class="outline-3">
501
+<h3 id="org20ffa7f"><span class="section-number-3">3.1</span> Routing utilities</h3>
497 502
 <div class="outline-text-3" id="text-3-1">
498 503
 <p>
499 504
 The core utility here is the <code>defroutes</code> macro.  This takes a
... ...
@@ -503,7 +508,7 @@ routes.
503 508
 </p>
504 509
 
505 510
 <div class="org-src-container">
506
-<pre class="src src-lisp" id="org2c08451"><span style="color: #8c8c8c;">(</span><span style="color: #F0DFAF;">defmacro</span> <span style="color: #8CD0D3;">defroutes</span> <span style="color: #93a8c6;">(</span>app <span style="color: #CC9393;">&amp;body</span> routes<span style="color: #93a8c6;">)</span>
511
+<pre class="src src-lisp" id="org95e4a72"><span style="color: #8c8c8c;">(</span><span style="color: #F0DFAF;">defmacro</span> <span style="color: #8CD0D3;">defroutes</span> <span style="color: #93a8c6;">(</span>app <span style="color: #CC9393;">&amp;body</span> routes<span style="color: #93a8c6;">)</span>
507 512
   <span style="color: #93a8c6;">(</span>alexandria:once-only <span style="color: #b0b1a3;">(</span>app<span style="color: #b0b1a3;">)</span>
508 513
     `<span style="color: #b0b1a3;">(</span>setf
509 514
       ,@<span style="color: #97b098;">(</span><span style="color: #F0DFAF;">loop</span> for <span style="color: #aebed8;">(</span>target . descriptors<span style="color: #aebed8;">)</span> in routes
... ...
@@ -532,14 +537,14 @@ a list of verbs <code>(:GET :POST)</code> in the head of each handler clause.
532 537
 
533 538
 
534 539
 <pre class="example">
535
-(LET ((#:APP1876 APP))
536
-  (SETF (NINGLE/APP:ROUTE #:APP1876 "/" :METHOD METHOD)
540
+(LET ((#:APP1882 APP))
541
+  (SETF (NINGLE/APP:ROUTE #:APP1882 "/" :METHOD METHOD)
537 542
           (HANDLER NIL
538 543
             (TODOS))
539
-        (NINGLE/APP:ROUTE #:APP1876 "/" :METHOD METHOD)
544
+        (NINGLE/APP:ROUTE #:APP1882 "/" :METHOD METHOD)
540 545
           (HANDLER (V)
541 546
             (NEW-TODO V))
542
-        (NINGLE/APP:ROUTE #:APP1876 "/" :METHOD METHOD)
547
+        (NINGLE/APP:ROUTE #:APP1882 "/" :METHOD METHOD)
543 548
           (HANDLER NIL
544 549
             (CLEAR-TODOS))))
545 550
 T
... ...
@@ -553,7 +558,7 @@ that all the API results get JSON encoded.
553 558
 </p>
554 559
 
555 560
 <div class="org-src-container">
556
-<pre class="src src-lisp" id="org21fec3a"><span style="color: #8c8c8c;">(</span><span style="color: #F0DFAF;">defun</span> <span style="color: #8CD0D3;">success</span> <span style="color: #93a8c6;">(</span>value<span style="color: #93a8c6;">)</span>
561
+<pre class="src src-lisp" id="orgb9cfd08"><span style="color: #8c8c8c;">(</span><span style="color: #F0DFAF;">defun</span> <span style="color: #8CD0D3;">success</span> <span style="color: #93a8c6;">(</span>value<span style="color: #93a8c6;">)</span>
557 562
   <span style="color: #93a8c6;">(</span>list 200 '<span style="color: #b0b1a3;">(</span><span style="font-weight: bold;">:conent-type</span> <span style="color: #D0BF8F;">"application/json"</span><span style="color: #b0b1a3;">)</span> value<span style="color: #93a8c6;">)</span><span style="color: #8c8c8c;">)</span>
558 563
 
559 564
 <span style="color: #8c8c8c;">(</span><span style="color: #F0DFAF;">defmacro</span> <span style="color: #8CD0D3;">handler</span> <span style="color: #93a8c6;">(</span><span style="color: #b0b1a3;">(</span><span style="color: #CC9393;">&amp;optional</span> <span style="color: #97b098;">(</span>sym <span style="color: #aebed8;">(</span>gensym <span style="color: #D0BF8F;">"PARAMS"</span><span style="color: #aebed8;">)</span><span style="color: #97b098;">)</span><span style="color: #b0b1a3;">)</span> <span style="color: #CC9393;">&amp;body</span> body<span style="color: #93a8c6;">)</span>
... ...
@@ -567,8 +572,8 @@ that all the API results get JSON encoded.
567 572
 </div>
568 573
 </div>
569 574
 
570
-<div id="outline-container-org9f65218" class="outline-3">
571
-<h3 id="org9f65218"><span class="section-number-3">3.2</span> todo routes</h3>
575
+<div id="outline-container-org7bdd028" class="outline-3">
576
+<h3 id="org7bdd028"><span class="section-number-3">3.2</span> todo routes</h3>
572 577
 <div class="outline-text-3" id="text-3-2">
573 578
 <p>
574 579
 <code>setup-routes</code> binds the endpoints to handlers: <code>"/"</code> to handlers
... ...
@@ -580,7 +585,7 @@ alist. <code>get-id</code> handles this, and extracts an integer for the id
580 585
 </p>
581 586
 
582 587
 <div class="org-src-container">
583
-<pre class="src src-lisp" id="org2d99b0f"><span style="color: #A6A689; background-color: #2B2B2B;">;; </span><span style="color: #A6A689; background-color: #2B2B2B;">routing</span>
588
+<pre class="src src-lisp" id="org1538a61"><span style="color: #A6A689; background-color: #2B2B2B;">;; </span><span style="color: #A6A689; background-color: #2B2B2B;">routing</span>
584 589
 <span style="color: #8c8c8c;">(</span><span style="color: #F0DFAF;">defun</span> <span style="color: #8CD0D3;">get-id</span> <span style="color: #93a8c6;">(</span>params<span style="color: #93a8c6;">)</span>
585 590
   <span style="color: #93a8c6;">(</span>parse-integer <span style="color: #b0b1a3;">(</span>serapeum:assocdr <span style="font-weight: bold;">:id</span> params<span style="color: #b0b1a3;">)</span><span style="color: #93a8c6;">)</span><span style="color: #8c8c8c;">)</span>
586 591
 
... ...
@@ -602,12 +607,12 @@ alist. <code>get-id</code> handles this, and extracts an integer for the id
602 607
 </div>
603 608
 </div>
604 609
 
605
-<div id="outline-container-org5597baf" class="outline-2">
606
-<h2 id="org5597baf"><span class="section-number-2">4</span> Source</h2>
610
+<div id="outline-container-orgd46ec32" class="outline-2">
611
+<h2 id="orgd46ec32"><span class="section-number-2">4</span> Source</h2>
607 612
 <div class="outline-text-2" id="text-4">
608 613
 </div>
609
-<div id="outline-container-org80852ef" class="outline-3">
610
-<h3 id="org80852ef"><span class="section-number-3">4.1</span> model.lisp source code</h3>
614
+<div id="outline-container-org9c84f34" class="outline-3">
615
+<h3 id="org9c84f34"><span class="section-number-3">4.1</span> model.lisp source code</h3>
611 616
 <div class="outline-text-3" id="text-4-1">
612 617
 <div class="org-src-container">
613 618
 <pre class="src src-lisp"><span style="color: #A6A689; background-color: #2B2B2B;">;; </span><span style="color: #A6A689; background-color: #2B2B2B;">[[file:~/git_repos/lisp-sandbox/todo/README.org::package-include][package-include]]</span>
... ...
@@ -670,20 +675,25 @@ alist. <code>get-id</code> handles this, and extracts an integer for the id
670 675
            <span style="color: #aebed8;">(</span>rutilsx.threading:-&gt;&gt;
671 676
             value
672 677
             <span style="color: #b0b0b3;">(</span>acons <span style="color: #D0BF8F;">"completed"</span> 'yason:false<span style="color: #b0b0b3;">)</span>
673
-            <span style="color: #b0b0b3;">(</span>acons <span style="color: #D0BF8F;">"url"</span> <span style="color: #90a890;">(</span>format nil <span style="color: #D0BF8F;">"http://~a:~d/todo/~d"</span> *external-host* *external-port* id<span style="color: #90a890;">)</span><span style="color: #b0b0b3;">)</span><span style="color: #aebed8;">)</span>
678
+            <span style="color: #b0b0b3;">(</span>acons <span style="color: #D0BF8F;">"url"</span>
679
+                   <span style="color: #90a890;">(</span>format nil <span style="color: #D0BF8F;">"http://~a:~d/todo/~d"</span>
680
+                           *external-host*
681
+                           *external-port*
682
+                           id<span style="color: #90a890;">)</span><span style="color: #b0b0b3;">)</span><span style="color: #aebed8;">)</span>
674 683
            <span style="font-weight: bold;">:test</span> 'equal<span style="color: #97b098;">)</span><span style="color: #b0b1a3;">)</span><span style="color: #93a8c6;">)</span><span style="color: #8c8c8c;">)</span>
675 684
 <span style="color: #A6A689; background-color: #2B2B2B;">;; </span><span style="color: #A6A689; background-color: #2B2B2B;">new-todo ends here</span>
676 685
 
677 686
 <span style="color: #A6A689; background-color: #2B2B2B;">;; </span><span style="color: #A6A689; background-color: #2B2B2B;">[[file:~/git_repos/lisp-sandbox/todo/README.org::update-todo][update-todo]]</span>
678 687
 <span style="color: #8c8c8c;">(</span><span style="color: #F0DFAF;">defun</span> <span style="color: #8CD0D3;">update-todo</span> <span style="color: #93a8c6;">(</span>id v<span style="color: #93a8c6;">)</span>
679
-  <span style="color: #93a8c6;">(</span>setf <span style="color: #b0b1a3;">(</span>todo id<span style="color: #b0b1a3;">)</span>
680
-        <span style="color: #b0b1a3;">(</span>serapeum:merge-tables <span style="color: #97b098;">(</span>or <span style="color: #aebed8;">(</span>todo id<span style="color: #aebed8;">)</span>
681
-                                   <span style="color: #aebed8;">(</span>make-hash-table <span style="font-weight: bold;">:test</span> 'equal<span style="color: #aebed8;">)</span><span style="color: #97b098;">)</span>
682
-                               <span style="color: #97b098;">(</span>data-lens.lenses:over *completed-lens*
683
-                                                      'bool-to-yason
684
-                                                      <span style="color: #aebed8;">(</span>alexandria:alist-hash-table
685
-                                                       v
686
-                                                       <span style="font-weight: bold;">:test</span> 'equal<span style="color: #aebed8;">)</span><span style="color: #97b098;">)</span><span style="color: #b0b1a3;">)</span><span style="color: #93a8c6;">)</span><span style="color: #8c8c8c;">)</span>
688
+  <span style="color: #93a8c6;">(</span><span style="color: #F0DFAF;">let*</span> <span style="color: #b0b1a3;">(</span><span style="color: #97b098;">(</span>old-todo <span style="color: #aebed8;">(</span>or <span style="color: #b0b0b3;">(</span>todo id<span style="color: #b0b0b3;">)</span>
689
+                       <span style="color: #b0b0b3;">(</span>make-hash-table <span style="font-weight: bold;">:test</span> 'equal<span style="color: #b0b0b3;">)</span><span style="color: #aebed8;">)</span><span style="color: #97b098;">)</span>
690
+         <span style="color: #97b098;">(</span>in-hash-table <span style="color: #aebed8;">(</span>alexandria:alist-hash-table v <span style="font-weight: bold;">:test</span> 'equal<span style="color: #aebed8;">)</span><span style="color: #97b098;">)</span>
691
+         <span style="color: #97b098;">(</span>update <span style="color: #aebed8;">(</span>data-lens.lenses:over *completed-lens*
692
+                                        'bool-to-yason
693
+                                        in-hash-table<span style="color: #aebed8;">)</span><span style="color: #97b098;">)</span><span style="color: #b0b1a3;">)</span>
694
+    <span style="color: #b0b1a3;">(</span>setf <span style="color: #97b098;">(</span>todo id<span style="color: #97b098;">)</span>
695
+          <span style="color: #97b098;">(</span>serapeum:merge-tables old-todo
696
+                                 update<span style="color: #97b098;">)</span><span style="color: #b0b1a3;">)</span><span style="color: #93a8c6;">)</span><span style="color: #8c8c8c;">)</span>
687 697
 <span style="color: #A6A689; background-color: #2B2B2B;">;; </span><span style="color: #A6A689; background-color: #2B2B2B;">update-todo ends here</span>
688 698
 
689 699
 <span style="color: #8c8c8c;">(</span><span style="color: #F0DFAF;">defmacro</span> <span style="color: #8CD0D3;">with-fresh-todos</span> <span style="color: #93a8c6;">(</span><span style="color: #b0b1a3;">()</span> <span style="color: #CC9393;">&amp;body</span> body<span style="color: #93a8c6;">)</span>
... ...
@@ -694,8 +704,8 @@ alist. <code>get-id</code> handles this, and extracts an integer for the id
694 704
 </div>
695 705
 </div>
696 706
 
697
-<div id="outline-container-orgde4e27d" class="outline-3">
698
-<h3 id="orgde4e27d"><span class="section-number-3">4.2</span> routing.lisp source</h3>
707
+<div id="outline-container-org76ec19a" class="outline-3">
708
+<h3 id="org76ec19a"><span class="section-number-3">4.2</span> routing.lisp source</h3>
699 709
 <div class="outline-text-3" id="text-4-2">
700 710
 <div class="org-src-container">
701 711
 <pre class="src src-lisp"><span style="color: #A6A689; background-color: #2B2B2B;">;; </span><span style="color: #A6A689; background-color: #2B2B2B;">[[file:~/git_repos/lisp-sandbox/todo/README.org::package-include][package-include]]</span>
... ...
@@ -749,8 +759,8 @@ alist. <code>get-id</code> handles this, and extracts an integer for the id
749 759
 </div>
750 760
 </div>
751 761
 
752
-<div id="outline-container-org76a7993" class="outline-3">
753
-<h3 id="org76a7993"><span class="section-number-3">4.3</span> main.lisp source</h3>
762
+<div id="outline-container-org98907a6" class="outline-3">
763
+<h3 id="org98907a6"><span class="section-number-3">4.3</span> main.lisp source</h3>
754 764
 <div class="outline-text-3" id="text-4-3">
755 765
 <div class="org-src-container">
756 766
 <pre class="src src-lisp"><span style="color: #8c8c8c;">(</span><span style="color: #F0DFAF;">in-package</span> <span style="font-weight: bold;">:fwoar.todo</span><span style="color: #8c8c8c;">)</span>
... ...
@@ -796,7 +806,7 @@ alist. <code>get-id</code> handles this, and extracts an integer for the id
796 806
 </div>
797 807
 <div id="postamble" class="status">
798 808
 <p class="author">Author: Langley</p>
799
-<p class="date">Created: 2019-08-30 Fri 03:12</p>
809
+<p class="date">Created: 2019-08-30 Fri 16:33</p>
800 810
 <p class="validation"><a href="http://validator.w3.org/check?uri=referer">Validate</a></p>
801 811
 </div>
802 812
 </body>
... ...
@@ -59,20 +59,25 @@
59 59
            (rutilsx.threading:->>
60 60
             value
61 61
             (acons "completed" 'yason:false)
62
-            (acons "url" (format nil "http://~a:~d/todo/~d" *external-host* *external-port* id)))
62
+            (acons "url"
63
+                   (format nil "http://~a:~d/todo/~d"
64
+                           *external-host*
65
+                           *external-port*
66
+                           id)))
63 67
            :test 'equal))))
64 68
 ;; new-todo ends here
65 69
 
66 70
 ;; [[file:~/git_repos/lisp-sandbox/todo/README.org::update-todo][update-todo]]
67 71
 (defun update-todo (id v)
68
-  (setf (todo id)
69
-        (serapeum:merge-tables (or (todo id)
70
-                                   (make-hash-table :test 'equal))
71
-                               (data-lens.lenses:over *completed-lens*
72
-                                                      'bool-to-yason
73
-                                                      (alexandria:alist-hash-table
74
-                                                       v
75
-                                                       :test 'equal)))))
72
+  (let* ((old-todo (or (todo id)
73
+                       (make-hash-table :test 'equal)))
74
+         (in-hash-table (alexandria:alist-hash-table v :test 'equal))
75
+         (update (data-lens.lenses:over *completed-lens*
76
+                                        'bool-to-yason
77
+                                        in-hash-table)))
78
+    (setf (todo id)
79
+          (serapeum:merge-tables old-todo
80
+                                 update))))
76 81
 ;; update-todo ends here
77 82
 
78 83
 (defmacro with-fresh-todos (() &body body)