Acme-CPANModulesBundle-Import-MojoliciousAdvent-2017

 view release on metacpan or  search on metacpan

MANIFEST  view on Meta::CPAN

devdata/https_mojolicious.io_blog_2017_12_06_day-6-adding-your-own-commands
devdata/https_mojolicious.io_blog_2017_12_07_day-7-using-template-variants-for-a-beta-landing-page
devdata/https_mojolicious.io_blog_2017_12_08_day-8-mocking-a-rest-api
devdata/https_mojolicious.io_blog_2017_12_09_day-9-the-best-way-to-test
devdata/https_mojolicious.io_blog_2017_12_10_day-10-give-the-customer-what-they-want
devdata/https_mojolicious.io_blog_2017_12_11_day-11-useragent-content-generators
devdata/https_mojolicious.io_blog_2017_12_12_day-12-more-than-a-base-class
devdata/https_mojolicious.io_blog_2017_12_13_day-13-more-about-roles
devdata/https_mojolicious.io_blog_2017_12_14_day-14-you-promised-to-call
devdata/https_mojolicious.io_blog_2017_12_15_day-15-start-a-new-yancy-app
devdata/https_mojolicious.io_blog_2017_12_16_day-16-the-secret-life-of-sessions
devdata/https_mojolicious.io_blog_2017_12_17_day-17-the-wishlist-app
devdata/https_mojolicious.io_blog_2017_12_18_day-18-the-wishlist-model
devdata/https_mojolicious.io_blog_2017_12_19_day-19-make-your-app-installable
devdata/https_mojolicious.io_blog_2017_12_20_day-20-practical-testing
devdata/https_mojolicious.io_blog_2017_12_21_day-21-virtually-a-lumberjack
devdata/https_mojolicious.io_blog_2017_12_22_day-22-how-to-build-a-public-rest-api
devdata/https_mojolicious.io_blog_2017_12_23_day-23-one-liners-for-fun-and-profit
devdata/https_mojolicious.io_blog_2017_12_24_day-24-release-and-wrap-up
devscripts/update
dist.ini

devdata/https_mojolicious.io_blog_2017_12_01_day-1-getting-started  view on Meta::CPAN


            </div>

              <div class="post-thumb">
                <!-- theme suggests 1300x500 -->
                <img alt="hot air ballons" src="/blog/2017/12/01/day-1-getting-started/1280px-Colorado_Springs_Hot_Air_Balloon_Competition.jpg">
              </div>

            <div class="post-content">

              <section id="section-1">
                  <h2>Start at the Beginning</h2>

<p>In this Advent Calendar series, some posts will be introductory, some will be advanced, some will be on new features.
Who knows what could be next?
But for now let&#39;s ensure a level playing field by working out how to get started.</p>

              </section>
              <section id="section-2">
                  <h2>What is Mojolicious?</h2>

<p>Well, <a href="http://mojolicious.org">Mojolicious</a> is really two things.
First it is a powerful web-focused toolkit called Mojo.
Second it is a powerful web framework called Mojolicious.
The Mojolicious framework is built using the Mojo toolkit.</p>

<p>That that doesn&#39;t mean you can&#39;t use Mojo tools elsewhere.
If you see some tools you like but want to use with some other framework, go ahead, I won&#39;t tell!
Use it in any Perl code you want!</p>

devdata/https_mojolicious.io_blog_2017_12_01_day-1-getting-started  view on Meta::CPAN

<p>Shoot I wasn&#39;t going to mention Perl!
Yes, Mojolicious is written in Perl.
Don&#39;t let that scare you.
It has tons of ways to keep you and your code safe!
From a built-in object system to a consistent API with chainable methods, Mojolicious is designed to keep your code clean and readable.
Hopefully you&#39;ll even have some fun using it!</p>

<h2>Installation</h2>

<p>Installation is easy and fast.
In fact, if you set the test harness to run in parallel, it should install in seconds!
You can do that by setting <code>HARNESS_OPTIONS=j9</code> in your environment (where <code>9</code> is one more than your number of cores).</p>

<p>The easiest way to install is to run</p>

<pre><code>curl -L https://cpanmin.us | perl - -M https://cpan.metacpan.org -n Mojolicious
</code></pre>

<p>or, you can install using any cpan client (we like <a href="https://metacpan.org/pod/App::cpanminus"><code>cpanm</code></a>) or using your system&#39;s package manager.</p>

<h2>Your First Application</h2>

devdata/https_mojolicious.io_blog_2017_12_01_day-1-getting-started  view on Meta::CPAN

<p>When it starts it should tell you to visit <code>http://127.0.0.1:3000</code>.
Open that url in your browser.
Your first advent treat should be waiting for you!</p>

<h2>Getting Help</h2>

<p>The documentation is available at <a href="http://mojolicious.org/perldoc">http://mojolicious.org/perldoc</a>.
You are especially encouraged to read the Tutorial and Guides in the order suggested there.</p>

<p>Read it carefully, unlike some documentation, it is written for brevity and conciseness.
Users accustomed to skimming documentation filled with fluff might need a second take.</p>

<p>If you still have trouble, we have a mailing list and an IRC channel ready to help!
Find us at <a href="http://mojolicious.org/perldoc#SUPPORT">http://mojolicious.org/perldoc#SUPPORT</a>!</p>

              </section>
              <small><p><a href="https://commons.wikimedia.org/wiki/File:Colorado_Springs_Hot_Air_Balloon_Competition.jpg">Image by DarlArthurS</a> licensed under the <a class="extiw" href="https://en.wikipedia.org/wiki/en:Creative_Commons" title="w:...
</small>

              <p class="tags">
                <span>Tagged in </span>:
                  <a href="/blog/tag/advent/">advent</a>,
                  <a href="/blog/tag/installing/">installing</a>,
                  <a href="/blog/tag/hello-world/">hello world</a>,
                  <a href="/blog/tag/lite/">lite</a>
              </p>


                  <div class="bio cf">

                      <div class="gravatar">
                        <img alt="author image" src="https://secure.gravatar.com/avatar/cc767569f5863a7c261991ee5b23f147">
                      </div>
                      <div class="about">
                        <h5>Joel Berger</h5>
                        <p>Joel has Ph.D. in Physics from the University of Illinois at Chicago.
He an avid Perl user and <a href="https://metacpan.org/author/JBERGER">author</a> and is a member of the Mojolicious Core Team.</p>

                      </div>

                  </div>

devdata/https_mojolicious.io_blog_2017_12_01_day-1-getting-started  view on Meta::CPAN

                  <li class="next"><a href="/blog/2017/12/02/day-2-the-stash/index.html" rel="next"><strong>Next Article</strong> Day 2: The Stash </a></li>
              </ul>

            </div>

        </article>


      </div>

      <div class="four columns end" id="secondary">
        <aside id="sidebar">
          







<div class="widget widget_tag_cloud">

devdata/https_mojolicious.io_blog_2017_12_02_day-2-the-stash  view on Meta::CPAN


            </div>

              <div class="post-thumb">
                <!-- theme suggests 1300x500 -->
                <img alt="leather bag" src="/blog/2017/12/02/day-2-the-stash/bag-1854148_1920.jpg">
              </div>

            <div class="post-content">

              <section id="section-1">
                  <p>In Mojolicious, when processing a request and preparing a response one of the most important concepts is &quot;the stash&quot;.
Since it is a non-blocking framework, your code can&#39;t use global variables to store any state during processing.
If you did and some other code were to run, it could very easily get cross-talk between requests.</p>

<p>The stash is the place you can store information while you process it.
It is just a simple hash reference that is attached to the controller object that is processing the request.
It lives and dies with that one transaction.</p>

<p>While you can and should use it as a scratchpad, it really is much more.
The stash controls almost every aspect of the response that you generate.
Let&#39;s look a little closer to see how it works</p>

              </section>
              <section id="section-2">
                  <h2>Using the Stash for Rendering Text</h2>

<p>In the previous post, we discussed the most simple &#39;Hello world&#39; application.</p>

<pre><code>use Mojolicious::Lite;
get &#39;/&#39; =&gt; {text =&gt; &#39;Hello 🌍 World!&#39;};
app-&gt;start;
</code></pre>

<p>While that is a very simple working case, a more common example would look like</p>

devdata/https_mojolicious.io_blog_2017_12_02_day-2-the-stash  view on Meta::CPAN

Here is the previous example using an &quot;inline template&quot;.</p>

<pre><code>use Mojolicious::Lite;
get &#39;/:name&#39; =&gt; {name =&gt; &#39;🌍 world!&#39;} =&gt; sub {
  my $c = shift;
  $c-&gt;stash(inline =&gt; &#39;hello &lt;%= $name %&gt;&#39;);
};
app-&gt;start;
</code></pre>

<p>Or if you&#39;ll let me use a concept without fully introducing it, here is a template in the data section of your script.</p>

<pre><code>use Mojolicious::Lite;
get &#39;/:name&#39; =&gt; {name =&gt; &#39;🌍 world!&#39;} =&gt; sub {
  my $c = shift;
  $c-&gt;render(&#39;hello&#39;);
};
app-&gt;start;

__DATA__

devdata/https_mojolicious.io_blog_2017_12_02_day-2-the-stash  view on Meta::CPAN

<pre><code>use Mojolicious::Lite;
get &#39;/&#39; =&gt; {text =&gt; &#39;hello 🌍 world!&#39;, format =&gt; &#39;txt&#39;};
app-&gt;start;
</code></pre>

<p>Where the understood formats are listed <a href="http://mojolicious.org/perldoc/Mojolicious/Types#DESCRIPTION">here</a> (and more <a href="http://mojolicious.org/perldoc/Mojolicious/Types#DESCRIPTION">can be added</a>).</p>

<p>The others all have meanings, some of which you can probably figure out on your own, but this post has gone on long enough.
Those others will have to wait for another day.</p>

              </section>
              <small><p><a href="https://pixabay.com/en/bag-classic-leather-messenger-bag-1854148/">Image</a> in the Public Domain.</p>
</small>

              <p class="tags">
                <span>Tagged in </span>:
                  <a href="/blog/tag/advent/">advent</a>,
                  <a href="/blog/tag/hello-world/">hello world</a>,
                  <a href="/blog/tag/lite/">lite</a>,
                  <a href="/blog/tag/rendering/">rendering</a>
              </p>


                  <div class="bio cf">

                      <div class="gravatar">
                        <img alt="author image" src="https://secure.gravatar.com/avatar/cc767569f5863a7c261991ee5b23f147">
                      </div>
                      <div class="about">
                        <h5>Joel Berger</h5>
                        <p>Joel has Ph.D. in Physics from the University of Illinois at Chicago.
He an avid Perl user and <a href="https://metacpan.org/author/JBERGER">author</a> and is a member of the Mojolicious Core Team.</p>

                      </div>

                  </div>

devdata/https_mojolicious.io_blog_2017_12_02_day-2-the-stash  view on Meta::CPAN

                  <li class="next"><a href="/blog/2017/12/03/day-3-using-named-routes/index.html" rel="next"><strong>Next Article</strong> Day 3: Using Named Routes </a></li>
              </ul>

            </div>

        </article>


      </div>

      <div class="four columns end" id="secondary">
        <aside id="sidebar">
          







<div class="widget widget_tag_cloud">

devdata/https_mojolicious.io_blog_2017_12_03_day-3-using-named-routes  view on Meta::CPAN


            </div>

              <div class="post-thumb">
                <!-- theme suggests 1300x500 -->
                <img alt="&quot;my name is&quot; stickers" src="/blog/2017/12/03/day-3-using-named-routes/my_name_is.jpg">
              </div>

            <div class="post-content">

              <section id="section-1">
                  <p>One of the things we know from years of programming is that you should never hard-code anything if you don&#39;t have to.
And yet far too many web application hard-code their urls, especially internal ones.
But what if you didn&#39;t have to?</p>

<p>Each Mojolicious route has its own <a href="http://mojolicious.org/perldoc/Mojolicious/Guides/Routing#Named-routes">name</a> which can be used to generate urls.
If you don&#39;t specify one, one is generated, but you shouldn&#39;t rely on that name, give it one that is meaningful and relevant to your purposes.
In lite apps, the name is the last parameter, after any defaults or callbacks.
(In a full app it is an attribute, but we&#39;ll talk about those in another post).</p>

<p>Then when you need a url, rather than hard-coding it, use <a href="http://mojolicious.org/perldoc/Mojolicious/Controller#url_for"><code>url_for</code></a> or related functionality to generate a url by name, you can even pass placeholder values if ...
Let&#39;s see how it works!</p>

              </section>
              <section id="section-2">
                  <h2>The North Pole Homepage</h2>

<p>Santa started out with a simple webapp.
It just had a main page and a page for him and his employees.
Since it was so simple, he didn&#39;t have any deeper paths, just <code>/</code> for the homepage and <code>/:name</code> for staff pages.
Of course what I&#39;m going to show you is a simplification, I can&#39;t show you Santa&#39;s full site, for obvious reasons.</p>

<pre><code>use Mojolicious::Lite;

get &#39;/:name&#39; =&gt; {template =&gt; &#39;staff&#39;} =&gt; &#39;staff&#39;;

devdata/https_mojolicious.io_blog_2017_12_03_day-3-using-named-routes  view on Meta::CPAN

<pre><code>get &#39;/toy/:toy_name&#39; =&gt; &#39;toy&#39;;
get &#39;/meet/:name&#39; =&gt; &#39;staff&#39;;
get &#39;/&#39; =&gt; &#39;home&#39;;
</code></pre>

<p>While some people appreciate that feature, I personally like to be explicit about which template I want.
I also like to separate concerns.
Anyway, you can choose whichever you like best.
After all, there&#39;s more than one way to do it!</p>

              </section>
              <small><p><a href="https://flickr.com/photos/94599716@N06/15283079263">Image</a> by <a href="https://www.flickr.com/people/94599716@N06">Travis Wise</a> licensed under the <a class="extiw" href="https://en.wikipedia.org/wiki/en:Creative...
</small>

              <p class="tags">
                <span>Tagged in </span>:
                  <a href="/blog/tag/advent/">advent</a>,
                  <a href="/blog/tag/lite/">lite</a>,
                  <a href="/blog/tag/routing/">routing</a>
              </p>


                  <div class="bio cf">

                      <div class="gravatar">
                        <img alt="author image" src="https://secure.gravatar.com/avatar/cc767569f5863a7c261991ee5b23f147">
                      </div>
                      <div class="about">
                        <h5>Joel Berger</h5>
                        <p>Joel has Ph.D. in Physics from the University of Illinois at Chicago.
He an avid Perl user and <a href="https://metacpan.org/author/JBERGER">author</a> and is a member of the Mojolicious Core Team.</p>

                      </div>

                  </div>

devdata/https_mojolicious.io_blog_2017_12_03_day-3-using-named-routes  view on Meta::CPAN

                  <li class="next"><a href="/blog/2017/12/04/day-4-dont-fear-the-full-app/index.html" rel="next"><strong>Next Article</strong> Day 4: Don&#39;t Fear the Full App </a></li>
              </ul>

            </div>

        </article>


      </div>

      <div class="four columns end" id="secondary">
        <aside id="sidebar">
          







<div class="widget widget_tag_cloud">

devdata/https_mojolicious.io_blog_2017_12_04_day-4-dont-fear-the-full-app  view on Meta::CPAN


            </div>

              <div class="post-thumb">
                <!-- theme suggests 1300x500 -->
                <img alt="Arucaria trees in Curitiba Brazil" src="/blog/2017/12/04/day-4-dont-fear-the-full-app/arucaria.jpg">
              </div>

            <div class="post-content">

              <section id="section-1">
                  <p>One of the most common misconceptions about Mojolicious is that there is a large difference between the declarative &quot;Lite&quot; apps that we have seen so far and large-scale structured &quot;Full&quot; apps.
Nothing could be further from the truth.
<a href="http://mojolicious.org/perldoc/Mojolicious/Lite">Mojolicious::Lite</a> is a very tiny wrapper around the so-called &quot;Full&quot; app architecture, giving it the approachable keyword syntax.</p>

<p>Because it is much nicer to have concise single-file examples for documentation most of Mojolicious&#39; documentation uses Lite syntax most of the time.
It is understandable that people worry about migrating (or as we call it &quot;growing&quot;) even once their apps would benefit from Object-Oriented structure; after all the docs seem geared towards Lite apps.
However, let those fears go, the transition is easy.
And once you understand it, the documentatation examples are trivial to translate.</p>

<p>Plus, Mojolicious comes with two forms of help when transitioning.
The first is the <a href="http://mojolicious.org/perldoc/Mojolicious/Guides/Growing">Growing Guide</a> which covers everything this post will but from the perspective of porting an existing application (which I won&#39;t duplicate here).
The second is the <a href="http://mojolicious.org/perldoc/Mojolicious/Command/inflate">inflate command</a> which can even start you on the process by moving your templates from the data section and into their own files.</p>

<p>That said, in order to futher demystify things, I&#39;m going to cover some of the differences and pull back the curtain on the Lite syntax itself.</p>

              </section>
              <section id="section-2">
                  <h2>Let Me Convince You</h2>

<p>After repeated attempts to convince people that there is very little difference between the two, I&#39;ve found that there is one really great way to turn the conversation.
I show them the code.
No really <a href="https://github.com/kraih/mojo/blob/master/lib/Mojolicious/Lite.pm">take a look</a>.
As of this writing, Mojolicious::Lite is only 37 lines of code (as computed by David A. Wheeler&#39;s <a href="https://www.dwheeler.com/sloccount/">SLOCCount</a>)!
How much difference could there be in 37 lines of code?</p>

<p>Ok now that you believe me, let&#39;s talk about those few differences.</p>

devdata/https_mojolicious.io_blog_2017_12_04_day-4-dont-fear-the-full-app  view on Meta::CPAN

  # /protected/safe
  get &#39;/safe&#39; =&gt; &#39;safe&#39;;
};

get &#39;/another_unsafe&#39; =&gt; ...;
</code></pre>

<h3>Wait, What?</h3>

<p>If you are confused, that&#39;s ok.
I&#39;m going to let you in on a little secret, I think this is confusing too.
The Lite form of nesting routes is really more for completeness, once you need it, it is probably a good sign that you should look at switching to Full apps instead.
Full apps have it much easier!</p>

<p>In a Full app, the route methods all return a new route object.
If you store those in a variable, you can use them to build off of each other.
This is a much more natural API for building nested structures in my opinion.</p>

<pre><code>my $r = $app-&gt;routes;
$r-&gt;get(&#39;/unsafe&#39; =&gt; &#39;unsafe&#39;);

devdata/https_mojolicious.io_blog_2017_12_04_day-4-dont-fear-the-full-app  view on Meta::CPAN


# /protected/safe
$protected-&gt;get(&#39;/safe&#39; =&gt; &#39;safe&#39;);

$r-&gt;get(&#39;/another_unsafe&#39; =&gt; ...);
</code></pre>

<p>Since Lite app keywords don&#39;t have a way to attach to another route, they basically always add them to the &quot;current global route&quot;.
That&#39;s where the confusion comes in.</p>

<p>Speaking of which, I&#39;m going to let you in even deeper on my secret.
I like the chained type of routing so much more than using <code>group</code> that I actually use it in my Lite apps.
Sure I still use <code>app</code> and <code>plugin</code>, but one of the first things I do is <code>my $r = app-&gt;routes</code>.
Then, I use that instead of the routing keywords in all but the simplest of cases.</p>

<h2>Conclusion</h2>

<p>That&#39;s it, with the exception of using <code>group</code> for nested routing, it is just direct translation.
And if you always use the method forms of routing you don&#39;t even need to worry about that!
With that, I encourage you to go back and read the <a href="http://mojolicious.org/perldoc#TUTORIAL">Tutorial and Guides</a> and realize that everything that looks like Lite apps is really just as true for Full ones.</p>

              </section>
              <small><p>Image is copyright (c) 2013 Joel Berger.
It shows a pair of Arucaria trees in the city of Curitiba, during YAPC::Brasil 2013.
It is licensed under a <a href="http://creativecommons.org/licenses/by-sa/4.0/" rel="license">Creative Commons Attribution-ShareAlike 4.0 International License</a>.</p>
</small>

              <p class="tags">
                <span>Tagged in </span>:
                  <a href="/blog/tag/advent/">advent</a>,
                  <a href="/blog/tag/lite/">lite</a>,
                  <a href="/blog/tag/full/">full</a>,
                  <a href="/blog/tag/growing/">growing</a>
              </p>


                  <div class="bio cf">

                      <div class="gravatar">
                        <img alt="author image" src="https://secure.gravatar.com/avatar/cc767569f5863a7c261991ee5b23f147">
                      </div>
                      <div class="about">
                        <h5>Joel Berger</h5>
                        <p>Joel has Ph.D. in Physics from the University of Illinois at Chicago.
He an avid Perl user and <a href="https://metacpan.org/author/JBERGER">author</a> and is a member of the Mojolicious Core Team.</p>

                      </div>

                  </div>

devdata/https_mojolicious.io_blog_2017_12_04_day-4-dont-fear-the-full-app  view on Meta::CPAN

                  <li class="next"><a href="/blog/2017/12/05/day-5-your-apps-built-in-commands/index.html" rel="next"><strong>Next Article</strong> Day 5: Your App&#39;s Built-In Commands </a></li>
              </ul>

            </div>

        </article>


      </div>

      <div class="four columns end" id="secondary">
        <aside id="sidebar">
          







<div class="widget widget_tag_cloud">

devdata/https_mojolicious.io_blog_2017_12_05_day-5-your-apps-built-in-commands  view on Meta::CPAN


            </div>

              <div class="post-thumb">
                <!-- theme suggests 1300x500 -->
                <img alt="Space shuttle Atlantis liftoff" src="/blog/2017/12/05/day-5-your-apps-built-in-commands/1200px-Rocket_prolant.jpg">
              </div>

            <div class="post-content">

              <section id="section-1">
                  <p>I mentioned at the outset of this series that Mojolicious applications are more than just web servers.
I then showed how you can start a web server using the <a href="http://mojolicious.org/perldoc/Mojolicious/Command/daemon"><code>daemon</code></a> or <a href="http://mojolicious.org/perldoc/Mojolicious/Command/prefork"><code>prefork</code></a> comman...
In the previous post, I mentioned an <a href="http://mojolicious.org/perldoc/Mojolicious/Command/inflate"><code>inflate</code></a> command that can help you with growing your app from Lite to Full.</p>

<p>But there are other commands, built right in to your app, that can help you be more productive right away!</p>

              </section>
              <section id="section-2">
                  <h2>Command Basics</h2>

<p>Before I start, I want to briefly discuss the <a href="http://mojolicious.org/perldoc/mojo"><code>mojo</code></a> application/script that comes bundled with the Mojolicious distribution.
This command is a tiny Mojolicious app (actually another &quot;hello world&quot;) which can be thought of as the &quot;null app&quot;.
The built-in commands work both for your application and this null one, so use whichever is more appropriate.
When it doesn&#39;t matter which application runs a command, you can just use <code>mojo</code>.</p>

<p>Each command comes with a one-line description and a (possibly multi-line) usage statement.
To see the available commands, run <code>mojo help</code> and you will see all of the commands and their description.
You should see something like this:</p>

devdata/https_mojolicious.io_blog_2017_12_05_day-5-your-apps-built-in-commands  view on Meta::CPAN

<p>Or just check that the database is reachable.</p>

<pre><code>perl myapp.pl eval -V &#39;app-&gt;pg-&gt;db-&gt;query(&quot;SELECT NOW()&quot;)-&gt;hash&#39;
</code></pre>

<p>These last two database examples assumed that your app was using <a href="http://mojolicious.org/perldoc/Mojo/Pg">Mojo::Pg</a> but similar one-liners could work for any database that your app knows about.</p>

<p>There really is nothing like debugging or administering your application without having to copy and paste a bunch of your logic from your app to some script.
Although if you really find yourself using the <code>eval</code> command for the same tasks often ... well that should wait until tomorrow.</p>

              </section>
              <small><p><a href="https://commons.wikimedia.org/w/index.php?curid=44576486">Image</a> by <a href="//commons.wikimedia.org/w/index.php?title=User:Gsaisudha75&amp;action=edit&amp;redlink=1" title="User:Gsaisudha75 (page does not exist)">...
</small>

              <p class="tags">
                <span>Tagged in </span>:
                  <a href="/blog/tag/advent/">advent</a>,
                  <a href="/blog/tag/command/">command</a>,
                  <a href="/blog/tag/debugging/">debugging</a>,
                  <a href="/blog/tag/administration/">administration</a>
              </p>


                  <div class="bio cf">

                      <div class="gravatar">
                        <img alt="author image" src="https://secure.gravatar.com/avatar/cc767569f5863a7c261991ee5b23f147">
                      </div>
                      <div class="about">
                        <h5>Joel Berger</h5>
                        <p>Joel has Ph.D. in Physics from the University of Illinois at Chicago.
He an avid Perl user and <a href="https://metacpan.org/author/JBERGER">author</a> and is a member of the Mojolicious Core Team.</p>

                      </div>

                  </div>

devdata/https_mojolicious.io_blog_2017_12_05_day-5-your-apps-built-in-commands  view on Meta::CPAN

                  <li class="next"><a href="/blog/2017/12/06/day-6-adding-your-own-commands/index.html" rel="next"><strong>Next Article</strong> Day 6: Adding Your Own Commands </a></li>
              </ul>

            </div>

        </article>


      </div>

      <div class="four columns end" id="secondary">
        <aside id="sidebar">
          







<div class="widget widget_tag_cloud">

devdata/https_mojolicious.io_blog_2017_12_06_day-6-adding-your-own-commands  view on Meta::CPAN


            </div>

              <div class="post-thumb">
                <!-- theme suggests 1300x500 -->
                <img alt="Space shuttle Atlantis prepared for liftoff (night)" src="/blog/2017/12/06/day-6-adding-your-own-commands/1280px-Brightly_lit_STS-135_on_launch_pad_39a.jpg">
              </div>

            <div class="post-content">

              <section id="section-1">
                  <p>Everyone has written those one-off administration or check scripts.
There are probably a few cluttering your project root or bin directory right now.
Those have a problem beyond just the clutter: duplication.</p>

<p>Programmers hate duplication because of skew.
If code gets improved in one place, it is unlikely to be improved in all places, unless there is only the one.
So that script you wrote a while back, the one with the database connection you hand-rolled, is that still correct?</p>

<p>In the <a href="/blog/2017/12/05/day-5-your-apps-built-in-commands">previous article in this series</a> I talked about the built-in commands available to your application.
The final command was <a href="http://mojolicious.org/perldoc/Mojolicious/Command/eval"><code>eval</code></a>.
I mentioned that when combined with predefined behaviors, the command could be great for administrative tasks.
That&#39;s true, but you need to know what to eval in order to do so.</p>

<p>To formalize that process, we can go one step further: defining our own commands.
By doing this your application&#39;s administative behaviors can take arguemnts and provide optional switches as well as give usage messages.
In this way these administative commands decouple themselves from knowledge of the application&#39;s internals and become useful to a broader set of users.</p>

              </section>
              <section id="section-2">
                  <h2>What is a Command?</h2>

<p>Structurally, a command is just a class that inherits from <a href="http://mojolicious.org/perldoc/Mojolicious/Command">Mojolicious::Command</a> and implements a <code>run</code> method.
The method is passed an instance of the command class and the arguments given on the command line.
The command has the application as an attribute.
Just as the <code>eval</code> command demonstrated, the real power of the command comes from having access to an instance of the application, including its relevant configuration and methods.</p>

<p>By default your application looks for available commands in the namespace <code>Mojolicious::Command</code>.
As we saw before, several are available built-in to the system.
However others are available from CPAN, for example, I have a <a href="https://metacpan.org/pod/Mojolicious::Command::nopaste">nopaste clone</a> that when installed is available via your application or the <code>mojo</code> executable.</p>

devdata/https_mojolicious.io_blog_2017_12_06_day-6-adding-your-own-commands  view on Meta::CPAN

Helpers are very useful for tying parts of your application together.
In this case we use one to build and return an instance of our model class.
It attaches that required data that we noted earlier.</p>

<p>Moving on, the application now defines a route.
As we&#39;ll see later it is attached to the <a href="https://github.com/jberger/MyWeatherApp/blob/master/lib/MyWeatherApp/Controller/Weather.pm">Weather controller class</a> and more specifically its <code>recall</code> action method.
This is much like the action callbacks we saw before, but by keeping it in a separate class the application class is easier to read.</p>

<p>Finally we define the database schema.
This is a format common to the Mojo-flavored database modules, like <a href="http://mojolicious.org/perldoc/Mojo/Pg">Mojo::Pg</a>, <a href="https://metacpan.org/pod/Mojo::mysql">Mojo::mysql</a>, and <a href="https://metacpan.org/pod/Mojo::SQLite">Moj...
Each section is defined with a version number and the word <code>up</code> or <code>down</code>.
When migrating versions, it will apply each change set from the current version (beginning at 0) until the version you request.
If you don&#39;t request a version it gets the highest version.</p>

<p>Now that all that is done, we can try it out!</p>

<pre><code>$ perl bin/myweatherapp eval -V &#39;app-&gt;weather-&gt;fetch(&quot;Chicago&quot;)&#39;
</code></pre>

<p>If you&#39;ve configured your appid correctly you should get a dump of weather data about my home city.</p>

devdata/https_mojolicious.io_blog_2017_12_06_day-6-adding-your-own-commands  view on Meta::CPAN

    &#39;v|version=i&#39; =&gt; \my $version,
  );

  my $app = $self-&gt;app;
  $app-&gt;sqlite-&gt;migrations-&gt;migrate(defined $version ? $version : ());
}

1;
</code></pre>

<p>The second use is to fetch and store the data in the database.
This could be run manually, but more likely this could be run by cron to regularly keep the database up to date.
It is located at <a href="https://github.com/jberger/MyWeatherApp/blob/master/lib/MyWeatherApp/Command/fetch_weather.pm">lib/MyWeatherApp/Command/fetch_weather.pm</a>.</p>

<pre><code>package MyWeatherApp::Command::fetch_weather;
use Mojo::Base &#39;Mojolicious::Command&#39;;

has description =&gt; &#39;Fetch and cache the current weather&#39;;
has usage =&gt; &lt;&lt;&quot;USAGE&quot;;
$0 fetch_weather [SEARCH, ...]

devdata/https_mojolicious.io_blog_2017_12_06_day-6-adding-your-own-commands  view on Meta::CPAN


<p>There are convenient mechanisms to generate the usage output from pod documentation inline in the command&#39;s file.
And there is one command that lists subcommands, <a href="http://mojolicious.org/perldoc/Mojolicious/Commands">Mojolicious::Commands</a> itself.
Indeed the one command we&#39;ve seen so far that has subcommands, the <a href="http://mojolicious.org/perldoc/Mojolicious/Command/generate"><code>generate</code></a> command subclasses it to get that behavior.
It in turn has its own set of namespaces to search for commands, which it displays as subcommands.</p>

<p>Commands are very flexible and very powerful.
Indeed they are one of my very favorite things about Mojolicious.
Perhaps you can tell?</p>

              </section>
              <small><p><a href="https://commons.wikimedia.org/w/index.php?curid=15739462">Image</a>
by Bill Ingalls - <a href="http://www.flickr.com/photos/nasahqphoto/5914101671/in/photostream/" rel="nofollow">http://www.flickr.com/photos/nasahqphoto/5914101671/in/photostream/</a>, Public Domain.</p>
</small>

              <p class="tags">
                <span>Tagged in </span>:
                  <a href="/blog/tag/advent/">advent</a>,
                  <a href="/blog/tag/command/">command</a>,
                  <a href="/blog/tag/example/">example</a>
              </p>


                  <div class="bio cf">

                      <div class="gravatar">
                        <img alt="author image" src="https://secure.gravatar.com/avatar/cc767569f5863a7c261991ee5b23f147">
                      </div>
                      <div class="about">
                        <h5>Joel Berger</h5>
                        <p>Joel has Ph.D. in Physics from the University of Illinois at Chicago.
He an avid Perl user and <a href="https://metacpan.org/author/JBERGER">author</a> and is a member of the Mojolicious Core Team.</p>

                      </div>

                  </div>

devdata/https_mojolicious.io_blog_2017_12_06_day-6-adding-your-own-commands  view on Meta::CPAN

                  <li class="next"><a href="/blog/2017/12/07/day-7-using-template-variants-for-a-beta-landing-page/index.html" rel="next"><strong>Next Article</strong> Day 7: Using Template Variants For a Beta Landing Page </a></li>
              </ul>

            </div>

        </article>


      </div>

      <div class="four columns end" id="secondary">
        <aside id="sidebar">
          







<div class="widget widget_tag_cloud">

devdata/https_mojolicious.io_blog_2017_12_07_day-7-using-template-variants-for-a-beta-landing-page  view on Meta::CPAN


            </div>

              <div class="post-thumb">
                <!-- theme suggests 1300x500 -->
                <img alt="Single yellow tulip in a field of red tulips" src="/blog/2017/12/07/day-7-using-template-variants-for-a-beta-landing-page/1280px-Single_yellow_tulip_in_a_field_of_red_tulips.jpg">
              </div>

            <div class="post-content">

              <section id="section-1">
                  <p><a href="http://cpantesters.org">CPAN Testers</a> is a pretty big project with a long,
storied history. At its heart is a data warehouse holding all the test reports
made by people installing CPAN modules. Around that exists an ecosystem of
tools and visualizations that use this data to provide useful insight into the
status of CPAN distributions.</p>

<p>For the <a href="http://github.com/cpan-testers/cpantesters-web">CPAN Testers webapp
project</a>, I needed a way to
show off some pre-release tools with some context about what they are and how
they might be made ready for release. I needed a &quot;beta&quot; website with a front
page that introduced the beta projects. But, I also needed the same
<a href="http://mojolicious.org">Mojolicious</a> application to serve (in the future) as a
production website. The front page of the production website would be
completely different from the front page of the beta testing website.</p>

<p>To achieve this, I used <a href="http://mojolicious.org/perldoc/Mojolicious/Guides/Rendering#Template-variants">Mojolicious&#39;s template variants
feature</a>.</p>

              </section>
              <section id="section-2">
                  <p>First, I created a variant of my index.html template for my beta site
and called it <code>index.html+beta.ep</code>.</p>

<pre><code class="hljs"><span class="hljs-keyword">&lt;h1&gt;</span>CPAN Testers Beta<span class="hljs-keyword">&lt;/h1&gt;</span>
<span class="hljs-keyword">&lt;p&gt;</span>This site shows off some new features currently being tested.<span class="hljs-keyword">&lt;/p&gt;</span>
<span class="hljs-keyword">&lt;h2&gt;&lt;a</span> href=<span class="hljs-string">&quot;/chart.html&quot;</span><span class="hljs-keyword">&gt;</span>Release Dashboard<span class="hljs-keyword">&lt;/a&gt;&lt;/h2&gt;</span>
</code></pre>

<p>Next, I told Mojolicious to use the &quot;beta&quot; variant when in &quot;beta&quot; mode
by passing <code>$app-&gt;mode</code> to the <code>variant</code> stash variable.</p>

devdata/https_mojolicious.io_blog_2017_12_07_day-7-using-template-variants-for-a-beta-landing-page  view on Meta::CPAN


<p>Template variants are a useful feature in some edge cases, and this isn&#39;t the
first time I&#39;ve found a good use for them. I&#39;ve also used them to provide a
different layout template in &quot;development&quot; mode to display a banner saying
&quot;You&#39;re on the development site&quot;. Useful for folks who are undergoing user
acceptance testing. The best part is that if the desired variant for that
specific template is not found, Mojolicious falls back to the main template. I
built a mock JSON API application which made extensive use of this fallback
feature, but that&#39;s another blog post for another time.</p>

              </section>
              <small><p><a href="https://commons.wikimedia.org/w/index.php?curid=2147460">Image</a> by Photo by and (c)2007 <a href="//commons.wikimedia.org/wiki/User:Jina_Lee" title="User:Jina Lee">Jina Lee</a> - <span class="int-own-work" lang="en"...
</small>

              <p class="tags">
                <span>Tagged in </span>:
                  <a href="/blog/tag/advent/">advent</a>,
                  <a href="/blog/tag/rendering/">rendering</a>,
                  <a href="/blog/tag/templates/">templates</a>
              </p>


                  <div class="bio cf">

                      <div class="gravatar">
                        <img alt="author image" src="https://secure.gravatar.com/avatar/4bdc4922059d58a0fcbf8f35652dc254.png">
                      </div>
                      <div class="about">
                        <h5>Doug Bell</h5>
                        <p>Doug (<a href="http://preaction.me">preaction</a>) is a long time Perl user.
He is the current maintainer of <a href="http://www.cpantesters.org/">CPAN Testers</a> and the author of many <a href="https://metacpan.org/author/PREACTION">CPAN modules</a> including the <a href="http://preaction.me/statocles/">Statocles</a> blog e...

                      </div>

                  </div>

devdata/https_mojolicious.io_blog_2017_12_07_day-7-using-template-variants-for-a-beta-landing-page  view on Meta::CPAN

                  <li class="next"><a href="/blog/2017/12/08/day-8-mocking-a-rest-api/index.html" rel="next"><strong>Next Article</strong> Day 8: Mocking a REST API </a></li>
              </ul>

            </div>

        </article>


      </div>

      <div class="four columns end" id="secondary">
        <aside id="sidebar">
          







<div class="widget widget_tag_cloud">

devdata/https_mojolicious.io_blog_2017_12_08_day-8-mocking-a-rest-api  view on Meta::CPAN


            </div>

              <div class="post-thumb">
                <!-- theme suggests 1300x500 -->
                <img alt="Two crash test dummies" src="/blog/2017/12/08/day-8-mocking-a-rest-api/1280px-crash-test-dummies.jpg">
              </div>

            <div class="post-content">

              <section id="section-1">
                  <p>One of my applications is a pure-JavaScript UI for a JSON API. This UI
is an entirely different project that communicates with a public API
using an OpenAPI specification.</p>

<p>Our public API is huge and complex: To set up the public API, I need
a database, sample data, and three other private API servers that
perform individual tasks as directed by the public API. Worse, I would
need to set up a lot of different test scenarios with different kinds of
data.</p>

<p>It would be a lot easier to set up a mock public API that I could use to
test my UI, and it turns out that Mojolicious makes this very easy.</p>

              </section>
              <section id="section-2">
                  <p>So let&#39;s set up a simple Mojolicious::Lite app that responds to a path
with a JSON response:</p>

<pre><code class="hljs"><span class="hljs-comment"># test-api.pl</span><span class="hljs-comment">
</span><span class="hljs-keyword">use</span> <span class="hljs-function">Mojolicious::Lite</span>;
get &#39;<span class="hljs-string">/servers</span>&#39; =&gt; <span class="hljs-keyword">sub </span>{
    <span class="hljs-keyword">my</span> ( <span class="hljs-type">$c</span> ) = <span class="hljs-type">@_</span>;
    <span class="hljs-keyword">return</span> <span class="hljs-type">$c</span>-&gt;<span class="hljs-type">render</span>(
        json =&gt; [
            { ip =&gt; &#39;<span class="hljs-string">10.0.0.1</span>&#39;, os =&gt; &#39;<span class="hljs-string">Debian 9</span>&#39; },

devdata/https_mojolicious.io_blog_2017_12_08_day-8-mocking-a-rest-api  view on Meta::CPAN

</code></pre>

<p>That&#39;s pretty easy and shows how easy Mojolicious can be to get started.
But I have dozens of routes in my application! Combined with all the
possible data and its thousands of routes. How do I make all of them
work without copy-pasting code for every single route?</p>

<p>Let&#39;s match the whole path of the route and then create a template with
the given path. Mojolicious lets us match the whole path using the <code>*</code>
placeholder in the route path. Then we can use that path to look up the
template, which we&#39;ll put in the <code>__DATA__</code> section.</p>

<pre><code class="hljs"><span class="hljs-comment"># test-api.pl</span><span class="hljs-comment">
</span><span class="hljs-keyword">use</span> <span class="hljs-function">Mojolicious::Lite</span>;
any &#39;<span class="hljs-string">/*path</span>&#39; =&gt; <span class="hljs-keyword">sub </span>{
    <span class="hljs-keyword">my</span> ( <span class="hljs-type">$c</span> ) = <span class="hljs-type">@_</span>;
    <span class="hljs-keyword">return</span> <span class="hljs-type">$c</span>-&gt;<span class="hljs-type">render</span>(
        template =&gt; <span class="hljs-type">$c</span>-&gt;<span class="hljs-type">stash</span>( &#39;<span class="hljs-string">path</span>&#39; ),
        <span class="hljs-function">format</span> =&gt; &#39;<span class="hljs-string">json</span>&#39;,
    );
};

devdata/https_mojolicious.io_blog_2017_12_08_day-8-mocking-a-rest-api  view on Meta::CPAN

@@ POST/servers.json.ep
{ &quot;status&quot;: &quot;success&quot;, &quot;id&quot;: 3, &quot;server&quot;: &lt;%== $c-&gt;req-&gt;body %&gt; }
@@ POST/servers.json+error.ep
% $c-&gt;res-&gt;code( 400 );
{ &quot;status&quot;: &quot;error&quot;, &quot;error&quot;: &quot;Bad request&quot; }
</code></pre>

<p>Now I have 20 lines of code that can be made to mock any JSON API
I write. Mojolicious makes everything easy!</p>

              </section>
              <small><p><a href="https://commons.wikimedia.org/w/index.php?curid=37564272">Image</a> by Calspan Corporation, National Highway Traffic Safety Administration - Public Domain.</p>
</small>

              <p class="tags">
                <span>Tagged in </span>:
                  <a href="/blog/tag/advent/">advent</a>,
                  <a href="/blog/tag/mocking/">mocking</a>,
                  <a href="/blog/tag/api/">api</a>
              </p>


                  <div class="bio cf">

                      <div class="gravatar">
                        <img alt="author image" src="https://secure.gravatar.com/avatar/4bdc4922059d58a0fcbf8f35652dc254.png">
                      </div>
                      <div class="about">
                        <h5>Doug Bell</h5>
                        <p>Doug (<a href="http://preaction.me">preaction</a>) is a long time Perl user.
He is the current maintainer of <a href="http://www.cpantesters.org/">CPAN Testers</a> and the author of many <a href="https://metacpan.org/author/PREACTION">CPAN modules</a> including the <a href="http://preaction.me/statocles/">Statocles</a> blog e...

                      </div>

                  </div>

devdata/https_mojolicious.io_blog_2017_12_08_day-8-mocking-a-rest-api  view on Meta::CPAN

                  <li class="next"><a href="/blog/2017/12/09/day-9-the-best-way-to-test/index.html" rel="next"><strong>Next Article</strong> Day 9: The Best Way to Test </a></li>
              </ul>

            </div>

        </article>


      </div>

      <div class="four columns end" id="secondary">
        <aside id="sidebar">
          







<div class="widget widget_tag_cloud">

devdata/https_mojolicious.io_blog_2017_12_09_day-9-the-best-way-to-test  view on Meta::CPAN


            </div>

              <div class="post-thumb">
                <!-- theme suggests 1300x500 -->
                <img alt="Woman using chemistry lab equipment" src="/blog/2017/12/09/day-9-the-best-way-to-test/1280px-CSIRO_ScienceImage_2798_Testing_in_the_Laboratory.jpg">
              </div>

            <div class="post-content">

              <section id="section-1">
                  <p>Ok so it is a bit of a click-bait headline.
But that doesn&#39;t mean I don&#39;t believe it.</p>

<p><a href="http://mojolicious.org/perldoc/Test/Mojo">Test::Mojo</a> is a test framework for websites and related technologies.
While its true that there are many such tools, this one gets its power comes from combining so many of the tools that Mojolicious provides.
A full non-blocking web server, including websockets, an <a href="http://mojolicious.org/perldoc/Mojo/IOLoop">event loop</a>, an <a href="http://mojolicious.org/perldoc/Mojo/DOM">XML/HTML DOM parser</a>, <a href="http://mojolicious.org/perldoc/Mojo/J...
Further, with the recent additions in support of <a href="http://mojolicious.org/perldoc/Mojo/Base#with_roles">roles</a> (which will be discussed in a future post), Test::Mojo is becoming an extensible testing platform.</p>

<p>In this article, I&#39;ll give a quick overview of how to use Test::Mojo and some of its methods.
Rest assured you&#39;ll see more of it as the series continues.</p>

              </section>
              <section id="section-2">
                  <h2>Getting Started</h2>

<p>The topmatter of a Test::Mojo script usually is fairly consistent.</p>

<pre><code>use Mojo::Base -strict;
use Test::More;
use Test::Mojo;
</code></pre>

<p>Unlike the Mojolicious, Mojolicious::Lite or Mojo::Base modules, importing Test::Mojo does not import strict, warnings and other recommended pragma.

devdata/https_mojolicious.io_blog_2017_12_09_day-9-the-best-way-to-test  view on Meta::CPAN

<pre><code>use Mojolicious::Lite;
plugin &#39;MyCoolPlugin&#39;;
my $t = Test::Mojo-&gt;new;
</code></pre>

<p>Testing a Full app couldn&#39;t be simpler, you just pass it a class name for it to instantiate.</p>

<pre><code>my $t = Test::Mojo-&gt;new(&#39;MyApp&#39;);
</code></pre>

<p>When instantiating a Full app you can actually pass it a second argument, a hash reference of configuration overrides.
This can be especially handy for overriding things like database parameters to access a test instance rather than your regular database.
Of couse how you use your configuration might vary but if your app does something like</p>

<pre><code>has pg =&gt; sub {
  my $app = shift;
  return Mojo::Pg-&gt;new($app-&gt;config-&gt;{pg});
};
</code></pre>

<p>Then you could override whatever configuration might be present in your system by doing</p>

devdata/https_mojolicious.io_blog_2017_12_09_day-9-the-best-way-to-test  view on Meta::CPAN


<p>You can make requests with most of the same arguments as to <a href="http://mojolicious/perldoc/Mojo/UserAgent#METHODS">Mojo::UserAgent</a>.
These can include headers as a hash reference:</p>

<pre><code>$t-&gt;get_ok(&#39;/login&#39;, {&#39;X-Application-Auth&#39; =&gt; &#39;custom value&#39;});
</code></pre>

<p>Requests with JSON, form, for multipart data are built via <a href="http://mojolicious.org/perldoc/Mojo/UserAgent/Transactor#GENERATORS">content generators</a>.
You can <a href="http://mojolicious.org/perldoc/Mojo/UserAgent/Transactor#add_generator">add your own</a> generator too; perhaps the subject of another article if there is interest.</p>

<pre><code>$t-&gt;post_ok(&#39;/login&#39;, form =&gt; {user =&gt; &#39;me&#39;, pass =&gt; &#39;secr3t&#39;});
$t-&gt;put_ok(&#39;/inventory/12345&#39;, json =&gt; {type =&gt; &#39;widget&#39;, value =&gt; &#39;tons&#39;});
</code></pre>

<p>Or you can submit raw data as a trailing argument</p>

<pre><code>use Mojo::XMLRPC &#39;encode_xmlrpc&#39;; # from CPAN
$t-&gt;post_ok(&#39;/xmlrpc&#39;, encode_xmlrpc(call =&gt; &#39;mymethod&#39;, &#39;myarg&#39;));
</code></pre>

<p>There are methods for all the standard HTTP methods.

devdata/https_mojolicious.io_blog_2017_12_09_day-9-the-best-way-to-test  view on Meta::CPAN

  -&gt;json_is(&#39;/status&#39;, &#39;nice&#39;);
</code></pre>

<p>Of course there are methods to test HTML responses.
Since it makes little sense to test the whole thing (and if you wanted to you could use <code>content_</code>), these take a <a href="http://mojolicious.org/perldoc/Mojo/DOM/CSS">CSS3 Selector</a> to narrow their focus in a similar manner to the JSON...
To inspect the textual portions of the HTML response, use the <code>text_</code> methods with a selector.
For other tests, there might not be text to test, or the value doesn&#39;t matter.
For those cases there are <code>element_exists</code>, <code>element_exists_not</code>, and <code>element_count_is</code>, which, as their names indicate, take a selector and tries to find if or how many elements match it.
These really need a post of their own, but as a few examples</p>

<pre><code>$t-&gt;text_is(&#39;div.main-content p:nth-of-type(2)&#39;, &#39;This is the third paragraph of the main-section of text&#39;);
$t-&gt;element_exists(&#39;img[src=&quot;kitten.jpg&quot;]&#39;);
</code></pre>

<h2>Testing Websockets</h2>

<p>Websockets are an intersting challenge to test, however Test::Mojo makes them easy.
We&#39;ve already seen that you open a websocket with <code>websocket_ok</code>.</p>

<p>You can then either send a message with <code>send_ok</code> (taking the same arguments as the controller&#39;s <a href="http://mojolicious.org/perldoc/Mojolicious/Controller#send">send</a> method) or you can wait for a message with <code>message_...
The test then waits for a message to arrive without blocking the application, so it can do its work.

devdata/https_mojolicious.io_blog_2017_12_09_day-9-the-best-way-to-test  view on Meta::CPAN

<h2>To Be Continued</h2>

<p>There is still so much to say on the topic of testing.
Various tips and tricks.
Extensions that make testing javascript possible, extensions that make testing Catalyst or Dancer apps possible.
But this overview has gone plenty long and those should wait for another day.</p>

<p>As I said before, the Mojolicious documentation has lots of examples both in the <a href="http://mojolicious.org/perldoc/Test/Mojo">class documenation</a> and in the <a href="http://mojolicious.org/perldoc/Mojolicious/Guides/Testing">testing guide...
Check those out while you wait, if you&#39;ve liked what you&#39;ve seen above.</p>

              </section>
              <small><p><a href="https://commons.wikimedia.org/w/index.php?curid=35474503">Image</a> by CSIRO, <a href="http://creativecommons.org/licenses/by/3.0" title="Creative Commons Attribution 3.0">CC BY 3.0</a>.</p>
</small>

              <p class="tags">
                <span>Tagged in </span>:
                  <a href="/blog/tag/advent/">advent</a>,
                  <a href="/blog/tag/testing/">testing</a>
              </p>


                  <div class="bio cf">

                      <div class="gravatar">
                        <img alt="author image" src="https://secure.gravatar.com/avatar/cc767569f5863a7c261991ee5b23f147">
                      </div>
                      <div class="about">
                        <h5>Joel Berger</h5>
                        <p>Joel has Ph.D. in Physics from the University of Illinois at Chicago.
He an avid Perl user and <a href="https://metacpan.org/author/JBERGER">author</a> and is a member of the Mojolicious Core Team.</p>

                      </div>

                  </div>

devdata/https_mojolicious.io_blog_2017_12_09_day-9-the-best-way-to-test  view on Meta::CPAN

                  <li class="next"><a href="/blog/2017/12/10/day-10-give-the-customer-what-they-want/index.html" rel="next"><strong>Next Article</strong> Day 10: Give the Customer What They Want </a></li>
              </ul>

            </div>

        </article>


      </div>

      <div class="four columns end" id="secondary">
        <aside id="sidebar">
          







<div class="widget widget_tag_cloud">

devdata/https_mojolicious.io_blog_2017_12_10_day-10-give-the-customer-what-they-want  view on Meta::CPAN


            </div>

              <div class="post-thumb">
                <!-- theme suggests 1300x500 -->
                <img alt="Wood bar counter with chairs" src="/blog/2017/12/10/day-10-give-the-customer-what-they-want/cafe-wood-vintage-retro-seat-restaurant-946984-pxhere.com.jpg">
              </div>

            <div class="post-content">

              <section id="section-1">
                  <p>Writing an API can be as easy as taking the results of some database query and presenting it to the user.
A more advanced one can often present the data in one of multiple formats.
The user can then specify which format they want.</p>

<p>JSON is currently the most popular format for new APIs.
XML is another common one and was certainly king before JSON hit the scene.
An API might choose to make an HTML format of the data available, whether in some representation of the data or to render documentation about the API itself.
Of course there are many others.</p>

<p>Mojolicious believes in <a href="http://mojolicious.org/perldoc/Mojolicious/Guides/Rendering#Content-negotiation">Content Negotiation</a>, as it is called, and supports it throughout the stack.
Mojolicious makes it easy and convenient for users to pick a format they would like.
Similarly it makes rendering the different formats easy on the site author, as you would expect.</p>

              </section>
              <section id="section-2">
                  <h2>Requesting a Format</h2>

<h3>Accept Headers</h3>

<p>The most HTTP-native way to choose a response format is with the <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Accept"><code>Accept</code></a>.
A request bearing the <code>Accept: application/json</code> header is indicating it wants JSON in the response.
Mojolicious supports this header, and this format is very handy for programmatic API clients, but it isn&#39;t very friendly to users, so there are several other options.</p>

<h3>File Extension</h3>

devdata/https_mojolicious.io_blog_2017_12_10_day-10-give-the-customer-what-they-want  view on Meta::CPAN

  $c-&gt;reply-&gt;table($data);
};

app-&gt;start;
</code></pre>

<p>Of course under the hood this is using Content Negotiation and several other modules to provide CSV, HTML, JSON, text, XLS, and XLSX outputs.
It is configurable via several stash values that might be set.
If you&#39;d like to dig into that code to see how it works, please feel free.</p>

              </section>
              <small><p><a href="https://pxhere.com/en/photo/946984">Image</a> in the Public Domain.</p>
</small>

              <p class="tags">
                <span>Tagged in </span>:
                  <a href="/blog/tag/advent/">advent</a>,
                  <a href="/blog/tag/rendering/">rendering</a>
              </p>


                  <div class="bio cf">

                      <div class="gravatar">
                        <img alt="author image" src="https://secure.gravatar.com/avatar/cc767569f5863a7c261991ee5b23f147">
                      </div>
                      <div class="about">
                        <h5>Joel Berger</h5>
                        <p>Joel has Ph.D. in Physics from the University of Illinois at Chicago.
He an avid Perl user and <a href="https://metacpan.org/author/JBERGER">author</a> and is a member of the Mojolicious Core Team.</p>

                      </div>

                  </div>

devdata/https_mojolicious.io_blog_2017_12_10_day-10-give-the-customer-what-they-want  view on Meta::CPAN

                  <li class="next"><a href="/blog/2017/12/11/day-11-useragent-content-generators/index.html" rel="next"><strong>Next Article</strong> Day 11: UserAgent Content Generators </a></li>
              </ul>

            </div>

        </article>


      </div>

      <div class="four columns end" id="secondary">
        <aside id="sidebar">
          







<div class="widget widget_tag_cloud">

devdata/https_mojolicious.io_blog_2017_12_11_day-11-useragent-content-generators  view on Meta::CPAN


            </div>

              <div class="post-thumb">
                <!-- theme suggests 1300x500 -->
                <img alt="Artist painting" src="/blog/2017/12/11/day-11-useragent-content-generators/artist-painting-1459778857j86.jpg">
              </div>

            <div class="post-content">

              <section id="section-1">
                  <p>We have already seen <a href="http://mojolicious.org/perldoc/Mojo/UserAgent">Mojo::UserAgent</a> used to make HTTP requests in this series.
In fact we&#39;ve already seen how you can use <a href="http://mojolicious.org/perldoc/Mojolicious/Guides/Cookbook#USER-AGENT">Content Generators</a> to build requests <a href="/blog/2017/12/09/day-9-the-best-way-to-test#making-requests">in tests</a>...
But we didn&#39;t look at how they work or how you can add new ones.</p>

              </section>
              <section id="section-2">
                  <h2>Using Content Generators</h2>

<p>The UserAgent, and more specifically its <a href="http://mojolicious.org/perl/Mojo/UserAgent/Transactor">Transactor</a>, help you by making it easy to create HTTP requests.
Consider the most basic request with a body, a <code>POST</code> with a binary body, maybe ASCII text.
In that case, the request</p>

<pre><code>my $ua = Mojo::UserAgent-&gt;new;
$ua-&gt;post(
  &#39;/url&#39;,
  {&#39;Content-Type&#39; =&gt; &#39;text/plain&#39;},

devdata/https_mojolicious.io_blog_2017_12_11_day-11-useragent-content-generators  view on Meta::CPAN


</code></pre>

<p>which produces an output essentially identical to the first.</p>

<p>At first glance it only appears to be a modest improvement.
However, once defined, it does cut down on repeated code for subsequent requests.
Thus the benefit grows the more times it is used.
In a larger code base, that adherence to the DRY mantra (Don&#39;t Repeat Yourself) might be invaluable.</p>

              </section>
              <small><p><a href="http://www.publicdomainpictures.net/view-image.php?image=157945&amp;picture=artist-painting">Image</a> in the Public Domain.</p>
</small>

              <p class="tags">
                <span>Tagged in </span>:
                  <a href="/blog/tag/advent/">advent</a>,
                  <a href="/blog/tag/useragent/">useragent</a>
              </p>


                  <div class="bio cf">

                      <div class="gravatar">
                        <img alt="author image" src="https://secure.gravatar.com/avatar/cc767569f5863a7c261991ee5b23f147">
                      </div>
                      <div class="about">
                        <h5>Joel Berger</h5>
                        <p>Joel has Ph.D. in Physics from the University of Illinois at Chicago.
He an avid Perl user and <a href="https://metacpan.org/author/JBERGER">author</a> and is a member of the Mojolicious Core Team.</p>

                      </div>

                  </div>

devdata/https_mojolicious.io_blog_2017_12_11_day-11-useragent-content-generators  view on Meta::CPAN

                  <li class="next"><a href="/blog/2017/12/12/day-12-more-than-a-base-class/index.html" rel="next"><strong>Next Article</strong> Day 12: More Than a Base Class </a></li>
              </ul>

            </div>

        </article>


      </div>

      <div class="four columns end" id="secondary">
        <aside id="sidebar">
          







<div class="widget widget_tag_cloud">

devdata/https_mojolicious.io_blog_2017_12_12_day-12-more-than-a-base-class  view on Meta::CPAN


            </div>

              <div class="post-thumb">
                <!-- theme suggests 1300x500 -->
                <img alt="Golden Gate Bridge viewed and Fort Point" src="/blog/2017/12/12/day-12-more-than-a-base-class/1280px-GG-ftpoint-bridge-2.jpg">
              </div>

            <div class="post-content">

              <section id="section-1">
                  <p>Through this series, you&#39;ve seen the module <a href="http://mojolicious.org/perldoc/Mojo/Base">Mojo::Base</a> referenced several times, though briefly and mostly in passing.
It shouldn&#39;t be taken lightly however, it packs a lot of punch in one import statement!
Nearly every file in the Mojolicious distribution uses it, either directly or indirectly.
So what is it?</p>

<p>First it imports several handy pragma that make your code safer and some features that are useful.
Second, it can be a base class to the current package, or establish a parent class, or even define a role.
Let&#39;s see how it does it.</p>

              </section>
              <section id="section-2">
                  <h2>Importing Pragma and Functionality</h2>

<p>Most of the authors in the modern Perl commmunity recommend that all Perl code use the <a href="https://metacpan.org/pod/strict">strict</a> and <a href="https://metacpan.org/pod/warnings">warnings</a> pragmas.
Like many of the major Perl object frameworks, <a href="https://metacpan.org/pod/Moose">Moose</a> and <a href="https://metacpan.org/pod/Moo">Moo</a> included, Mojo::Base feels these are important enough that it imports them for you.
Unlike those others, it goes further.</p>

<p>Since the modern web is trending towards UTF-8 encoding, the <a href="https://metacpan.org/pod/utf8">utf8</a> pragma is loaded; this enables you to use UTF-8 encoded characters right in your script.
Mojolicious does much of your web-facing encoding for you so this <strong>almost</strong> means you don&#39;t have to think about character encoding at all!</p>

<p>And because Mojolicious itself requires Perl 5.10, it also enables all of the <a href="https://metacpan.org/pod/feature">features</a> that came with that version.

devdata/https_mojolicious.io_blog_2017_12_12_day-12-more-than-a-base-class  view on Meta::CPAN

</code></pre>

<p>Perhaps this is too much adherence to fluent interfaces but as you progress, getting a nice long chain can really feel like an accomplishment!
If you&#39;d rather pass on this method, that&#39;s fine too.</p>

<h2>Roles</h2>

<p>While Mojo::Base has always tacitly supported roles via external modules, just recently has it started to offer explicit functionality in this area.
That said, I have lots ot say on the matter, so if you&#39;ll permit me, I&#39;m going to keep you in suspense until <a href="/blog/2017/12/13/day-13-more-about-roles">tomorrow</a>.</p>

              </section>
              <small><p><a href="https://commons.wikimedia.org/w/index.php?curid=1592390">Image</a> by <a href="https://en.wikipedia.org/wiki/User:Mactographer" title="en:User:Mactographer">David Ball</a> - Original work, <a href="http://creativecomm...
</small>

              <p class="tags">
                <span>Tagged in </span>:
                  <a href="/blog/tag/advent/">advent</a>,
                  <a href="/blog/tag/fluent/">fluent</a>,
                  <a href="/blog/tag/roles/">roles</a>
              </p>


                  <div class="bio cf">

                      <div class="gravatar">
                        <img alt="author image" src="https://secure.gravatar.com/avatar/cc767569f5863a7c261991ee5b23f147">
                      </div>
                      <div class="about">
                        <h5>Joel Berger</h5>
                        <p>Joel has Ph.D. in Physics from the University of Illinois at Chicago.
He an avid Perl user and <a href="https://metacpan.org/author/JBERGER">author</a> and is a member of the Mojolicious Core Team.</p>

                      </div>

                  </div>

devdata/https_mojolicious.io_blog_2017_12_12_day-12-more-than-a-base-class  view on Meta::CPAN

                  <li class="next"><a href="/blog/2017/12/13/day-13-more-about-roles/index.html" rel="next"><strong>Next Article</strong> Day 13: More About Roles </a></li>
              </ul>

            </div>

        </article>


      </div>

      <div class="four columns end" id="secondary">
        <aside id="sidebar">
          







<div class="widget widget_tag_cloud">

devdata/https_mojolicious.io_blog_2017_12_13_day-13-more-about-roles  view on Meta::CPAN


            </div>

              <div class="post-thumb">
                <!-- theme suggests 1300x500 -->
                <img alt="Pile of hats" src="/blog/2017/12/13/day-13-more-about-roles/amsterdam_hats.jpg">
              </div>

            <div class="post-content">

              <section id="section-1">
                  <p>Before we get ahead of ourselves, what are roles?
Briefly stated, roles enable composing functionality (usually methods) into a class without without implying a change of inheritence.
Said another way, roles let you specify what a class does without changing what it is.
For a better description, check out Toby Inkster&#39;s article <a href="http://radar.oreilly.com/2014/01/horizontal-reuse-an-alternative-to-inheritance.html">Horizontal Reuse: An Alternative to Inheritance</a>.</p>

<p>An important utility of roles is that you can easily use more than one role at the same time in the same consuming class.
With inheritance, especially of third-party functionality, you have to choose one set of extensions to utilize.
This is because the author of the subclass establishes the inheritance.
In roles, the user determines which roles to compose into the base class.</p>

<p><a href="/blog/2017/12/12/day-12-more-than-a-base-class">Yesterday</a> I ended the discussion of <a href="http://mojolicious.org/perldoc/Mojo/Base">Mojo::Base</a> before discussing the roles support.
Added in several installments between Mojolicious versions <a href="https://metacpan.org/release/SRI/Mojolicious-7.40">7.40</a> and <a href="https://metacpan.org/release/SRI/Mojolicious-7.55">7.55</a>, this role support is one of the most recently ad...
The role handling comes from <a href="https://metacpan.org/pod/Role::Tiny">Role::Tiny</a> which is an optional dependency in Mojolicious, but is required in order to use the functionality that I will describe.</p>

              </section>
              <section id="section-2">
                  <p>This is not to say that roles couldn&#39;t be or weren&#39;t used in Mojolicious before then, only that Mojo::Base didn&#39;t include any special handling to make it user-friendly.
Prior to the functionality being formally available from Mojo::Base, a few roles were available for Mojo stack classes on CPAN.
To my knowledge they all used Role::Tiny, but they had to roll their own composition mechanisms, presenting some barrier to use.</p>

<h2>Creating Roles</h2>

<p>A role itself looks like a class at first glance.
It has a package name and probably has methods.
Rather than using the <code>-base</code> flag or specifying a parent class, a role uses the <code>-role</code> flag.
Once again, an optional <code>-signatures</code> flag is allowed too.</p>

devdata/https_mojolicious.io_blog_2017_12_13_day-13-more-about-roles  view on Meta::CPAN

use Test::Deep; # for its keywords

my $t = Test::Mojo
  -&gt;with_roles(&#39;+PSGI&#39;, &#39;+TestDeep&#39;, &#39;+Debug&#39;)
  -&gt;new(&#39;/path/to/app.psgi&#39;);

$t-&gt;get_ok(&#39;/&#39;)
  -&gt;text_deeply(
    &#39;nav a&#39;,
    [qw( Home Blog Projects About Contact )],
    &#39;nav link text matches site section titles&#39;,
  )-&gt;d(sub{ diag $t-&gt;tx-&gt;req-&gt;body });
</code></pre>

<p>This example loads a hypothetical psgi application from the filesystem, tests it for text elements and if that test fails dumps the response body to the console.</p>

<p>There are three modules (only two on CPAN so far) that let you run javascript on pages via external processes.
<a href="https://metacpan.org/pod/Test::Mojo::Role::Phantom">Test::Mojo::Role::Phantom</a> and <a href="https://metacpan.org/pod/Test::Mojo::Role::Selenium">Test::Mojo::Role::Selenium</a> use <a href="http://phantomjs.org/">PhantomJS</a> and <a href=...
PhantomJS is abandoned however so <a href="https://github.com/jberger/Mojo-Chrome">Test::Mojo::Role::Chrome</a> is in development on my Github and will replace the PhantomJS role.</p>

<p>Note that several of these modules depend on a module named <a href="https://metacpan.org/pod/Test::Mojo::WithRoles">Test::Mojo::WithRoles</a> which is essentially obsolete at this point.

devdata/https_mojolicious.io_blog_2017_12_13_day-13-more-about-roles  view on Meta::CPAN

<ul>
<li><a href="https://metacpan.org/pod/Mojo::Log::Role::Clearable">Mojo::Role::Log::Clearable</a> allowing the Mojo::Log to cleanly change paths</li>
<li><a href="https://metacpan.org/pod/Mojo::DOM::Role::PrettyPrinter">Mojo::DOM::Role::PrettyPrinter</a> pretty prints Mojo::DOM documents</li>
<li><a href="https://metacpan.org/pod/Mojo::Collection::Role::UtilsBy">Mojo::Collection::Role::UtilsBy</a> adds <a href="https://metacpan.org/pod/List::UtilsBy">List::UtilsBy</a> methods to <a href="http://mojolicious.org/perldoc/Mojo/Collection">Moj...
<li><a href="https://metacpan.org/pod/distribution/Mojo-UserAgent-CookieJar-Role-Persistent/lib/Mojo/UserAgent/CookieJar/Role/Persistent.pod">Mojo::UserAgent::CookieJar::Role::Persistent</a> can store cookies from Mojo::UserAgent requests persistentl...
</ul>

<p>... as well as others.
And the list is sure to grow now that Mojo::Base can natively compose these roles.</p>

              </section>
              <small><p><a href="https://commons.wikimedia.org/w/index.php?curid=15179120">Image</a> © Jorge Royan / <a class="external free" href="http://www.royan.com.ar" rel="nofollow">http://www.royan.com.ar</a>, <a href="https://creativ...
</small>

              <p class="tags">
                <span>Tagged in </span>:
                  <a href="/blog/tag/advent/">advent</a>,
                  <a href="/blog/tag/roles/">roles</a>
              </p>


                  <div class="bio cf">

                      <div class="gravatar">
                        <img alt="author image" src="https://secure.gravatar.com/avatar/cc767569f5863a7c261991ee5b23f147">
                      </div>
                      <div class="about">
                        <h5>Joel Berger</h5>
                        <p>Joel has Ph.D. in Physics from the University of Illinois at Chicago.
He an avid Perl user and <a href="https://metacpan.org/author/JBERGER">author</a> and is a member of the Mojolicious Core Team.</p>

                      </div>

                  </div>

devdata/https_mojolicious.io_blog_2017_12_13_day-13-more-about-roles  view on Meta::CPAN

                  <li class="next"><a href="/blog/2017/12/14/day-14-you-promised-to-call/index.html" rel="next"><strong>Next Article</strong> Day 14: You Promised To Call! </a></li>
              </ul>

            </div>

        </article>


      </div>

      <div class="four columns end" id="secondary">
        <aside id="sidebar">
          







<div class="widget widget_tag_cloud">

devdata/https_mojolicious.io_blog_2017_12_14_day-14-you-promised-to-call  view on Meta::CPAN


            </div>

              <div class="post-thumb">
                <!-- theme suggests 1300x500 -->
                <img alt="Two hands with interlocked pinkies, a pinky swear" src="/blog/2017/12/14/day-14-you-promised-to-call/pinky_swear.jpg">
              </div>

            <div class="post-content">

              <section id="section-1">
                  <p>A new feature of <a href="http://mojolicious.org/">Mojolicious</a>, as of <a href="https://metacpan.org/release/SRI/Mojolicious-7.49">7.49</a>, is the implementation of the <a href="https://promisesaplus.com/implementations#in-ot...

              </section>
              <section id="section-2">
                  <h2>Background</h2>

<p>&quot;Normal&quot; Perl code runs synchronously: it does each step it is told to, one at a time, and only that. This is also known as &quot;blocking&quot;, since the program cannot do anything else.</p>

<p>The essence of a non-blocking code framework is that if you are waiting for something, you can register with the framework what to do when that thing happens. It can then do other processing tasks in the meantime. This means you don&#39;t have lot...

<p>Originally this was done just using callbacks, but this lead to what is known as &quot;callback hell&quot;: each callback contains the next callback, at an increasing level of indentation. Even harder to keep track of is if the functions are kept ...

<p>Promises are used to easily add processing steps to a transaction: one can keep adding code for what to do &quot;then&quot; - after a previous stage has finished. Best of all, each &quot;callback&quot; is small and separate, with each one placed i...

devdata/https_mojolicious.io_blog_2017_12_14_day-14-you-promised-to-call  view on Meta::CPAN


<p><code>catch</code> is given a code-ref, which will be called when a Promise is &quot;rejected&quot;. When things work as above, each Promise is &quot;resolved&quot;. That means the value it was resolved with gets passed to the next <code>then</cod...

<pre><code>sub fetchpage {
  $ua-&gt;get_p($url)-&gt;then(sub { ... })-&gt;then(sub { ... })-&gt;catch(sub {
    # either log, or report, or something else
  });
}
</code></pre>

<p>If either the initial <code>get_p</code>, or either of the <code>then</code>s get rejected, then execution will skip to the <code>catch</code>. Another way to get this behaviour is to give a second code-ref to <code>then</code>.</p>

<p><code>finally</code> is given a code-ref which will be called with either the successful (i.e. resolved) value, or the failure (i.e. the rejection) value.</p>

<h2>The task at hand</h2>

<p>We have to synchronise the work between the multiple &quot;streams&quot; of execution, so that nothing gets missed, or done twice. Luckily, in the asynchronous but single-threaded context we have here, we can just pass around a reference to a sing...

<pre><code>#!/usr/bin/env perl

# cut down from https://stackoverflow.com/questions/15152633/perl-mojo-and-json-for-simultaneous-requests/15166898#15166898

devdata/https_mojolicious.io_blog_2017_12_14_day-14-you-promised-to-call  view on Meta::CPAN

<p>Once each stream runs out of suffixes to process, it will finish. If we wanted to add the ability to add to the queue that could keep as many streams as we started, we would restructure so that each stream is subscribed to a queue, and if the queu...

<h2>See also</h2>

<ul>
<li>The Mojolicious Cookbook shows how to implement non-blocking requests <a href="http://mojolicious.org/perldoc/Mojolicious/Guides/Cookbook#Concurrent-blocking-requests">with promises</a>.</li>
<li>The new <a href="http://mojolicious.org/perldoc/Mojo/Promise">Mojo::Promise</a> class documentation.</li>
<li>This script is now available as a <code>Mojolicious::Command</code>: <a href="https://metacpan.org/pod/Mojolicious::Command::bulkget">Mojolicious::Command::bulkget</a>!</li>
</ul>

              </section>
              <small><p><a href="https://www.flickr.com/photos/elsabordelossegundos/15418211523">Image</a> by <a href="https://www.flickr.com/photos/elsabordelossegundos/">mariadelajuana</a>, <a href="https://creativecommons.org/licenses/by/2.0/">CC ...
</small>

              <p class="tags">
                <span>Tagged in </span>:
                  <a href="/blog/tag/advent/">advent</a>,
                  <a href="/blog/tag/non-blocking/">non-blocking</a>,
                  <a href="/blog/tag/promises/">promises</a>
              </p>


                  <div class="bio cf">

                      <div class="gravatar">
                        <img alt="author image" src="https://secure.gravatar.com/avatar/c6e74e4e0ab61c61db655f0e60c9f8a6.jpg">
                      </div>
                      <div class="about">
                        <h5>Ed J</h5>
                        <p>Ed J (aka &quot;mohawk&quot; on IRC) has been using Perl for a long time. He is currently porting the reference <a href="http://graphql.org/">GraphQL</a> implementation from the <a href="http://graphql.org/graphql-js/">Java...

                      </div>

                  </div>

              <ul class="post-nav cf">

devdata/https_mojolicious.io_blog_2017_12_14_day-14-you-promised-to-call  view on Meta::CPAN

                  <li class="next"><a href="/blog/2017/12/15/day-15-start-a-new-yancy-app/index.html" rel="next"><strong>Next Article</strong> Day 15: Start a New Yancy App </a></li>
              </ul>

            </div>

        </article>


      </div>

      <div class="four columns end" id="secondary">
        <aside id="sidebar">
          







<div class="widget widget_tag_cloud">

devdata/https_mojolicious.io_blog_2017_12_15_day-15-start-a-new-yancy-app  view on Meta::CPAN


            </div>

              <div class="post-thumb">
                <!-- theme suggests 1300x500 -->
                <img alt="Workers on a scaffold" src="/blog/2017/12/15/day-15-start-a-new-yancy-app/scaffold.jpg">
              </div>

            <div class="post-content">

              <section id="section-1">
                  <p><a href="http://metacpan.org/pod/Yancy">Yancy</a> is a new content management
plugin for the <a href="http://mojolicious.org">Mojolicious web framework</a>.
Yancy allows you to easily administrate your site’s content just by
describing it using <a href="http://json-schema.org">JSON Schema</a>. Yancy
supports <a href="http://metacpan.org/pod/Yancy::Backend">multiple backends</a>, so
your site&#39;s content can be in
<a href="http://metacpan.org/pod/Yancy::Backend::Pg">Postgres</a>,
<a href="http://metacpan.org/pod/Yancy::Backend::Mysql">MySQL</a>, and
<a href="http://metacpan.org/pod/Yancy::Backend::Dbic">DBIx::Class</a>.</p>

              </section>
              <section id="section-2">
                  <h2>Demonstration</h2>

<p>For an demonstration application, let’s create a simple blog using
<a href="http://mojolicious.org/perldoc/Mojolicious/Lite">Mojolicious::Lite</a>.
First we need to create a database schema for our blog posts. Let&#39;s use
<a href="http://metacpan.org/pod/Mojo::Pg">Mojo::Pg</a> and its <a href="http://metacpan.org/pod/Mojo::Pg::Migrations">migrations
feature</a> to create a table
called &quot;blog&quot; with fields for an ID, a title, a date, some markdown, and
some HTML.</p>

devdata/https_mojolicious.io_blog_2017_12_15_day-15-start-a-new-yancy-app  view on Meta::CPAN

Server available at http://127.0.0.1:3000
</code></pre>

<p><img alt="The rendered blog post with our template" src="blog-post.png"></p>

<p>Yancy provides a rapid way to get started building a Mojolicious
application (above Mojolicious’s already rapid development). Yancy
provides a basic level of content management so site developers can
focus on what makes their site unique.</p>

              </section>
              <small><p><a href="http://www.publicdomainpictures.net/view-image.php?image=6416">Image</a> in the public domain.</p>
</small>

              <p class="tags">
                <span>Tagged in </span>:
                  <a href="/blog/tag/advent/">advent</a>,
                  <a href="/blog/tag/app/">app</a>
              </p>


                  <div class="bio cf">

                      <div class="gravatar">
                        <img alt="author image" src="https://secure.gravatar.com/avatar/4bdc4922059d58a0fcbf8f35652dc254.png">
                      </div>
                      <div class="about">
                        <h5>Doug Bell</h5>
                        <p>Doug (<a href="http://preaction.me">preaction</a>) is a long time Perl user.
He is the current maintainer of <a href="http://www.cpantesters.org/">CPAN Testers</a> and the author of many <a href="https://metacpan.org/author/PREACTION">CPAN modules</a> including the <a href="http://preaction.me/statocles/">Statocles</a> blog e...

                      </div>

                  </div>

              <ul class="post-nav cf">
                  <li class="prev"><a href="/blog/2017/12/14/day-14-you-promised-to-call/index.html" rel="prev"><strong>Previous Article</strong> Day 14: You Promised To Call!</a></li>
                  <li class="next"><a href="/blog/2017/12/16/day-16-the-secret-life-of-sessions/index.html" rel="next"><strong>Next Article</strong> Day 16: The Secret Life of Sessions </a></li>
              </ul>

            </div>

        </article>


      </div>

      <div class="four columns end" id="secondary">
        <aside id="sidebar">
          







<div class="widget widget_tag_cloud">

devdata/https_mojolicious.io_blog_2017_12_16_day-16-the-secret-life-of-sessions  view on Meta::CPAN

  <meta content="width=device-width, initial-scale=1, maximum-scale=1" name="viewport">

  <link href="/theme/css/default.css" rel="stylesheet">
  <link href="/theme/css/layout.css" rel="stylesheet">
  <link href="/theme/css/media-queries.css" rel="stylesheet">
  <link href="/theme/css/statocles.css" rel="stylesheet">

  <!-- twitter and opengraph -->
  <meta content="summary" name="twitter:card">
      <meta content="@joelaberger" name="twitter:creator">
  <meta content="https://mojolicious.io/blog/2017/12/16/day-16-the-secret-life-of-sessions/" property="og:url">
  <meta content="Day 16: The Secret Life of Sessions" property="og:title">
    <meta content="Use the session secret effectively to protect users without inconveniencing them." property="og:description">
    <meta content="https://mojolicious.io/blog/2017/12/16/day-16-the-secret-life-of-sessions/scrabble.jpg" property="og:image">
    <meta content="summary_large_image" name="twitter:card">

  <script src="/theme/js/modernizr.js"></script>

      <link href="//cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/styles/sunburst.min.css" rel="stylesheet">

  <title>Day 16: The Secret Life of Sessions - mojolicious.io</title>
  <meta content="Joel Berger" name="author">
  <meta content="Statocles 0.093" name="generator">
  <link href="/static/favicon.ico" rel="shortcut icon">

devdata/https_mojolicious.io_blog_2017_12_16_day-16-the-secret-life-of-sessions  view on Meta::CPAN


                  <time class="date" datetime="2017-12-16">Dec 16, 2017</time>
                  

              </p>

            </div>

              <div class="post-thumb">
                <!-- theme suggests 1300x500 -->
                <img alt="Pile of Scrabble tiles" src="/blog/2017/12/16/day-16-the-secret-life-of-sessions/scrabble.jpg">
              </div>

            <div class="post-content">

              <section id="section-1">
                  <p>As you all know, HTTP is a stateless protocol.
In Mojolicious applications the session is used to maintain state between requests.
These sessions are managed by the application&#39;s <a href="http://mojolicious.org/perldoc/Mojolicious/#sessions">session manager</a>.</p>

<p>During each request, the <a href="http://mojolicious.org/perldoc/Mojolicious/Controller#session">session</a> is just another hash reference attached to the controller, in some ways like the <a href="/blog/2017/12/02/day-2-the-stash">stash</a>, exc...
Mojolicious does this by encoding the structure, first as JSON then Base64.
It then signs the resulting string using HMAC-SHA1 and the application&#39;s <a href="http://mojolicious.org/perldoc/Mojolicious#secrets">secret</a> to prevent tampering and stores it as a cookie on the response to the client.</p>

<p>On subsequent requests, the client sends the cookie along with the request (as cookies do).
Mojolicious then checks if the document and signature validate against the secret, if so the cookie is decoded and made available again via the session method.</p>

<p>Two important things to note.
First, though the data is safe from tampering, it isn&#39;t encrypted; a savvy user can decode the cookie and see the stored data, so don&#39;t put anything in it that shouldn&#39;t be seen.
Second, this is only useful if the secret is strong and safe.
If not, the client could forge a cookie that appeared to come from your application, possibly with catastrophic results!
So while Mojolicious makes it easy, a little care can go a long way toward keeping your session data safe and trusted.</p>

              </section>
              <section id="section-2">
                  <h2>A Simple Session Example</h2>

<p>A very simple application that could use the session would be to store a counter of the user&#39;s visits to the site.</p>

<pre><code class="hljs"><span class="hljs-keyword">use</span> <span class="hljs-function">Mojolicious::Lite</span>;

get &#39;<span class="hljs-string">/</span>&#39; =&gt; <span class="hljs-keyword">sub </span>{
  <span class="hljs-keyword">my</span> <span class="hljs-type">$c</span> = <span class="hljs-function">shift</span>;
  <span class="hljs-keyword">my</span> <span class="hljs-type">$count</span> = ++<span class="hljs-type">$c</span>-&gt;<span class="hljs-type">session</span>-&gt;{count};
  <span class="hljs-keyword">my</span> <span class="hljs-type">$message</span> = &quot;<span class="hljs-string">You have visited </span><span class="hljs-type">$count</span><span class="hljs-string"> time</span>&quot;;

devdata/https_mojolicious.io_blog_2017_12_16_day-16-the-secret-life-of-sessions  view on Meta::CPAN

</code></pre>

<p>When you run this application</p>

<pre><code>$ perl myapp.pl daemon
</code></pre>

<p>and visit <code>localhost:3000</code> you should see a counter that increments on each request.
That data is stored on the client (e.g. in the browser) between each request and is incremented on the server before sending it back to the client.
Each response is a new cookie with the new session data and a new cookie expiration time, <a href="http://mojolicious.org/perldoc/Mojolicious/Sessions#default_expiration">defaulting to one hour</a> from issue.
This also therefore implies that as long as you visit often enough (before any one cookie expires) and your data continues to validate against the secret, your session can last forever.</p>

<h2>Secret Security</h2>

<p>Now, one other thing you should see is that in your application&#39;s log output, you should have a message like</p>

<pre><code>Your secret passphrase needs to be changed
</code></pre>

<p>This happens because you are using the default secret for the application.
This default is just the name of the script, as you can see via the <a href="/blog/2017/12/05/day-5-your-apps-built-in-commands">eval command</a></p>

<pre><code>$ perl myapp.pl eval -V &#39;app-&gt;secrets&#39;
[
  &quot;myapp&quot;
]
</code></pre>

<p>This secret is not secure both because it is short and because it is easy to guess.
With a trivial application like this you might not need to worry about forgery, as you would with say a session that tracks user logins.
But who knows, perhaps you are going to award a prize to the user for the most requests made!
Let&#39;s play it safe.</p>

<p>The secret isn&#39;t something you need to remember, it just has to be hard to guess.
So I suggest you pick a random one.
You could generate 12 characters of random text using</p>

<pre><code>$ &lt;/dev/urandom base64 | head -c 12
yuIB7m88wS07
</code></pre>

<p>Once you have that you have to tell the app to use it.
Create a file called <code>myapp.conf</code> and set it up like so</p>

<pre><code class="hljs">{
  secrets =&gt; [&#39;<span class="hljs-string">yuIB7m88wS07</span>&#39;],
}
</code></pre>

<p>Where the value is whatever secret you generated.
Notice that it is in an array reference, we&#39;ll talk about why soon.
Before that, let&#39;s tweak the application so that it uses that configuration</p>

<pre><code class="hljs"><span class="hljs-keyword">use</span> <span class="hljs-function">Mojolicious::Lite</span>;

plugin &#39;<span class="hljs-string">Config</span>&#39;;

<span class="hljs-keyword">if</span> (<span class="hljs-keyword">my</span> <span class="hljs-type">$secrets</span> = app-&gt;config-&gt;{secrets}) {
  app-&gt;secrets(<span class="hljs-type">$secrets</span>);
}

get &#39;<span class="hljs-string">/</span>&#39; =&gt; <span class="hljs-keyword">sub </span>{
  <span class="hljs-keyword">my</span> <span class="hljs-type">$c</span> = <span class="hljs-function">shift</span>;
  <span class="hljs-keyword">my</span> <span class="hljs-type">$count</span> = ++<span class="hljs-type">$c</span>-&gt;<span class="hljs-type">session</span>-&gt;{count};
  <span class="hljs-keyword">my</span> <span class="hljs-type">$message</span> = &quot;<span class="hljs-string">You have visited </span><span class="hljs-type">$count</span><span class="hljs-string"> time</span>&quot;;
  <span class="hljs-type">$message</span> .= &#39;<span class="hljs-string">s</span>&#39; <span class="hljs-keyword">unless</span> <span class="hljs-type">$count</span> == <span class="hljs-number">1</span>;
  <span class="hljs-type">$c</span>-&gt;<span class="hljs-type">render</span>(text =&gt; <span class="hljs-type">$message</span>);
};

app-&gt;start;

</code></pre>

<p>If it finds a <code>secrets</code> parameter in your configuration, it will set it as the <code>secrets</code> on your application.
Since you have one in your new configuration file, it should set that property and the warning should go away.
Congratulations, you have a safer application already!</p>

<p>If sometime later, you suspect that someone has guessed your secret, or if your secret leaks out, you can change that secret and restart your application.
This will protect your application from malicious users.</p>

<p>For your clients, this will have the jarring effect that all existing sessions will be invalidated.
In the example application the counter would be reset.
If instead the session were being used to keep users logged in, they would suddenly be logged out.
If it was for tracking a shopping cart ... no more shopping cart.</p>

<p>This can actually be useful even if your secret is safe but you want to force-invalidate sessions for some other reason, like say your application was generating corrupt data or worse.
Generally, however, this is something you&#39;d like to avoid.</p>

<h2>A Random Secret?</h2>

<p>Now perhaps you are asking yourself, if Mojolicious knows I&#39;m using the insecure default couldn&#39;t it just set a random secret?
Sure, and you could do so yourself too if you wanted.
Something as easy as this would set a random secret.</p>

<pre><code class="hljs"><span class="hljs-keyword">use</span> <span class="hljs-function">Mojolicious::Lite</span>;

<span class="hljs-comment"># NOT RECOMMENDED!</span><span class="hljs-comment">
</span>app-&gt;secrets([<span class="hljs-function">rand</span>]);

get &#39;<span class="hljs-string">/</span>&#39; =&gt; <span class="hljs-keyword">sub </span>{
  <span class="hljs-keyword">my</span> <span class="hljs-type">$c</span> = <span class="hljs-function">shift</span>;
  <span class="hljs-keyword">my</span> <span class="hljs-type">$count</span> = ++<span class="hljs-type">$c</span>-&gt;<span class="hljs-type">session</span>-&gt;{count};
  <span class="hljs-keyword">my</span> <span class="hljs-type">$message</span> = &quot;<span class="hljs-string">You have visited </span><span class="hljs-type">$count</span><span class="hljs-string"> time</span>&quot;;
  <span class="hljs-type">$message</span> .= &#39;<span class="hljs-string">s</span>&#39; <span class="hljs-keyword">unless</span> <span class="hljs-type">$count</span> == <span class="hljs-number">1</span>;
  <span class="hljs-type">$c</span>-&gt;<span class="hljs-type">render</span>(text =&gt; <span class="hljs-type">$message</span>);
};

app-&gt;start;

</code></pre>

<p>So why isn&#39;t this recommended?
Because it would mean that each time you started the server you would get a new secret.
As with the case of changing your secret intentionally above, all existing sessions would be invalidated any time you wanted to reboot a server or restart the server process.
Additionally you could only use one server, any load balancing scenario would result in different secrets on different hosts, your users would randomly invalidate their sessions depending on which server they hit!</p>

<h2>Forward Secrecy</h2>

<p>Just as you have to change application passwords from time to time, so too you need to change your secret.
In a brute force scenario, a nefarious user could take one of their cookies and try to reverse engineer the secret that was used to generate it.</p>

<p>But wait!
You just said that changing the secret to prevent brute forcing will invalidate all of our sessions!</p>

<p>Remember when I pointed out that rather than being a single value, <code>secrets</code> was an array reference?
Well when Mojolicious generates a session cookie, it does so using the first value in the array reference.
However, when it validates session signatures, it will check them against each secret in the array.</p>

<p>So, say the time has come to rotate our secrets so we generate another</p>

<pre><code>$ &lt;/dev/urandom base64 | head -c 12
w8S4b+90CWwf
</code></pre>

<p>add that value to the configuration file</p>

<pre><code class="hljs">{
  secrets =&gt; [
    &#39;<span class="hljs-string">w8S4b+90CWwf</span>&#39;,
    &#39;<span class="hljs-string">yuIB7m88wS07</span>&#39;,
  ],
}
</code></pre>

<p>and restart the application.
Any requests with valid sessions will still work.
The reply they receive will contain a new session cookie, as always, but this time it will be issued using the new secret!</p>

<p>Requests issued by the old credentials will slowly be replaced by new ones as clients each make their first requests following the change.
Once you wait long enough that any valid session cookie would have expired, you can remove the old secret from the configuration and restart again.</p>

<h2>Restarting</h2>

<p>This is a good time to mention <a href="http://mojolicious.org/perldoc/Mojolicious/Guides/Cookbook#Hypnotoad"><code>hypnotoad</code></a>.
It is Mojolicious&#39; recommended production application server.
It has many of the same characteristics as the <a href="http://mojolicious.org/perldoc/Mojolicious/Guides/Cookbook#Pre-forking"><code>prefork</code></a> server but with some tuned settings and one killer feature, <a href="http://mojolicious.org/perld...

<p>Note that on native Windows, <code>hypnotoad</code> will not work.
That said, it works great on the new <a href="https://blogs.msdn.microsoft.com/wsl/">Windows Subsystem for Linux</a>!</p>

<p>A major usage difference is that hypnotoad (for technical reasons) can&#39;t use command line parameters.
Instead it takes its parameters via configuration.
It also starts on port <code>8080</code> rather than <code>3000</code> to prevent accidentally exposing your development servers unexpectedly.
For now however, let&#39;s set it back, more for an example than any particular reason.</p>

<pre><code class="hljs">{
  secrets =&gt; [
    &#39;<span class="hljs-string">w8S4b+90CWwf</span>&#39;,
    &#39;<span class="hljs-string">yuIB7m88wS07</span>&#39;,
  ],
  hypnotoad =&gt; {
    <span class="hljs-function">listen</span> =&gt; [&#39;<span class="hljs-string">http://*:3000</span>&#39;],
  },
}
</code></pre>

<p>Rather than starting you application like</p>

devdata/https_mojolicious.io_blog_2017_12_16_day-16-the-secret-life-of-sessions  view on Meta::CPAN

<p>The application should again be available on port <code>3000</code>.</p>

<p>You&#39;ll see that rather than staying in the foreground like with <code>daemon</code> the command returns and you get your prompt back.
Don&#39;t worry, as long as it said that it started it should stay running.
To stop the application, run the same commmand but also pass a <code>-s</code> switch</p>

<pre><code>$ hypnotoad -s myapp.pl
</code></pre>

<p>The really interesting thing happens when restarting a running application.
Say you&#39;ve rolled your secrets and want to restart the application to use it.
Simply run the command as before, just like when you started it up.</p>

<p>Any requests currently being served by the old server processes will continue to be served by them (up to some timeout).
Any new requests will be served by new processes using the new configuration.
You don&#39;t cut off any users in the process.</p>

<p>Actually <code>hypnotoad</code> can be used to zero downtime restart for more reasons than just configuration changes.
It can handle changes to your application, updating dependencies, or even upgrading your version of Perl itself!</p>

<p>For now though, we&#39;re just satisfied that clients are none the wiser that you rolled the application secret out from under them without losing any connections nor invalidating any sessions.</p>

              </section>
              <small><p><a href="https://commons.wikimedia.org/w/index.php?curid=54930070">Image</a> by <a class="external text" href="https://www.flickr.com/people/30478819@N08" rel="nofollow">Marco Verch</a> - <a class="external text" href="https:/...
</small>

              <p class="tags">
                <span>Tagged in </span>:
                  <a href="/blog/tag/advent/">advent</a>,
                  <a href="/blog/tag/session/">session</a>
              </p>


                  <div class="bio cf">

                      <div class="gravatar">
                        <img alt="author image" src="https://secure.gravatar.com/avatar/cc767569f5863a7c261991ee5b23f147">
                      </div>
                      <div class="about">
                        <h5>Joel Berger</h5>
                        <p>Joel has Ph.D. in Physics from the University of Illinois at Chicago.
He an avid Perl user and <a href="https://metacpan.org/author/JBERGER">author</a> and is a member of the Mojolicious Core Team.</p>

                      </div>

                  </div>

devdata/https_mojolicious.io_blog_2017_12_16_day-16-the-secret-life-of-sessions  view on Meta::CPAN

                  <li class="next"><a href="/blog/2017/12/17/day-17-the-wishlist-app/index.html" rel="next"><strong>Next Article</strong> Day 17: The Wishlist App </a></li>
              </ul>

            </div>

        </article>


      </div>

      <div class="four columns end" id="secondary">
        <aside id="sidebar">
          







<div class="widget widget_tag_cloud">

devdata/https_mojolicious.io_blog_2017_12_17_day-17-the-wishlist-app  view on Meta::CPAN


            </div>

              <div class="post-thumb">
                <!-- theme suggests 1300x500 -->
                <img alt="Living room, Christmas tree, and presents" src="/blog/2017/12/17/day-17-the-wishlist-app/xmas_tree.jpg">
              </div>

            <div class="post-content">

              <section id="section-1">
                  <p>For today&#39;s article, I really wanted to demonstrate concepts using a practical example appliation.
It is possible I let the exaxmple get away from me!</p>

<p>In today&#39;s article I indend to show how to use template composition techniques to produce a wishlist app.
We will cover <a href="http://mojolicious.org/perldoc/Mojolicious/Guides/Rendering#Layouts">layouts</a>, <a href="http://mojolicious.org/perldoc/Mojolicious/Guides/Rendering#Partial-templates">partial templates</a>, <a href="http://mojolicious.org/pe...

<p>The data model is admittedly rough, however I think my plan will be to make that a feature and not a bug.
Today we will example concepts mostly relating to the templates, then in tomorrows post I will migrate the model from using the simplistic persistence of <a href="https://metacpan.org/pod/DBM::Deep">DBM::Deep</a> that it uses now to <a href="https://...

              </section>
              <section id="section-2">
                  <p>At that point I hope to put the application into a repository of its own.
In the meantime however, you can see the application in the source for this <a href="https://github.com/MojoliciousDotIO/mojolicious.io/tree/master/blog/2017/12/17/day-17-the-wishlist-app/wishlist">article</a>.
To run it, you will need to install two additional modules, DBM::Deep and <a href="https://metacpan.org/pod/LinkEmbedder">LinkEmbedder</a>.</p>

<pre><code>$ cpanm Mojolicious DBM::Deep LinkEmbedder
</code></pre>

<h2>Layouts</h2>

<p>Most web sites have a defined style and layout between pages.
A header bar, a sidebar for navigation, a footer.
The content of each might change slightly between pages but the similarity is remarkable.</p>

<p>Do the developers copy and paste this logic between pages?
Certainly not!</p>

<p>The first tool of the trade is a layout template.
This is a template that will contain the results of rendering some inner template.
This will usually contain the outermost tags, like <code>&lt;html&gt;</code>, <code>&lt;head&gt;</code>, and <code>&lt;body&gt;</code>.
They will likely also establish any structure that exists on all of the pages, like navigation and sidebar sections.</p>

<p>Let&#39;s look at the layout that our wishlist application</p>

<pre><code class="hljs">&lt;!DOCTYPE html&gt;
&lt;html&gt;
  &lt;head&gt;
    &lt;meta charset=&quot;<span class="hljs-string">utf-8</span>&quot;&gt;
    &lt;meta http-equiv=&quot;<span class="hljs-string">X-UA-Compatible</span>&quot; content=&quot;<span class="hljs-string">IE=edge</span>&quot;&gt;
    &lt;meta name=&quot;<span class="hljs-string">viewport</span>&quot; content=&quot;<span class="hljs-string">width=device-width, initial-scale=1</span>&quot;&gt;

devdata/https_mojolicious.io_blog_2017_12_17_day-17-the-wishlist-app  view on Meta::CPAN


</code></pre>

<p><small>templates/login.html.ep</small></p>

<p>Immediately you can see that there are a few statements at the top.
These set the layout to our default one above and set the title key for the page.
It is important to realize that this page is rendered <strong>first</strong> before any layout is rendered.</p>

<p>After the template renders, Mojolicious will notice that a layout key was set and as a result it will render the layout with the result of the primary template rendering available as the default content buffer.
As we saw before, that content will be placed inside the <code>#main</code> section of the page.
However, in the process of rendering the primary template, the title was also set.
Since the layout is rendered afterwards, this value is now available to set the <code>&lt;title&gt;</code> tag at the top of the page.</p>

<p>While this may seem obvious, it is actually quite remarkable.
If the page had been rendered all in order, the value would not have been set in time to be used there at the top of the page.
Knowing the rendering order is therefore very important to understanding the rendering process.</p>

<h2>The Application</h2>

<p>I&#39;ve gone about as far as is practical without showing you, dear reader, what the actual application script looks like.</p>

devdata/https_mojolicious.io_blog_2017_12_17_day-17-the-wishlist-app  view on Meta::CPAN

</code></pre>

<p><small>wishlist.pl</small></p>

<h3>Helpers</h3>

<p>I won&#39;t go into great detail today as much of the model logic will be replaced in tomorrow&#39;s article.
Still, in broad strokes, we define a persistent hash structure, the keys of which are users and the values are hashes of information.</p>

<p>Once you login, your name is stored in the <a href="http://mojolicious.org/perldoc/Mojolicious/Controller#session"><code>session</code></a> and in this hash.
While I haven&#39;t followed the <a href="https://mojolicious.io/blog/2017/12/16/day-16-the-secret-life-of-sessions/">best practices for sessions from yesterday</a>, you certainly could and should if this data mattered to you.
But also, no authentication is attempted, this is a personal wishlist app, hopefully none of your friends are going to play the Grinch on you!</p>

<p>The <code>user</code> helper is especially clever.
You can pass it a name for lookup, if that isn&#39;t provided then a name is looked for in the stash and the session in turn.
In this way you are looking up a specific user, the user being referenced by the page, or the logged in user.</p>

<p>There is also a helper that uses <a href="https://metacpan.org/pod/LinkEmbedder">LinkEmbedder</a> to look up information about a link and return it.
That is used when a user pastes a url that they want to add to their list.
LinkEmbedder will fetch that page and scrape it for metadata using several open protocols and falling back onto heuristics if possible.
It will then return the information and an short HTML representation of that resource.</p>

devdata/https_mojolicious.io_blog_2017_12_17_day-17-the-wishlist-app  view on Meta::CPAN

    &lt;%== <span class="hljs-type">$link</span>-&gt;<span class="hljs-type">html</span> %&gt;
  &lt;/div&gt;
&lt;/div&gt;

</code></pre>

<p><small>templates/add.html.ep</small></p>

<p>Beyond being interesting to see how the link is used to embed HTML into the page, we also see our first uses of named content buffers via <a href="http://mojolicious.org/perldoc/Mojolicious/Plugin/DefaultHelpers#content_for"><code>content_for</cod...
These add styling that is specific to the page into the <code>&lt;head&gt;</code> tag and inject a panel into the sidebar.
Once this page renders, again before the layout is rendered, the content of that section is available in the <code>sidebar</code> buffer.</p>

<p>The result is a tiny form that contains the data to be stored if the user wants to add it to their wishlist.
Because the resulting main page might be quite large, and I want the user to have easy access to decide if they want to add the item, I&#39;ve placed it in the left hand column.
Perhaps this is bad UX, but for educational purposes, it shows how these buffers can be used.</p>

<p>We also see our first example of <a href="http://mojolicious.org/perldoc/Mojolicious/Plugin/DefaultHelpers#include"><code>include</code></a>.
When called, the renderer immediately renders the template specified and returns the result.</p>

<pre><code class="hljs">&lt;div class=&quot;<span class="hljs-string">panel panel-default</span>&quot;&gt;
  &lt;div class=&quot;<span class="hljs-string">panel-body</span>&quot;&gt;

devdata/https_mojolicious.io_blog_2017_12_17_day-17-the-wishlist-app  view on Meta::CPAN


<p><small>templates/partial/add_url.html.ep</small></p>

<p>This form calls back to the add template we saw earlier.</p>

<h2>Moving On</h2>

<p>As I said before, I&#39;m looking forward to making a more complete application with proper storage for tomorrow.
That said, the code shown today already works and is quite useful, even for as small as it is!</p>

              </section>
              <small><p><a href="https://pxhere.com/en/photo/1056078">Image</a> in the Public Domain.</p>
</small>

              <p class="tags">
                <span>Tagged in </span>:
                  <a href="/blog/tag/advent/">advent</a>,
                  <a href="/blog/tag/rendering/">rendering</a>,
                  <a href="/blog/tag/templates/">templates</a>,
                  <a href="/blog/tag/example/">example</a>,
                  <a href="/blog/tag/wishlist/">wishlist</a>
              </p>


                  <div class="bio cf">

                      <div class="gravatar">
                        <img alt="author image" src="https://secure.gravatar.com/avatar/cc767569f5863a7c261991ee5b23f147">
                      </div>
                      <div class="about">
                        <h5>Joel Berger</h5>
                        <p>Joel has Ph.D. in Physics from the University of Illinois at Chicago.
He an avid Perl user and <a href="https://metacpan.org/author/JBERGER">author</a> and is a member of the Mojolicious Core Team.</p>

                      </div>

                  </div>

              <ul class="post-nav cf">
                  <li class="prev"><a href="/blog/2017/12/16/day-16-the-secret-life-of-sessions/index.html" rel="prev"><strong>Previous Article</strong> Day 16: The Secret Life of Sessions</a></li>
                  <li class="next"><a href="/blog/2017/12/18/day-18-the-wishlist-model/index.html" rel="next"><strong>Next Article</strong> Day 18: The Wishlist Model </a></li>
              </ul>

            </div>

        </article>


      </div>

      <div class="four columns end" id="secondary">
        <aside id="sidebar">
          







<div class="widget widget_tag_cloud">

devdata/https_mojolicious.io_blog_2017_12_18_day-18-the-wishlist-model  view on Meta::CPAN


            </div>

              <div class="post-thumb">
                <!-- theme suggests 1300x500 -->
                <img alt="Still Life: Vase with Pink Roses by Vincent van Gogh" src="/blog/2017/12/18/day-18-the-wishlist-model/van_gogh_still_life.jpg">
              </div>

            <div class="post-content">

              <section id="section-1">
                  <p><a href="https://mojolicious.io/blog/2017/12/17/day-17-the-wishlist-app/">Yesterday</a> we discussed templates features like layouts, partial templates, and content buffers.
We motivated the discussion by introducing a fully functioning example application that tracked user&#39;s Christmas wishlists.
That application did lack sophistication in the area of data storage, using <a href="https://metacpan.org/pod/DBM::Deep">DBM::Deep</a> for quickly getting a basic persistence layer.
While that worked well enough to demonstrate template functionality it was no triumph of the model layer.
Indeed some very hack techniques are used, especially in manipulating wishlist items, since there was no unique record ids.</p>

<p>Well as promised I have created a <a href="https://github.com/jberger/Wishlist">repository</a> for the application on Github.
I have also added several tags.
While development on the application may continue, those tags will remain for future readers.</p>

<p>The initial form of the application (as seen in yesterday&#39;s post) is tagged <a href="https://github.com/jberger/Wishlist/tree/blog_post/dbm_deep"><code>blog_post/dbm_deep</code></a>.
You are then invited to step through the commits <a href="https://github.com/jberger/Wishlist/compare/blog_post/dbm_deep...blog_post/full_app">from that one to <code>blog_post/full_app</code></a> to follow along as I port it from a Lite to a Full app...

<p>This article will briefly discuss the application as it exists in the next tag, <a href="https://github.com/jberger/Wishlist/tree/blog_post/sqlite_model"><code>blog_post/sqlite_model</code></a>.
At this point I have replaced DBM::Deep with <a href="https://metacpan.org/pod/Mojo::SQLite">Mojo::SQLite</a>, written a rudimentary model layer for it, and connected the two with the application via helpers.
Let&#39;s see how that improves the application and in the meantime, get a look at idiomatic database access in Mojolicious!</p>

              </section>
              <section id="section-2">
                  <h2>Model View Controller</h2>

<p>Most modern web applications adhere to a pattern called <a href="https://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller">Model View Controller</a> or MVC.
Much has been written about MVC, more than could be conveyed here.
Quickly though, the view is how data is displayed, the template.
The model is the database, both read and write access, and how to manipulated it.
This is usually thought of as the &quot;business logic&quot;.
Finally the controller is supposed to be the minimal amount of logic that can be used to connect the two and process web requests.</p>

<p>In Perl almost all relational database access is via <a href="https://metacpan.org/pod/DBI">DBI</a> whether directly or indirectly.

devdata/https_mojolicious.io_blog_2017_12_18_day-18-the-wishlist-model  view on Meta::CPAN

  <span class="hljs-keyword">return</span> <span class="hljs-type">$sqlite</span>;
};

<span class="hljs-keyword">sub </span><span class="hljs-function">startup</span> {
  <span class="hljs-keyword">my</span> <span class="hljs-type">$app</span> = <span class="hljs-function">shift</span>;

  <span class="hljs-type">$app</span>-&gt;<span class="hljs-type">plugin</span>(&#39;<span class="hljs-string">Config</span>&#39; =&gt; {
    default =&gt; {},
  });

  <span class="hljs-keyword">if</span> (<span class="hljs-keyword">my</span> <span class="hljs-type">$secrets</span> = <span class="hljs-type">$app</span>-&gt;<span class="hljs-type">config</span>-&gt;{secrets}) {
    <span class="hljs-type">$app</span>-&gt;<span class="hljs-type">secrets</span>(<span class="hljs-type">$secrets</span>);
  }

  <span class="hljs-type">$app</span>-&gt;<span class="hljs-type">helper</span>(<span class="hljs-function">link</span> =&gt; <span class="hljs-keyword">sub </span>{
    <span class="hljs-keyword">my</span> <span class="hljs-type">$c</span> = <span class="hljs-function">shift</span>;
    state <span class="hljs-type">$le</span> = LinkEmbedder-&gt;new;
    <span class="hljs-keyword">return</span> <span class="hljs-type">$le</span>-&gt;<span class="hljs-type">get</span>(<span class="hljs-type">@_</span>);
  });

  <span class="hljs-type">$app</span>-&gt;<span class="hljs-type">helper</span>(model =&gt; <span class="hljs-keyword">sub </span>{
    <span class="hljs-keyword">my</span> <span class="hljs-type">$c</span> = <span class="hljs-function">shift</span>;

devdata/https_mojolicious.io_blog_2017_12_18_day-18-the-wishlist-model  view on Meta::CPAN


<p><small>lib/Wishlist/Controller/List.pm</small></p>

<p>While all the same business logic is accomplished, this time the semantic model methods are used rather than manipulating the data directly.
THe methods establish what they want to be done not how to do it.
This is much better MVC and will serve you better in the long run.</p>

<p>So is this the end of our discussion of the Wishlist app?
Who can say?</p>

              </section>
              <small><p><a href="https://commons.wikimedia.org/w/index.php?curid=10510831">Image</a> &quot;Still Life: Vase with Pink Roses&quot; by <a class="extiw" href="https://en.wikipedia.org/wiki/en:Vincent_van_Gogh" title="w:en:Vincent van Gog...
</small>

              <p class="tags">
                <span>Tagged in </span>:
                  <a href="/blog/tag/advent/">advent</a>,
                  <a href="/blog/tag/model/">model</a>,
                  <a href="/blog/tag/example/">example</a>,
                  <a href="/blog/tag/wishlist/">wishlist</a>
              </p>


                  <div class="bio cf">

                      <div class="gravatar">
                        <img alt="author image" src="https://secure.gravatar.com/avatar/cc767569f5863a7c261991ee5b23f147">
                      </div>
                      <div class="about">
                        <h5>Joel Berger</h5>
                        <p>Joel has Ph.D. in Physics from the University of Illinois at Chicago.
He an avid Perl user and <a href="https://metacpan.org/author/JBERGER">author</a> and is a member of the Mojolicious Core Team.</p>

                      </div>

                  </div>

devdata/https_mojolicious.io_blog_2017_12_18_day-18-the-wishlist-model  view on Meta::CPAN

                  <li class="next"><a href="/blog/2017/12/19/day-19-make-your-app-installable/index.html" rel="next"><strong>Next Article</strong> Day 19: Make Your App Installable </a></li>
              </ul>

            </div>

        </article>


      </div>

      <div class="four columns end" id="secondary">
        <aside id="sidebar">
          







<div class="widget widget_tag_cloud">

devdata/https_mojolicious.io_blog_2017_12_19_day-19-make-your-app-installable  view on Meta::CPAN


            </div>

              <div class="post-thumb">
                <!-- theme suggests 1300x500 -->
                <img alt="Container ship loading at the dock" src="/blog/2017/12/19/day-19-make-your-app-installable/container_ship.jpg">
              </div>

            <div class="post-content">

              <section id="section-1">
                  <p>Thus far we have always run our applications from the local directory.
That is usually the project root directory and/or the repository checkout.
But did you know that with only a few changes you can make your application installable like other Perl modules?</p>

<p>While, you must do this if you want to upload your application to CPAN, even if you don&#39;t intend to do that, it still has benefits.
You can install the application on your personal computer, especially if you want to be able to run the script while in other directories.
Having an installable module also means that you can use a so-called &quot;DarkPAN&quot; and related tools to build yourself a local &quot;CPAN&quot;.
If you have multiple Perl modules at your company (or as part of any project) using a DarkPAN can ease integration and deployment immensely!
N.B. there is even a DarkPAN tool written using Mojolicious called <a href="https://metacpan.org/pod/App::opan">opan</a>.</p>

<p>And hey if you needed even more more reason, it cleans up your project root directory somewhat too!</p>

              </section>
              <section id="section-2">
                  <h2>The Challenge</h2>

<p>The hardest part of this process is managing static files.
There are several Perl install tools that each handle static files slightly differently.
Some will happily bundle any files in the project directory, others will only bundle Perl files by default.</p>

<p>Then once installed that bundle location is usually different that what it was during development (even relative to the project).
It can be a challenge to make it so that you application can find those file both during development and after installation.</p>

<h2>TIMTOWTDI</h2>

<p>Before we get started, I should mention that there are many ways to accomplish this task.
If your application small and already located in a <code>script</code> directory and has no external static files, you&#39;re probably already done!
That isn&#39;t the case for most applications of any real size, however.</p>

<p>If you&#39;ve read the <a href="http://mojolicious.org/perldoc/Mojolicious/Guides/Cookbook">Cookbook</a>, you&#39;ve already seen that there is a section on <a href="http://mojolicious.org/perldoc/Mojolicious/Guides/Cookbook#Making-your-applicatio...
While that&#39;s true, it makes its recommendations without using external modules and for one specific installation tool.
It also assumes that your application <a href="http://mojolicious.org/perldoc/Mojolicious#home"><code>home</code></a> should be related to the installation directory, which isn&#39;t always the case.</p>

<p>Yours truly has even written a <a href="https://metacpan.org/pod/Mojolicious::Plugin::InstallablePaths">module</a> that was intended to ease this process somewhat.
While it does that, and I don&#39;t intend to deprecate it, I think there are even easier patterns now.</p>

<h2>The Share Directory</h2>

<p>Perl has a lesser known and somewhat informal functionality for bundling static files called a &quot;share directory&quot;.
Create a directory in your project root called <code>share</code> which will serve for this purpose.

devdata/https_mojolicious.io_blog_2017_12_19_day-19-make-your-app-installable  view on Meta::CPAN

</code></pre>

<p>whose default is <code>share</code>.
I&#39;m sure other installers have ways to handle it too.</p>

<h2>File::Share Saves the Day</h2>

<p>Since we earlier moved the location of templates and static files, we now need to tell the application where we put them.
The major innovation that makes this method possible and so painless is the module <a href="https://metacpan.org/pod/File::Share">File::Share</a>.
While it isn&#39;t <a href="https://metacpan.org/pod/File::ShareDir">the original module</a> used to locate share directories after installation, it is the best one since it also works before hand during development too.
To do so it uses the heuristic of looking to see if a directory exists named <code>share</code> in that particular location (and a few checks for sanity), thus the second reason we call the directory that.</p>

<p>When used we get the absolute path to the share directory of your distribution.
Usually the name of the distribution is the name of your main module with the <code>::</code> replaced by <code>-</code>.</p>

<h2>Use in Mojolicious Apps</h2>

<p>To use File::Share in a Mojolicious (Full) app I recommend wrapping it in a <a href="http://mojolicious.org/perldoc/Mojo/File">Mojo::File</a> object and storing it in an attirbute on the app.
The attribute can be named anything, perhaps even as simple as <code>files</code>, though for the <a href="https://github.com/jberger/Wishlist/blob/blog_post/installable/lib/Wishlist.pm#L10-L14">Wishlist app</a> I have used the name <code>dist_dir</c...

<p>Why <code>dist_dir</code>?

devdata/https_mojolicious.io_blog_2017_12_19_day-19-make-your-app-installable  view on Meta::CPAN

You&#39;ll see that it it really isn&#39;t much to do.</p>

<p>You also see that I only used as much of these instructions as I needed; you can do the same.
There is no magic in any of what you&#39;ve seen (other than perhaps File::Share).
If you don&#39;t need to think about theming or customizing the environment variable, then don&#39;t worry about it.
But if you find yourself in that situation, you&#39;ll know you can make such features available to your users.</p>

<p>And hey, if it is a useful application, consider uploading it to CPAN.
Though I warn you, once you start contributing to CPAN it can be addictive!</p>

              </section>
              <small><p><a href="https://en.wikipedia.org/w/index.php?curid=31630711">Image</a> by Gnovick - Own work, <a href="https://creativecommons.org/licenses/by/3.0/" title="Creative Commons Attribution 3.0">CC BY 3.0</a>.</p>
</small>

              <p class="tags">
                <span>Tagged in </span>:
                  <a href="/blog/tag/advent/">advent</a>,
                  <a href="/blog/tag/wishlist/">wishlist</a>
              </p>


                  <div class="bio cf">

                      <div class="gravatar">
                        <img alt="author image" src="https://secure.gravatar.com/avatar/cc767569f5863a7c261991ee5b23f147">
                      </div>
                      <div class="about">
                        <h5>Joel Berger</h5>
                        <p>Joel has Ph.D. in Physics from the University of Illinois at Chicago.
He an avid Perl user and <a href="https://metacpan.org/author/JBERGER">author</a> and is a member of the Mojolicious Core Team.</p>

                      </div>

                  </div>

devdata/https_mojolicious.io_blog_2017_12_19_day-19-make-your-app-installable  view on Meta::CPAN

                  <li class="next"><a href="/blog/2017/12/20/day-20-practical-testing/index.html" rel="next"><strong>Next Article</strong> Day 20: Practical Testing </a></li>
              </ul>

            </div>

        </article>


      </div>

      <div class="four columns end" id="secondary">
        <aside id="sidebar">
          







<div class="widget widget_tag_cloud">

devdata/https_mojolicious.io_blog_2017_12_20_day-20-practical-testing  view on Meta::CPAN


            </div>

              <div class="post-thumb">
                <!-- theme suggests 1300x500 -->
                <img alt="Taking a sample of lava at Kilauea" src="/blog/2017/12/20/day-20-practical-testing/lava.jpg">
              </div>

            <div class="post-content">

              <section id="section-1">
                  <p>Back on <a href="/blog/2017/12/09/day-9-the-best-way-to-test">Day 9</a> we discussed testing and especially <a href="http://mojolicious.org/perldoc/Test/Mojo">Test::Mojo</a>.
Today I want to just briefly talk about some practical things that can come up when testing real world applications.
Once again the discussion will be motivated by the <a href="https://github.com/jberger/Wishlist">Wishlist</a> application that we&#39;ve been developing these past few days.</p>

              </section>
              <section id="section-2">
                  <h2>Configuration Overrides</h2>

<p>In the Day 9 article I mentioned that the Test::Mojo <a href="http://mojolicious.org/perldoc/Test/Mojo#new">constructor</a> could be passed configuration overrides.
In this example we can see how that override lets us ensure that we are testing on a fresh and isolated database.</p>

<pre><code class="hljs"><span class="hljs-keyword">use</span> <span class="hljs-function">Mojo::Base</span> -strict;

<span class="hljs-keyword">use</span> <span class="hljs-function">Test::More</span>;
<span class="hljs-keyword">use</span> <span class="hljs-function">Test::Mojo</span>;

devdata/https_mojolicious.io_blog_2017_12_20_day-20-practical-testing  view on Meta::CPAN

</code></pre>

<p>You might have to be careful about when the migration happens too (ie disable <code>auto_migrate</code> and run it manually).
Also this will only isolate the tests per-name, here <code>test_one</code>.
Therefore I recommend you name the path for the name of the test file, this should be both descriptive and unique.
And you have to clean up after yourself otherwise the next time the test is run it will be affected by the remaining data.</p>

<h2>Mocking Helpers</h2>

<p>If you have done any testing you&#39;ve probably dealt with mocking, but if you haven&#39;t, mocking is the act of replacing functionality from essentially unrelated code with test-specific code.
Doing this lets you test one section of code (called a unit) in isolation from others.</p>

<p>Everyone has their favorite mock library.
There are so many tastes and styles that in the end Many people make their own, including <a href="https://metacpan.org/pod/Mock::MonkeyPatch">yours truly</a>.
Of course you can use those libraries in Mojolicious when appropriate.
As I mentioned before you can also mock out services by attaching tiny Mojolicious applications to a UserAgent&#39;s <a href="http://mojolicious.org/perldoc/Mojo/UserAgent#server"><code>server</code></a> attribute or making an entire external service...

<p>In some cases however, the natural place to mock is in the place of a helper.
When you think about it, this is actually rather obvious since helpers are often the glue used in Mojolicious applications to combine disparate code, like models or in this case the <a href="https://github.com/jberger/Wishlist/blob/blog_post/practica...

<p>To test this we could actually do any of the mentioned options from mocking <a href="https://metacpan.org/pod/LinkEmbedder#get">LinkEmbedder-&gt;get</a> to attaching a mock service.

devdata/https_mojolicious.io_blog_2017_12_20_day-20-practical-testing  view on Meta::CPAN

<p><small><a href="https://github.com/jberger/Wishlist/blob/blog_post/practical_testing/t/embed.t">t/embed.t</a></small></p>

<p>Because the template expects the result to be an object we have to build a tiny class to contain our mock results.
Also whenever you are mocking, it is important to check the input your mock received as well as the results that the calling code derives from your mock return value.</p>

<p>In the test you can also see some examples of how to use selectors to test for both text and attribute values.
The text test is especially important because it shows that the html value that I got back from the LinkEmbedder isn&#39;t being escaped by the template and will render as HTML to the client.</p>

<p>A few more tests and some documentation and our application will really be taking final shape!</p>

              </section>
              <small><p><a href="https://commons.wikimedia.org/w/index.php?curid=11337658">Image</a> by Hawaii Volcano Observatory, USGS - <a class="external text" href="http://hvo.wr.usgs.gov/kilauea/update/archive/2009/2009_Jun-Oct.html" rel="nofol...
</small>

              <p class="tags">
                <span>Tagged in </span>:
                  <a href="/blog/tag/advent/">advent</a>,
                  <a href="/blog/tag/mocking/">mocking</a>,
                  <a href="/blog/tag/testing/">testing</a>,
                  <a href="/blog/tag/wishlist/">wishlist</a>
              </p>


                  <div class="bio cf">

                      <div class="gravatar">
                        <img alt="author image" src="https://secure.gravatar.com/avatar/cc767569f5863a7c261991ee5b23f147">
                      </div>
                      <div class="about">
                        <h5>Joel Berger</h5>
                        <p>Joel has Ph.D. in Physics from the University of Illinois at Chicago.
He an avid Perl user and <a href="https://metacpan.org/author/JBERGER">author</a> and is a member of the Mojolicious Core Team.</p>

                      </div>

                  </div>

devdata/https_mojolicious.io_blog_2017_12_20_day-20-practical-testing  view on Meta::CPAN

                  <li class="next"><a href="/blog/2017/12/21/day-21-virtually-a-lumberjack/index.html" rel="next"><strong>Next Article</strong> Day 21: Virtual(ly a) Lumberjack </a></li>
              </ul>

            </div>

        </article>


      </div>

      <div class="four columns end" id="secondary">
        <aside id="sidebar">
          







<div class="widget widget_tag_cloud">

devdata/https_mojolicious.io_blog_2017_12_21_day-21-virtually-a-lumberjack  view on Meta::CPAN


            </div>

              <div class="post-thumb">
                <!-- theme suggests 1300x500 -->
                <img alt="Woman wearing VR goggles outside" src="/blog/2017/12/21/day-21-virtually-a-lumberjack/vr.jpg">
              </div>

            <div class="post-content">

              <section id="section-1">
                  <p>What do you do when you want to split up a stream of data in real-time while
giving the user instructions?</p>

<p>This is just what I wanted to do to aid in reverse-engineering the USB
protocol of Virtual Reality devices known as Head Mounted Displays (HMD), for
the <a href="http://www.openhmd.net/">OpenHMD</a> project.</p>

<p>HMDs are used to create virtual reality environments. When worn, two slightly
different images are drawn to each side of the screen, with each side visible
to only one eye. This imitates binocular vision and creates an image with a

devdata/https_mojolicious.io_blog_2017_12_21_day-21-virtually-a-lumberjack  view on Meta::CPAN

movements include roll (tilting head side-to-side), pitch (looking up and
down) and yaw (turning left/right). Though position isn&#39;t tracked, we also
look for sway (left-right translation), surge (back and forth) and heave (up
and down) information as this is used in combination with the other values for
accurate tracking of rotation.</p>

<p>Mojo is an amazing toolkit for web development, as shown in previous
calendar entries, but using components of it can also solve problems in other
non-web spaces like these. Why use Mojo for this? Because it makes it <em>easy</em>.</p>

              </section>
              <section id="section-2">
                  <h2>Down By The Riverside</h2>

<p>First of all, we need the stream of data.
Initially, I used <code>tshark</code> for this, though another member of the OpenHMD team
built another application, OpenHMD-Dumper, which has both a device selection
interface and opens the device to read the packets, which makes this much
easier.
Doing so allows us to ask others who have HMDs to send us these logs, so we
can add driver support for devices none of the team have access to!
Otherwise, we use something else to open the device and read data and <code>tshark</code>

devdata/https_mojolicious.io_blog_2017_12_21_day-21-virtually-a-lumberjack  view on Meta::CPAN

pretty much perfect for our use as we can see it both visually and easily
manipulate it with standard *nix tools like <em>cut</em>, <em>head</em> and <em>sed</em>.</p>

<pre><code>#!/usr/bin/env perl
use Mojo::Base &#39;-base&#39;;

use Mojo::Asset::File;
use Mojo::IOLoop;
use Mojo::IOLoop::Stream;

use Mojo::Loader &#39;data_section&#39;;

has file_count =&gt; 0;

has file  =&gt; sub { shift-&gt;file_start(&#39;0_START.pgm&#39;) };
has loop  =&gt; sub { Mojo::IOLoop-&gt;singleton };
has stdin =&gt; sub { Mojo::IOLoop::Stream-&gt;new(\*STDIN)-&gt;timeout(0) };

__PACKAGE__-&gt;new-&gt;main;

sub main {
  my $self = shift;
  $self-&gt;stdin-&gt;on(read =&gt; sub { $self-&gt;stdin_read(@_) });
  $self-&gt;stdin-&gt;start;
  $self-&gt;loop-&gt;start unless $self-&gt;loop-&gt;is_running;
}

sub file_start {
  my ($self, $path) = @_;
  $self-&gt;file_count($self-&gt;file_count + 1);
  return Mojo::Asset::File-&gt;new(path =&gt; $path)-&gt;cleanup(0)-&gt;add_chunk(
    data_section(__PACKAGE__, &#39;pgm_header&#39;),
  );
};

sub stdin_read {
  my ($self, $stream, $bytes) = @_;

  foreach my $packet (split /\n/, $bytes) {
    my $chunk = join &#39; &#39;, (
      map { sprintf &#39;%03i&#39;, hex($_) } split /:/, $packet
    );

devdata/https_mojolicious.io_blog_2017_12_21_day-21-virtually-a-lumberjack  view on Meta::CPAN

<p><a href="http://mojolicious.org/perldoc/Mojo/IOLoop">Mojo::IOLoop</a> and
<a href="http://mojolicious.org/perldoc/Mojo/IOLoop/Stream">Mojo::IOLoop::Stream</a> give
us a nice callback interface for reading STDIN.
This doesn&#39;t seem too important right now, but the next stage will show why.
It allows us to direct the information coming in from STDIN while we instruct
the user which motion we want them to make with the HMD.</p>

<h2>I bid you.. move!</h2>

<p>Let&#39;s add some instructions to be shown to the user.
To do this, we can just add in another section like <em>pgm_header</em>:</p>

<pre><code>@@ instructions
1 Prepare for instructions, cherished aide!
3 Steady

2 Prep Yaw
5 Start Yaw
1 Stop Yaw
3 Steady

devdata/https_mojolicious.io_blog_2017_12_21_day-21-virtually-a-lumberjack  view on Meta::CPAN


2 Prep Heave
5 Start Heave
1 Stop Heave
3 Steady

0 The End Of Instructions. Thank you, generous one!
</code></pre>

<p>This format is very simple.
Leading number is how many seconds to wait on this instruction before moving
to the next one.
The text is what is output to the user.
We also use it to get the name of the file to create.</p>

<p>This could be formatted in a lot more of a structured way (e.g. YAML), but
this works fine for our purpose!</p>

<p>Let&#39;s make the instructions get loaded in, skipping any empty lines:</p>

<pre><code>has instructions =&gt; sub {[
  map {[split / /, $_, 2]}
  grep { length $_ }
  split /\n/, data_section(__PACKAGE__, &#39;instructions&#39;)
]};
</code></pre>

<p>And add a method which progresses us through the script:</p>

<pre><code>sub instruction_show {
  my $self = shift;

  my $instruction = shift @{$self-&gt;instructions};
  return $self-&gt;loop-&gt;stop_gracefully unless defined $instruction;

devdata/https_mojolicious.io_blog_2017_12_21_day-21-virtually-a-lumberjack  view on Meta::CPAN

    my $file_count = $self-&gt;file_count;
    my $path = sprintf &#39;%i_%s.pgm&#39;, $file_count, uc $type;
    $self-&gt;file( $self-&gt;file_start($path) );
  }) if $instruction-&gt;[1] eq &#39;Steady&#39;;
}
</code></pre>

<p>As you can see, we ask the loop to stop gracefully when there are no more
instructions.
Otherwise, we output the instruction and then schedule the next instruction
to be done in the amount of seconds we specified in the script.</p>

<p>If the action is to steady the HMD, we know we are going to start another
action shortly so, in half of the wait time, we start a new file.
This should mean that the end and start of each file, the HMD is not moving
(much).</p>

<p>Then we need to start walking through this script by adding this before
starting the event loop in <em>main</em>:</p>

<pre><code>$self-&gt;loop-&gt;timer(0 =&gt; sub { $self-&gt;instruction_show });

devdata/https_mojolicious.io_blog_2017_12_21_day-21-virtually-a-lumberjack  view on Meta::CPAN

(not everyone is familiar with nautical terms after all!).
Perhaps even with a device select?
A UI that allows the user to select the offset, size and unpack method and
render the graphs as appropriate could cut down the time to analyse.
Better yet, if it could detect which combinations result in a rough sine wave,
it could narrow down and present the user with likely candidates for each
movement..</p>

<p>.. but those are improvements for another day!</p>

              </section>
              <small><p><a href="https://www.pexels.com/photo/sky-woman-clouds-girl-123335/">Image</a> by Bradley Hook, in the Public Domain.</p>
</small>

              <p class="tags">
                <span>Tagged in </span>:
                  <a href="/blog/tag/advent/">advent</a>,
                  <a href="/blog/tag/non-web/">non-web</a>
              </p>


devdata/https_mojolicious.io_blog_2017_12_21_day-21-virtually-a-lumberjack  view on Meta::CPAN

                  <li class="next"><a href="/blog/2017/12/22/day-22-how-to-build-a-public-rest-api/index.html" rel="next"><strong>Next Article</strong> Day 22: A RESTful API with OpenAPI </a></li>
              </ul>

            </div>

        </article>


      </div>

      <div class="four columns end" id="secondary">
        <aside id="sidebar">
          







<div class="widget widget_tag_cloud">

devdata/https_mojolicious.io_blog_2017_12_22_day-22-how-to-build-a-public-rest-api  view on Meta::CPAN


            </div>

              <div class="post-thumb">
                <!-- theme suggests 1300x500 -->
                <img alt="A hammock on a beach" src="/blog/2017/12/22/day-22-how-to-build-a-public-rest-api/hammock_beach.jpg">
              </div>

            <div class="post-content">

              <section id="section-1">
                  <p>The <a href="https://www.openapis.org/">OpenAPI</a> Specification (formerly named
Swagger) is an API description format for REST APIs. An API specification
written using the the rules set by the Open API Initiative can be used to
describe:</p>

<ul>
<li>All the available endpoints. An endpoint is a unique resource that can
access or modify a given object.</li>
<li>Input parameters, such as headers, query parameters and/or body parameters.</li>
<li>The structure of the response, including headers status codes and the body -
if any.</li>
<li>Authentication methods</li>
<li>Contact information, license, terms of use and other information</li>
</ul>

<p>This post look into how to write an API specification and how to use it
together with
<a href="https://metacpan.org/pod/Mojolicious::Plugin::OpenAPI">Mojolicious::Plugin::OpenAPI</a>
and <a href="https://metacpan.org/pod/OpenAPI::Client">OpenAPI::Client</a>.</p>

              </section>
              <section id="section-2">
                  <h2>Why would you use OpenAPI</h2>

<p>This question comes up quite often after telling people about OpenAPI:
&quot;but...why?&quot; The people asking this often come from the same background as
myself, where you both write the producer (backend web server) and consumer
(JavaScript, ...) of the data. When you&#39;re in complete control of both sides
you don&#39;t really need to write any formal specification or document your API,
since you already <em>know</em> how it works. This can be very true - at least if you
make sure you have tests of all your endpoints.</p>

devdata/https_mojolicious.io_blog_2017_12_22_day-22-how-to-build-a-public-rest-api  view on Meta::CPAN

<li><a href="https://metacpan.org/pod/OpenAPI::Client">OpenAPI::Client</a>&#39;s manual
contains more information about how the client side works.</li>
<li><a href="https://swagger.io/docs/specification/about/">Swagger&#39;s about page</a> has
information about the specification and OpenAPI.</li>
<li><a href="https://www.openapis.org/">OAI</a> is the official OpenAPI resource page.</li>
<li><a href="https://metacpan.org/pod/JSON::Validator">JSON::Validator</a> is the &quot;brain&quot;
behind both the plugin and client side in Perl. Check it out, if you&#39;re
interested in JSON-Schema.</li>
</ul>

              </section>
              <small><p><a href="https://www.pexels.com/photo/hammock-palm-trees-bungalows-bora-bora-104750">Image</a> by Chris McClave, in the Public Domain.</p>
</small>

              <p class="tags">
                <span>Tagged in </span>:
                  <a href="/blog/tag/advent/">advent</a>,
                  <a href="/blog/tag/api/">api</a>,
                  <a href="/blog/tag/openapi/">openapi</a>,
                  <a href="/blog/tag/rest/">rest</a>,
                  <a href="/blog/tag/swagger/">swagger</a>
              </p>


                  <div class="bio cf">

                      <div class="gravatar">
                        <img alt="author image" src="https://secure.gravatar.com/avatar/806800a3aeddbad6af673dade958933b">
                      </div>
                      <div class="about">
                        <h5>Jan Henning Thorsen</h5>
                        <p>Jan (aka batman) is a self taught Perl hacker and a member of the Mojolicious Core Team. He likes to work with anything that has to do with web - both frontend and backend. Got more questions? Send him an <a href="mailto:jh...

                      </div>

                  </div>

              <ul class="post-nav cf">

devdata/https_mojolicious.io_blog_2017_12_22_day-22-how-to-build-a-public-rest-api  view on Meta::CPAN

                  <li class="next"><a href="/blog/2017/12/23/day-23-one-liners-for-fun-and-profit/index.html" rel="next"><strong>Next Article</strong> Day 23: One-Liners for Fun and Profit </a></li>
              </ul>

            </div>

        </article>


      </div>

      <div class="four columns end" id="secondary">
        <aside id="sidebar">
          







<div class="widget widget_tag_cloud">

devdata/https_mojolicious.io_blog_2017_12_23_day-23-one-liners-for-fun-and-profit  view on Meta::CPAN


            </div>

              <div class="post-thumb">
                <!-- theme suggests 1300x500 -->
                <img alt="Old man playing timed chess" src="/blog/2017/12/23/day-23-one-liners-for-fun-and-profit/chess.jpg">
              </div>

            <div class="post-content">

              <section id="section-1">
                  <p>Perl is well-known for its <a href="http://www.catonmat.net/download/perl1line.txt">one-liners</a>: short programs written as part of the <a href="http://perldoc.perl.org/perlrun.html">command line invocation of the interpreter</...
Certainly every programmer or sysadmin has the need, from time to time, to do a quick one-off task programmatically.
Such tasks can be done with a full script, to be sure, but once you get the hang of writing them, one-liners can save the time and hassle of actually doing so.</p>

<p>These tasks may include removing unwanted lines from files, collecting data from logs, or even a quick proof-of-concept of something that would become a script later.
They can read lines in files, even multiple files, can operate on files in-place, can read from STDIN as a pipe.
But while one-liners have been tools of the trade for these activities, certainly no such thing would be practical for web tasks, right?</p>

<p>But of course, on <a href="https://mojolicious.io/blog/2017/12/05/day-5-your-apps-built-in-commands/">day 5</a> and <a href="https://mojolicious.io/blog/2017/12/06/day-6-adding-your-own-commands/">day 6</a> of this series that we saw that we can b...
We have even seen how to use the <a href="http://mojolicious.org/perldoc/Mojolicious/Command/eval">eval</a> command to run a one-liner against your app.
So could we take this further?</p>

<p>Could we do remote data fetching and manipulation as a one-liner?
Could we build an entire web application as a one-liner?
Would I be asking if the answer was no?</p>

              </section>
              <section id="section-2">
                  <h2>A Note on Readability</h2>

<p>Almost always when I post articles on Mojolicious, I&#39;m keenly aware of Perl&#39;s reputation for readability.
I firmly believe that Perl can be written to be easily read, it just takes awareness from the author.
But every now and again you need to have a little fun!</p>

<p>One-liners are not meant for too much reuse.
Their value is the extreme rapidity of their creation and as such they are terse.
If they were well-formed scripts, well, you&#39;d put them in a file.</p>

devdata/https_mojolicious.io_blog_2017_12_23_day-23-one-liners-for-fun-and-profit  view on Meta::CPAN

We can take a baseline and then make our changes and each time run something like</p>

<pre><code>perl -Ilib -Mojo -E &#39;my $body = g(&quot;html.spec.whatwg.org&quot;)-&gt;body; n { x $body } 10&#39;
</code></pre>

<p>This fetches the rather large HTML document that defines HTML itself and then parses it 10 times.
The more runs, the more consistent your data should be since variations are averaged out.
Note especially how easily the fetching is excluded while what we care about is included.
On my laptop this gives the output.</p>

<pre><code>29.3775 wallclock secs (29.11 usr +  0.26 sys = 29.37 CPU) @  0.34/s (n=10)
</code></pre>

<p>Knowing that data taken with and without proposed changes we can have a better idea of the performance gains or impacts from that change.
While there is no magic in this function, the ease-of-use of the benchmarker means we are actually likely to use it, even for what may seem like small and insignificant changes.
This is a major reason for Mojolicious&#39; consistently blazing speeds.</p>

<h2>Conclusion</h2>

<p>Making <code>ojo</code> one-liners can be great to experiment with new concepts, demonstrate problems, fetch and work with data, and many other tasks.
You might use them in non-web one-liners that need JSON or Data::Dumper or perhaps MMojo::Collection for chaining.
(Speaking of chaining, for bonus points, check out <a href="https://metacpan.org/pod/ojoBox">ojoBox</a> for <a href="https://metacpan.org/pod/Mojo::Autobox">autoboxing Perl types</a>, making even cooler chains!)</p>

<p>These one-liners are not going to be everyone&#39;s cup of tea.
If these don&#39;t seem like your&#39;s you can completely ignore them.</p>

<p>However, once you start using them, I think you&#39;ll find yourself using them often.</p>

              </section>
              <small><p><a href="https://commons.wikimedia.org/w/index.php?curid=21375125">Image</a> by © <a href="http://www.royan.com.ar" rel="nofollow">Jorge Royan</a>, <a href="https://creativecommons.org/licenses/by-sa/3.0" title="Creative Co...
</small>

              <p class="tags">
                <span>Tagged in </span>:
                  <a href="/blog/tag/advent/">advent</a>,
                  <a href="/blog/tag/command/">command</a>,
                  <a href="/blog/tag/debugging/">debugging</a>,
                  <a href="/blog/tag/lite/">lite</a>
              </p>


                  <div class="bio cf">

                      <div class="gravatar">
                        <img alt="author image" src="https://secure.gravatar.com/avatar/cc767569f5863a7c261991ee5b23f147">
                      </div>
                      <div class="about">
                        <h5>Joel Berger</h5>
                        <p>Joel has Ph.D. in Physics from the University of Illinois at Chicago.
He an avid Perl user and <a href="https://metacpan.org/author/JBERGER">author</a> and is a member of the Mojolicious Core Team.</p>

                      </div>

                  </div>

devdata/https_mojolicious.io_blog_2017_12_23_day-23-one-liners-for-fun-and-profit  view on Meta::CPAN

                  <li class="next"><a href="/blog/2017/12/24/day-24-release-and-wrap-up/index.html" rel="next"><strong>Next Article</strong> Day 24: Release and Wrap-Up </a></li>
              </ul>

            </div>

        </article>


      </div>

      <div class="four columns end" id="secondary">
        <aside id="sidebar">
          







<div class="widget widget_tag_cloud">

devdata/https_mojolicious.io_blog_2017_12_24_day-24-release-and-wrap-up  view on Meta::CPAN


            </div>

              <div class="post-thumb">
                <!-- theme suggests 1300x500 -->
                <img alt="Out of focus image of lit Christmas tree" src="/blog/2017/12/24/day-24-release-and-wrap-up/tree_unfocused.jpg">
              </div>

            <div class="post-content">

              <section id="section-1">
                  <p>Over the course of this advent calendar, we have discussed the <a href="https://mojolicious.io/blog/tag/wishlist/">Wishlist example application</a> several times.
We used it to motivate discussions about <a href="/blog/2017/12/17/day-17-the-wishlist-app/">templates</a>, <a href="/blog/2017/12/18/day-18-the-wishlist-model/">models</a>, <a href="/blog/2017/12/19/day-19-make-your-app-installable/">installable app...
In this post I want to use it somewhat differently.
I would like to motivate you, the reader, into action in a few different ways.</p>

              </section>
              <section id="section-2">
                  <h3>The Double-Edged Sword</h3>

<p>The internet has made so many amazing things possible.
Old friendships are kept alive.
Personal photographs can be stored forever and shared with friends.
Rare items can be discussed, found, and purchased.
News can spread as fast as fingers can type them.</p>

<p>But for all this ease and convenience there is a price.
Personal data is being taken, mined, and sold.

devdata/https_mojolicious.io_blog_2017_12_24_day-24-release-and-wrap-up  view on Meta::CPAN

I wrote an application called <a href="https://github.com/jberger/CarPark">CarPark</a> to control my garage door via a RaspberryPi and even spoke about it at <a href="https://www.youtube.com/watch?v=aJc5yYONBBc">The Perl Conference</a>; it isn&#39;t ...

<p>And that brings us to the <a href="https://github.com/jberger/Wishlist">Wishlist</a> application.
Several sites, some large and some small, offer similar services: tracking your wishlists and aiding gift buying, all for free.
However, this too must also come at a cost.</p>

<p>In this article I&#39;m announcing that after adding a few tweaks around user registration, I have now released the Wishlist application to <a href="https://metacpan.org/pod/Wishlist">CPAN</a>.
I hope you can use it to keep a slightly tighter grasp on your digital footprint without sacrificing utility.</p>

<p>You can deploy it on a VPS, like <a href="https://www.linode.com/">Linode</a> or <a href="https://www.scaleway.com/">Scaleway</a>.
You could even use it on that old desktop computer in your home office as long as you are careful about network security.
Speaking of which, <a href="https://letsencrypt.org/">Let&#39;s Encrypt</a> finally makes SSL practical for personal users, try <a href="https://certbot.eff.org">certbot</a> or my <a href="https://metacpan.org/pod/Mojolicious::Plugin::ACME">plugin</a...
Once you have one service running, it will become progressively easier to host more and more of your own personal cloud applications.</p>

<p>I&#39;d love to see if Wishlist and CarPark and other such applications could put you back in the driver&#39;s seat for your digital lives.</p>

<h3>A Call to Action</h3>

<p>That said they aren&#39;t nearly good enough.
They need more tests, more documentation, more functionality.
It would be great if they could support plugins and theming.

devdata/https_mojolicious.io_blog_2017_12_24_day-24-release-and-wrap-up  view on Meta::CPAN


<h2>Getting Help</h2>

<p>As always I want to be sure to remind people where to get help.
I&#39;m on IRC almost all the time, you can find us in #mojo on <a href="http://irc.perl.org">irc.perl.org</a>, you can even join by <a href="https://chat.mibbit.com/?channel=%23mojo&amp;server=irc.perl.org">clicking here</a>.
We have a mailing list at <a href="https://groups.google.com/forum/#!forum/mojolicious">https://groups.google.com/forum/#!forum/mojolicious</a>.
All of the documentation is online at <a href="http://mojolicious.org/perldoc">http://mojolicious.org/perldoc</a>.</p>

<h2>Happy holidays from the Mojolicious community!</h2>

              </section>
              <small><p><a href="https://www.pexels.com/photo/art-blurred-blurry-bokeh-383646/">Image</a> by Tim Mossholder, in the Public Domain</p>
</small>

              <p class="tags">
                <span>Tagged in </span>:
                  <a href="/blog/tag/advent/">advent</a>,
                  <a href="/blog/tag/wishlist/">wishlist</a>
              </p>


                  <div class="bio cf">

                      <div class="gravatar">
                        <img alt="author image" src="https://secure.gravatar.com/avatar/cc767569f5863a7c261991ee5b23f147">
                      </div>
                      <div class="about">
                        <h5>Joel Berger</h5>
                        <p>Joel has Ph.D. in Physics from the University of Illinois at Chicago.
He an avid Perl user and <a href="https://metacpan.org/author/JBERGER">author</a> and is a member of the Mojolicious Core Team.</p>

                      </div>

                  </div>

devdata/https_mojolicious.io_blog_2017_12_24_day-24-release-and-wrap-up  view on Meta::CPAN

                  <li class="next"><a href="/blog/2018/03/18/graphql-openapi/index.html" rel="next"><strong>Next Article</strong> Mojolicious, OpenAPI - and GraphQL </a></li>
              </ul>

            </div>

        </article>


      </div>

      <div class="four columns end" id="secondary">
        <aside id="sidebar">
          







<div class="widget widget_tag_cloud">

devscripts/update  view on Meta::CPAN

    "06" => "https://mojolicious.io/blog/2017/12/06/day-6-adding-your-own-commands",
    "07" => "https://mojolicious.io/blog/2017/12/07/day-7-using-template-variants-for-a-beta-landing-page",
    "08" => "https://mojolicious.io/blog/2017/12/08/day-8-mocking-a-rest-api",
    "09" => "https://mojolicious.io/blog/2017/12/09/day-9-the-best-way-to-test",
    "10" => "https://mojolicious.io/blog/2017/12/10/day-10-give-the-customer-what-they-want",
    "11" => "https://mojolicious.io/blog/2017/12/11/day-11-useragent-content-generators",
    "12" => "https://mojolicious.io/blog/2017/12/12/day-12-more-than-a-base-class",
    "13" => "https://mojolicious.io/blog/2017/12/13/day-13-more-about-roles",
    "14" => "https://mojolicious.io/blog/2017/12/14/day-14-you-promised-to-call",
    "15" => "https://mojolicious.io/blog/2017/12/15/day-15-start-a-new-yancy-app",
    "16" => "https://mojolicious.io/blog/2017/12/16/day-16-the-secret-life-of-sessions",
    "17" => "https://mojolicious.io/blog/2017/12/17/day-17-the-wishlist-app",
    "18" => "https://mojolicious.io/blog/2017/12/18/day-18-the-wishlist-model",
    "19" => "https://mojolicious.io/blog/2017/12/19/day-19-make-your-app-installable",
    "20" => "https://mojolicious.io/blog/2017/12/20/day-20-practical-testing",
    "21" => "https://mojolicious.io/blog/2017/12/21/day-21-virtually-a-lumberjack",
    "22" => "https://mojolicious.io/blog/2017/12/22/day-22-how-to-build-a-public-rest-api",
    "23" => "https://mojolicious.io/blog/2017/12/23/day-23-one-liners-for-fun-and-profit",
    "24" => "https://mojolicious.io/blog/2017/12/24/day-24-release-and-wrap-up",
);

lib/Acme/CPANModules/Import/MojoliciousAdvent/2017_12_16.pm  view on Meta::CPAN

package Acme::CPANModules::Import::MojoliciousAdvent::2017_12_16;

our $DATE = '2018-12-30'; # DATE
our $VERSION = '0.001'; # VERSION

our $LIST = {description=>"This list is generated by extracting module names mentioned in [https://mojolicious.io/blog/2017/12/16/day-16-the-secret-life-of-sessions] (retrieved on 2018-12-30). Visit the URL for the full contents.",entries=>[{module=>...

1;
# ABSTRACT: Modules mentioned in Mojolicious Advent Calendar 2017 (day 16)

__END__

=pod

=encoding UTF-8

=head1 NAME

Acme::CPANModules::Import::MojoliciousAdvent::2017_12_16 - Modules mentioned in Mojolicious Advent Calendar 2017 (day 16)

=head1 VERSION

This document describes version 0.001 of Acme::CPANModules::Import::MojoliciousAdvent::2017_12_16 (from Perl distribution Acme-CPANModulesBundle-Import-MojoliciousAdvent-2017), released on 2018-12-30.

=head1 DESCRIPTION

This module is generated by extracting module names mentioned in L<https://mojolicious.io/blog/2017/12/16/day-16-the-secret-life-of-sessions> (retrieved on 2018-12-30). Visit the URL for the full contents.

Modules mentioned in Mojolicious Advent Calendar 2017 (day 16).

This list is generated by extracting module names mentioned in [https://mojolicious.io/blog/2017/12/16/day-16-the-secret-life-of-sessions] (retrieved on 2018-12-30). Visit the URL for the full contents.

=head1 INCLUDED MODULES

=over

=item * L<Mojolicious>

=item * L<Mojolicious::Controller>

=item * L<Mojolicious::Sessions>



( run in 1.998 second using v1.01-cache-2.11-cpan-39bf76dae61 )