view release on metacpan or search on metacpan
devdata/https_mojolicious.io_blog_2018_12_01_welcome-mojoconf-recap_ view on Meta::CPAN
</div>
<div class="post-thumb">
<!-- theme suggests 1300x500 -->
<img alt="View from fjord" src="/blog/2018/12/01/welcome-mojoconf-recap/banner.jpg">
</div>
<div class="post-content">
<section id="section-1">
<p>Welcome to another year of the Mojolicious Advent Calendar!
2018 has been very good to Mojolicious and I could think of no better way to kick off this calendar than with a recap of the 2018 Nordic Perl Workshop and MojoConf held in Oslo, Norway.</p>
</section>
<section id="section-2">
<h2>Sidetrip to Western Norway</h2>
<p>On a personal note, I especially enjoyed this trip because I was able to take a few extra days to visit the West of Norway, home to the iconic fjords.
I visited Bergen and several of its Perlers before taking a fjord tour by boat and train.
It would have been the perfect trip if my bag hadn't decided that it wanted to stay an extra few days in Iceland where I'd had a delayed stop-over.</p>
<p>Still I had an amazing times and saw once in a lifetime sights!
Thanks to Christopher and Jonis and all the people whoe were my companions for the trip!</p>
<h2>Nordic Perl Workshop and MojoConf</h2>
devdata/https_mojolicious.io_blog_2018_12_01_welcome-mojoconf-recap_ view on Meta::CPAN
If you're in the mood and have 5 minutes, what my rant about SAML.</p>
<p><iframe allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen frameborder="0" height="480" src="https://www.youtube.com/embed/xno08-KGJyY" width="854"></iframe></p>
<h3>Finally</h3>
<p>Have some fun, watch the talks from the conference, and if you enjoy what you see, consider coming to the next MojoConf!
I want to thank all of the organizers, the venue <a href="http://www.teknologihuset.no/">Teknologihuset</a> and the conference partner/sponsor <a href="https://www.ksat.no/">KSAT</a>.
I had a great time and I can't wait for the next one!</p>
</section>
<small><p>Original image by Joel Berger.</p>
</small>
<p class="tags">
<span>Tagged in </span>:
<a href="/blog/tag/advent/">advent</a>,
<a href="/blog/tag/mojoconf/">mojoconf</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_2018_12_01_welcome-mojoconf-recap_ view on Meta::CPAN
<li class="next"><a href="/blog/2018/12/02/automatic-reload-for-rapid-development/index.html" rel="next"><strong>Next Article</strong> Day 2: Automatic Reload for Rapid Development </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_2018_12_02_automatic-reload-for-rapid-development_ view on Meta::CPAN
</div>
<div class="post-thumb">
<!-- theme suggests 1300x500 -->
<img alt="Mojolicious art and reload icon, original artwork by Doug Bell" src="/blog/2018/12/02/automatic-reload-for-rapid-development/banner.jpg">
</div>
<div class="post-content">
<section id="section-1">
<p>Developing webapps with <a href="http://mojolicious.org">Mojolicious</a> is a lot of fun!
Using <a href="https://mojolicious.org/perldoc/morbo">the <code>morbo</code> server</a> for
development, every change to my webapp causes a restart to load my changes.
This way the next request I make has all my new code!</p>
<p>So, I change my code, the webapp restarts, and I go back to my browser window.
Wait... Where's my new code? Why isn't the bug fixed? Did... Did I forget to
reload my browser window again? Ugh! Of course!</p>
<p>Does this happen to you? Probably not. But, it's still annoying to reload the
browser window after every backend code change. It'd be nice if my browser
window automatically reloaded every time the web server restarted!</p>
</section>
<section id="section-2">
<h1>AutoReload Plugin</h1>
<p>Like every problem in Perl, there's a CPAN module for this:
<a href="http://metacpan.org/pod/Mojolicious::Plugin::AutoReload">Mojolicious::Plugin::AutoReload</a>.
Adding this plugin to our application will automatically reload any browser
windows connected to our app, making it even easier to develop Mojolicious
applications!</p>
<p>To use the plugin, we add it to our application using the <code>plugin</code> method.
Then, we add the <code>auto_reload</code> helper to our <a href="https://metacpan.org/pod/distribution/Mojolicious/lib/Mojolicious/Guides/Tutorial.pod#Layouts">layout
devdata/https_mojolicious.io_blog_2018_12_02_automatic-reload-for-rapid-development_ view on Meta::CPAN
<p><a href="myapp.pl">Download the code here</a>. Now while we have our application open in
our browser, if the server is restarted, our browser will reload the page to
see the new app!</p>
<h2>How It Works</h2>
<p>This plugin is sheer elegance in its simplicity: When the browser loads the
page, it connects to a WebSocket located at <code>/auto_reload</code>. When the server
restarts, the WebSocket connection is broken. The client sees the broken
connection, waits a second for the server to start listening for connections
again, and then reloads the page.</p>
<h2>Disable In Production</h2>
<p>Once we switch from <code>morbo</code> to <code>hypnotoad</code>, we don't want the automatic reload
anymore. So, the plugin doesn't send the browser the JavaScript to build the
websocket. This is controlled with <a href="https://mojolicious.org/perldoc/Mojolicious/Guides/Tutorial#Mode">the <code>mode</code>
attribute</a>.
When the <code>mode</code> is <code>development</code> (the default for <code>morbo</code>), the browser is told
to make the WebSocket. When the <code>mode</code> is anything else, no WebSocket is made.</p>
<p>Part of what makes Mojolicious so much fun is how easy it is. <a href="https://github.com/preaction/Mojolicious-Plugin-AutoReload/blob/v0.003/lib/Mojolicious/Plugin/AutoReload.pm#L56-L92">The entire
plugin is only 40 lines of
code</a>.</p>
<p>And now, with Mojolicious::Plugin::AutoReload, developing in Mojolicious is
just a little easier, and a little more fun!</p>
</section>
<small><p>Original artwork by Doug Bell, released under CC-BY-SA 4.0. It includes
a screenshot of the Mojolicious.org website (fair use), the Mojolicious
logo (CC-BY-SA 4.0), and a
<a href="https://commons.wikimedia.org/wiki/File:Refresh_icon.svg">"reload"</a>
icon from Wikimedia Commons (CC0: Public domain)</p>
</small>
<p class="tags">
<span>Tagged in </span>:
<a href="/blog/tag/advent/">advent</a>,
<a href="/blog/tag/development/">development</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_2018_12_02_automatic-reload-for-rapid-development_ view on Meta::CPAN
<li class="next"><a href="/blog/2018/12/03/higher-order-promises/index.html" rel="next"><strong>Next Article</strong> Day 3: Higher Order Promises </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_2018_12_03_higher-order-promises_ view on Meta::CPAN
</div>
<div class="post-thumb">
<!-- theme suggests 1300x500 -->
<img alt="fractal cauliflower" src="/blog/2018/12/03/higher-order-promises/banner.jpg">
</div>
<div class="post-content">
<section id="section-1">
<h2>Create new, complex Promises by composing Promises</h2>
<p>Mojolicious 7.49 added an its own implementation of the <a href="https://promisesaplus.com">Promises/A+ specification</a>. mohawk wrote about these in <a href="https://mojolicious.io/blog/2017/12/14/day-14-you-promised-to-call/">Day 14: You Promis...
</section>
<section id="section-2">
<p>A Promise is a structure designed to eliminate nested callbacks (also known as <a href="http://callbackhell.com">"callback hell"</a>). A properly written chain of Promises has a flat structure that easy to follow linear...
<p>A higher-order Promise is one that comprises other Promises and bases its status on them. The <a href="https://metacpan.org/pod/Mojo::Promise::Role::HigherOrder">Mojo::Promise::Role::HigherOrder</a> distribution provides three roles that you can m...
<h3>All</h3>
<p>An <code>all</code> promise resolves only when all of its Promises also resolve. If one of them is rejected, the <code>all</code> Promise is rejected. This means that the overall Promise knows what to do if one is rejected and it doesn't need ...
<pre><code>use Mojo::Promise;
use Mojo::UserAgent;
devdata/https_mojolicious.io_blog_2018_12_03_higher-order-promises_ view on Meta::CPAN
sub { say "At least one was 404: @_!" },
);
$all_promise->wait;
</code></pre>
<h2>Conclusion</h2>
<p>It's easy to make new Promises out of smaller ones to represent complex situations. You can combine the Promises that Mojolicious creates for you with your own handmade Promises to do almost anything you like.</p>
</section>
<small><p><a class="external text" href="https://www.flickr.com/photos/joeshlabotnik/3059554662/" rel="nofollow">Image</a> by <a href="https://www.flickr.com/photos/joeshlabotnik/">Joe Shlabotnik</a> <a href="https://creativecommons.org...
</small>
<p class="tags">
<span>Tagged in </span>:
<a href="/blog/tag/promises/">promises</a>,
<a href="/blog/tag/advent/">advent</a>
</p>
<div class="bio cf">
<div class="gravatar">
<img alt="author image" src="https://secure.gravatar.com/avatar/168427dea0a034607ee7850f3de98ea2.jpg">
</div>
<div class="about">
<h5>brian d foy</h5>
<p><a href="http://www252.pair.com/~comdog/">brian d foy</a> is the author of <a href="https://www.masteringperl.org/">Mastering Perl</a> and <a href="https://www.learningperl6.com/">Learning Perl 6</a>, and the co-author of <...
</div>
</div>
<ul class="post-nav cf">
devdata/https_mojolicious.io_blog_2018_12_03_higher-order-promises_ view on Meta::CPAN
<li class="next"><a href="/blog/2018/12/04/testing-hooks-and-helpers/index.html" rel="next"><strong>Next Article</strong> Day 4: Testing Hooks and Helpers </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_2018_12_04_testing-hooks-and-helpers_ view on Meta::CPAN
</div>
<div class="post-thumb">
<!-- theme suggests 1300x500 -->
<img alt="Scientific calculator on a mathematics textbook" src="/blog/2018/12/04/testing-hooks-and-helpers/banner.jpg">
</div>
<div class="post-content">
<section id="section-1">
<p><a href="https://mojolicious.org/perldoc/Test/Mojo">Test::Mojo</a>, the
<a href="http://mojolicious.org">Mojolicious</a> testing tool, has a lot of ways to
<a href="https://mojolicious.org/perldoc/Mojolicious/Guides/Testing">test routes in web
applications</a>
(even for <a href="https://metacpan.org/pod/Test::Mojo::Role::PSGI">testing in other web
frameworks</a>).</p>
<p>But what if what I need to test isn't a route? What if it's
a <a href="https://mojolicious.org/perldoc/Mojolicious#HOOKS">hook</a>,
a <a href="https://mojolicious.org/perldoc/Mojolicious/Guides/Cookbook#Adding-a-plugin-to-your-application">plugin</a>,
or
a <a href="https://mojolicious.org/perldoc/Mojolicious/Guides/Rendering#Helpers">helper</a>?
We can test all those things, too!</p>
</section>
<section id="section-2">
<h1>Hooks</h1>
<p>To thoroughly test hooks, I need to find ways to configure my test
cases. I could count on my application to do it, and find the right
routes to test the right behavior. But, that creates larger tests that
integrate different parts and makes test failures harder to debug. What
I want is to isolate the thing I'm testing. The best way to do that is
to create routes that test only what I want to test.</p>
<p>What if I have a hook to log exceptions to a special log file, like so:</p>
devdata/https_mojolicious.io_blog_2018_12_04_testing-hooks-and-helpers_ view on Meta::CPAN
<p>Of course, we'll still need to test whether the routes we want to
protect with tokens are protected, but this shows that our
authentication helper works so if there are problems with our routes,
it's probably not here.</p>
<p>So, it's not only the web requests in our app I can test. When I need to
test hooks, I can make my own routes for testing. When I need to test
helpers, I can do so by directly calling them. The narrower the scope of
the test, the easier debugging of test failures!</p>
</section>
<small><p>Photo from pexels.com, licensed CC0.</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/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_2018_12_04_testing-hooks-and-helpers_ view on Meta::CPAN
<li class="next"><a href="/blog/2018/12/05/compound-selectors/index.html" rel="next"><strong>Next Article</strong> Day 5: Compound Selectors are Easier than Regexes </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_2018_12_05_compound-selectors_ view on Meta::CPAN
</div>
<div class="post-thumb">
<!-- theme suggests 1300x500 -->
<img alt="Sled dogs waiting to run" src="/blog/2018/12/05/compound-selectors/banner.jpg">
</div>
<div class="post-content">
<section id="section-1">
<p>When people tell me that I can't (they mean shouldn't) parse HTML with a regex, I say "hold my beer". It isn't a matter of skill or attitude so much as convenience. Doing it the right way was not always so e...
</section>
<section id="section-2">
<p>The trick was always to isolate the interesting HTML. I could do that excising all of the data around the interesting parts:</p>
<pre><code>my $html = ...;
$html =~ s/.*?<table class="foo".*?>//;
$html =~ s/<\/table>.*//;
</code></pre>
<p>Now I don't have to parse all of HTML; I can think about the table. Even though that's expedient it's not so nice. Before I replace that with something nicer, I'll take a quick detour.</p>
<h2>Cascading Style Sheets</h2>
devdata/https_mojolicious.io_blog_2018_12_05_compound-selectors_ view on Meta::CPAN
<p>The HTML can be a bit more complicated. Perhaps those interesting tags are in a list. That wraps another layer of HTML structure around the data:</p>
<pre><code><ul class="employees">
<li><img id="bender" class="robot" src="..." /></li>
<li><img id="fry" class="human" src="..." /></li>
<li><img id="leela" class="mutant" src="..." /></li>
</ul>
</code></pre>
<p>If I'd like to affect only those images in that list but only the items in that list. I can specify the ancestry with a compound selector (two or more used together). With just a space between the selectors, this means that the second selector...
<pre><code>ul.employees img.human { border: 1px; }
ul.employees img.robot { margin: 20px; }
</code></pre>
<p>However, this article isn't about all the fancy things that you can do with selectors. You know that they exist and you can see the possibilities in <a href="https://mojolicious.org/perldoc/Mojo/DOM/CSS">Mojo::CSS::Selectors</a>. I'll show...
<h2>Using Selectors with Mojo</h2>
<p>But you can do much more with these. With <a href="https://mojolicious.org/perldoc/Mojo/DOM">Mojo::DOM</a>, which supports CSS Selectors <a href="https://www.w3.org/TR/2018/PR-selectors-3-20180911/">Level 3</a> (and some stuff from <a href="https:...
<p>Start with some HTML. Note the fancy new <a href="https://www.effectiveperlprogramming.com/2016/12/strip-leading-spaces-from-here-docs-with-v5-26/">indented here doc syntax introduced in Perl 5.26</a>:</p>
<pre><code>use v5.28;
use utf8;
use strict;
devdata/https_mojolicious.io_blog_2018_12_05_compound-selectors_ view on Meta::CPAN
</code></pre>
<p><em style="font-size: 10px">
Editor's note: Unfortunately this example breaks our syntax highlighter. This is the site's fault not the author. We're trying to find a better way to render it short of rewriting the rendering engine.
</em></p>
<h2>Conclusion</h2>
<p>Even for an old programmer like me, dealing with HTML through CSS Selectors applied by Mojolicious is much easier than what I was doing before (which was dirty and much easier than doing it correctly). With a little skill creating compound selecto...
</section>
<small><p><a class="external text" href="https://www.flickr.com/photos/feuilllu/101083313/in/photolist-9W5xK-SWEcv6-qmMqBb-9W66e-umaBj-7Gkg2a-bnmWDf-jZPHK7-bAgNFi-bnmW3J-Hd8y3-dYNuYc-Hd9o9-22MW7qW-6qZWkL-7yzScF-24W5o6o-bBNUMi-5QPxcD-boz...
</small>
<p class="tags">
<span>Tagged in </span>:
<a href="/blog/tag/promises/">promises</a>,
<a href="/blog/tag/advent/">advent</a>
</p>
<div class="bio cf">
<div class="gravatar">
<img alt="author image" src="https://secure.gravatar.com/avatar/168427dea0a034607ee7850f3de98ea2.jpg">
</div>
<div class="about">
<h5>brian d foy</h5>
<p><a href="http://www252.pair.com/~comdog/">brian d foy</a> is the author of <a href="https://www.masteringperl.org/">Mastering Perl</a> and <a href="https://www.learningperl6.com/">Learning Perl 6</a>, and the co-author of <...
</div>
</div>
<ul class="post-nav cf">
devdata/https_mojolicious.io_blog_2018_12_05_compound-selectors_ view on Meta::CPAN
<li class="next"><a href="/blog/2018/12/06/making-a-list-with-yancy/index.html" rel="next"><strong>Next Article</strong> Day 6: Making A List with Yancy </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_2018_12_06_making-a-list-with-yancy_ view on Meta::CPAN
</div>
<div class="post-thumb">
<!-- theme suggests 1300x500 -->
<img alt="Santa making a list" src="/blog/2018/12/06/making-a-list-with-yancy/banner.jpg">
</div>
<div class="post-content">
<section id="section-1">
<p>In these modern times, with billions of people in the world, Santa needs a
modern system to keep track of his naughty/nice list. Lucky for Santa, modern
Perl has a modern web framework, <a href="http://mojolicious.org">Mojolicious</a>.</p>
</section>
<section id="section-2">
<h1>Step 1: Build The List</h1>
<p>First, we need a database schema. Santa only really needs to know if someone
has been naughty or nice, so our schema is pretty simple. We'll start our
<a href="https://mojolicious.org/perldoc/Mojolicious/Guides/Tutorial">Mojolicious::Lite</a>
app by connecting to a <a href="http://sqlite.org">SQLite</a> database using
<a href="https://metacpan.org/pod/Mojo::SQLite">Mojo::SQLite</a> and loading our database
schema from the <a href="https://perldoc.perl.org/perldata.html#Special-Literals"><strong>DATA</strong> section of our
script</a> using
<a href="https://metacpan.org/pod/Mojo::SQLite::Migrations">Mojo::SQLite migrations</a>:</p>
<pre><code>use v5.28;
use Mojolicious::Lite;
use Mojo::SQLite;
# Connect to the SQLite database and load our schema from the
# '@@ migrations' section, below
my $db = Mojo::SQLite->new( 'sqlite:thelist.db' );
$db->auto_migrate(1)->migrations->from_data();
# Start the app. Must be the last code of the script.
app->start;
__DATA__
@@ migrations
-- 1 up
CREATE TABLE the_list (
devdata/https_mojolicious.io_blog_2018_12_06_making-a-list-with-yancy_ view on Meta::CPAN
collection => 'the_list',
properties => [qw( is_delivered )],
forward_to => 'the_list.list',
}, 'the_list.deliver';
</code></pre>
<p>With the route configured, we need to add a form to our template. We'll
use <a href="https://mojolicious.org/perldoc/Mojolicious/Plugin/TagHelpers#form_for">the <code>form_for</code> helper from
Mojolicious</a>.
The form will display a yes/no toggle button for every row. Yancy is
secure by default, so we need to make sure that our form contains the
<a href="https://mojolicious.org/perldoc/Mojolicious/Guides/Rendering#Cross-site-request-forgery">CSRF token</a>
(using <a href="https://mojolicious.org/perldoc/Mojolicious/Plugin/TagHelpers#csrf_field">the <code>csrf_field</code> helper</a>)
to prevent cross-site requests.</p>
<pre><code>@@ the_list.html.ep
% layout 'default';
<h1>Naughty List</h1>
<ul class="list-group">
% for my $item ( @$items ) {
<li class="list-group-item d-flex justify-content-between">
devdata/https_mojolicious.io_blog_2018_12_06_making-a-list-with-yancy_ view on Meta::CPAN
button" src="finished-screenshot.png"></p>
<p>We can view our entire list, and check off the ones who we've delivered to already!
<a href="myapp.pl">View the entire app here</a>.</p>
<p><img alt="Santa Robot in his sleigh with burning buildings in the foreground and
background" src="success.png"></p>
<p>Another successful Xmas, powered by <a href="http://mojolicious.org">Mojolicious</a>!</p>
</section>
<small><p><a href="https://pxhere.com/en/photo/1263707">Banner image</a> CC0 Public Domain</p>
</small>
<p class="tags">
<span>Tagged in </span>:
<a href="/blog/tag/advent/">advent</a>,
<a href="/blog/tag/yancy/">yancy</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/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_2018_12_06_making-a-list-with-yancy_ view on Meta::CPAN
<li class="next"><a href="/blog/2018/12/07/openapi/index.html" rel="next"><strong>Next Article</strong> Day 7: MetaCPAN, Mojolicious and 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_2018_12_07_openapi_ view on Meta::CPAN
</div>
<div class="post-thumb">
<!-- theme suggests 1300x500 -->
<img alt="Contract signing" src="/blog/2018/12/07/openapi/banner.jpg">
</div>
<div class="post-content">
<section id="section-1">
<p>During this years <a href="http://www.olafalders.com/2018/11/21/metahack-3-wrap-report/">meta::hack 3</a>, I was extremely fortunate to work with <a href="https://twitter.com/joelaberger">Joel Berger</a> on integrating/documentin...
<h2>What is it?</h2>
<p>OpenAPI is a specification for designing, documenting, validating and driving your RESTful API. It can be used to provide documentation to an existing API, or when creating a new one.</p>
<p>The OpenAPI Specification originated as the Swagger specification and was renamed to separate the API description format (OpenAPI) from the open source tooling (Swagger). The specification moved into a new GitHub repository, but did not change.</p...
<p>In the case of the MetaCPAN API, we set out to provide documentation to the existing API, but quickly moved into supporting validation to API calls as well.</p>
</section>
<section id="section-2">
<h2>The tools</h2>
<p>OpenAPI has many tools available to help, including discovery tools that will assist in writing the specification. We chose to write the definition by hand (in vim of course) and use tools to generate the documentation and to integrate the specifi...
<ul>
<li><a href="https://github.com/Rebilly/ReDoc">ReDoc</a> â OpenAPI/Swagger-generated API Reference Documentation</li>
</ul>
<p>ReDoc creates an interactive page providing documentation and examples based on the details provided in the OpenAPI specification file. ReDoc includes a <a href="https://github.com/Rebilly/ReDoc#tldr">HTML template</a> to be served as a static fil...
devdata/https_mojolicious.io_blog_2018_12_07_openapi_ view on Meta::CPAN
items:
# While items can be further broken into properties per item,
# type `object` is a catch all
type: object
</code></pre>
<h3>Advanced Definitions</h3>
<h4>Reusing definitions through references</h4>
<p>The specification allows for reuse by means of <a href="https://tools.ietf.org/html/draft-pbryan-zyp-json-ref-03">JSON references</a>. The <code>$ref</code> attribute is a relative pointer to the file and section (again separated by <code>#</code>...
<pre><code> results:
title: Results
type: array
items:
$ref: "../definitions/results.yml#/search_result_items"
</code></pre>
<p>The v2.0 specification does have restrictions on where references can be use, which does cause repetition in the specification file. The v3.0 specification has corrected these issues, and also allows for <code>http</code> references.</p>
devdata/https_mojolicious.io_blog_2018_12_07_openapi_ view on Meta::CPAN
<p>The entire specification doesnâÂÂt need to be complete in order to get OpenAPI up and running. When documenting an existing API, itâÂÂs possible to with one portion of the API. With MetaCPAN we started with the search endpoints.</p>
<p>The <a href="https://github.com/metacpan/metacpan-api/blob/master/root/static/v1.yml">spec file can be viewed here</a> and the <a href="https://fastapi.metacpan.org/static/index.html">API documentation here</a></p>
<h2>Further Reading</h2>
<p>The <a href="https://github.com/OAI/OpenAPI-Specification">OpenAPI Specification repository</a> includes full documentation and many examples of varying levels of details.</p>
<p>The <a href="https://openapi-map.apihandyman.io">OpenAPI Map</a> is an interactive site to aid in working with the OpenAPI Specification.</p>
</section>
<small><p>Photo by <a href="https://unsplash.com/photos/GJao3ZTX9gU">Cytonn Photography on Unsplash</a></p>
</small>
<p class="tags">
<span>Tagged in </span>:
<a href="/blog/tag/advent/">advent</a>,
<a href="/blog/tag/development/">development</a>,
<a href="/blog/tag/openapi/">openapi</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/b6d0ff68c2e0d081aba1a94e0f413e8c">
</div>
<div class="about">
<h5>Shawn Sorichetti</h5>
<p>Shawn is a long time Perl developer, with a tendency toward infrastructure, tooling, databases and devops.</p>
</div>
</div>
<ul class="post-nav cf">
devdata/https_mojolicious.io_blog_2018_12_07_openapi_ view on Meta::CPAN
<li class="next"><a href="/blog/2018/12/08/authenticating-with-ldap/index.html" rel="next"><strong>Next Article</strong> Day 8: Authenticating with LDAP </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_2018_12_08_authenticating-with-ldap_ view on Meta::CPAN
</div>
<div class="post-thumb">
<!-- theme suggests 1300x500 -->
<img alt="Who goes there?" src="/blog/2018/12/08/authenticating-with-ldap/banner.jpg">
</div>
<div class="post-content">
<section id="section-1">
<p>There are still quite a few people using LDAP in production,
but for those who are new to it,
LDAP is a directory with a tree-structure that's optimised for very fast lookups.
It used to be very common as a centralised authentication system
and if you're using Active Directory, you're using LDAP (mostly).
I wander through the wilderness of authentication,
ending with my solution on how to add LDAP authentication to your App.</p>
</section>
<section id="section-2">
<p>This post is based on a
<a href="https://docs.google.com/presentation/d/14ZbARlTj_3mxEf_9Bvbrz0AUYjQdFjIXfYuttb_J7uU">talk</a>
I gave at
<a href="https://act.yapc.eu/lpw2018">London Perl Workshop</a>
in 2018.
It's a little optimistic thinking that they'll get through
editing all the videos before Christmas, but we could hope
for an epiphany.
LDAP is just a small part of the authentication cycle here, so
this post generalises fairly well for those cases where you have
devdata/https_mojolicious.io_blog_2018_12_08_authenticating-with-ldap_ view on Meta::CPAN
sub check_credentials {
my ($username, $password) = @_;
my $encrypted = sha256($password);
...
$sth->execute($username, $encrypted) or return;
</code></pre>
<p>Technically, AES is an encryption algorithm and SHA-2 is a hashing algorithm,
meaning that the transformation is effectively one-way and is more secure.
Here are a couple of modules that make it easier and safer:</p>
<p>A nice module out there for handling passwords is, well,
<a href="https://metacpan.org/pod/Passwords">Passwords</a>.
It's just a wrapper around some other modules that gives you a simple API
and will use <a href="https://metacpan.org/pod/Crypt::Eksblowfish::Bcrypt">Bcrypt</a> by default.
So if you've hashed your password with the <code>password_hash</code> function
and stored the <code>$hash</code> value in your database like this</p>
<pre><code>my $hash = password_hash($initial_password);
devdata/https_mojolicious.io_blog_2018_12_08_authenticating-with-ldap_ view on Meta::CPAN
<p>Y'know, I'm sitting here on the Group W bench thinkin' ...
if I'm going to re-write this whole tutorial, maybe I should've started with
<a href="https://metacpan.org/pod/Mojolicious::Plugin::Authentication">Mojolicious::Plugin::Authentication</a>
and taken you through the code you needed for the <code>validate_user</code> option in the Plugin.
But let's leave that for next year.</p>
<p>Further reading on storing passwords:</p>
<ul>
<li><a href="https://crackstation.net/hashing-security.htm#properhashing">Secure Salted Password Hashing</a> by Defuse Security.</li>
</ul>
<h2>How to <a href="https://metacpan.org/pod/Net::LDAP">LDAP</a></h2>
<p><em>remember LDAP? ... this is a post about LDAP</em></p>
<p>These are the steps to authenticating:</p>
<ol>
<li>Connect to the LDAP server</li>
devdata/https_mojolicious.io_blog_2018_12_08_authenticating-with-ldap_ view on Meta::CPAN
<a href="https://mojolicious.io/blog/2017/12/03/day-3-using-named-routes/">named routes</a>
gives you the flexibility of changing URLs without much hassle.</p>
<h2>Where next?</h2>
<p>I go through the whole process of authenticating and maintaining sessions at my
<a href="https://github.com/duffee/Mojolicious_session_example">Mojolicious session tutorial</a>
which will be getting some updates in the New Year to reflect what I've learned.
Contributions welcome!</p>
</section>
<small><p><a href="https://www.flickr.com/photos/maxlfly/1834725880/">Image</a> by <a href="https://www.flickr.com/people/85105517@N00">Alex Grech</a> <a href="https://creativecommons.org/licenses/by/2.0" title="Creative Commons Attribu...
</small>
<p class="tags">
<span>Tagged in </span>:
<a href="/blog/tag/advent/">advent</a>,
<a href="/blog/tag/ldap/">LDAP</a>,
<a href="/blog/tag/authentication/">authentication</a>
</p>
devdata/https_mojolicious.io_blog_2018_12_08_authenticating-with-ldap_ view on Meta::CPAN
<li class="next"><a href="/blog/2018/12/09/add-a-theme-system-to-your-mojolicious-app/index.html" rel="next"><strong>Next Article</strong> Day 9: Add a theme system to your Mojolicious 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_2018_12_09_add-a-theme-system-to-your-mojolicious-app_ view on Meta::CPAN
</div>
<div class="post-thumb">
<!-- theme suggests 1300x500 -->
<img alt="Four lines of paint drawn on a roller, in green, red, orange and blue" src="/blog/2018/12/09/add-a-theme-system-to-your-mojolicious-app/banner.jpg">
</div>
<div class="post-content">
<section id="section-1">
<p>You wrote an awesome Mojolicious app, and people use it.
Marvellous!
But users may want to modify the theme of your app: change the logo, use another CSS framework, such sort of things.</p>
<p>Modifying the theme of a Mojolicious app is quite easy: add, modify or delete things in <code>public</code> and <code>templates</code>.
But all those direct modifications may not survive on update of the app: they will simply be erased by the files of the new version.</p>
<p>Let's see how we can provide a way to have a theme system in a Mojolicious application, that allows users to have a custom theme without pain and without risk of losing it on updates.</p>
</section>
<section id="section-2">
<h2>A fresh application</h2>
<p>When you create a new Mojolicious app with <code>mojo generate MyApplication</code>, these are the default directories that will serve files and their default contents to be served:</p>
<pre><code>$ tree public templates
public
âÂÂâÂÂâ index.html
templates
âÂÂâÂÂâ example
âÂÂààâÂÂâÂÂâ welcome.html.ep
devdata/https_mojolicious.io_blog_2018_12_09_add-a-theme-system-to-your-mojolicious-app_ view on Meta::CPAN
<p>Note the <code>if -d $theme.'/templates'</code>: it prevents problems if the use made a typo in the name of the theme and allow to avoid creating both <code>templates</code> and <code>public</code> in the theme directory if you only need o...
<h2>Conclusion</h2>
<p>You are now providing a theme system in your application.
Users will now be able to change the style of it without fearing losing their changes on updates (though they will need to check the changes they made in case the default theme changed a lot).</p>
<p>You may even provides different themes yourself, like I did for my <a href="https://framagit.org/fiat-tux/hat-softwares/lstu">URL-shortening app, Lstu</a>àðÂÂÂ</p>
</section>
<small><p><a href="https://unsplash.com/photos/46juD4zY1XA">Photo</a> by <a href="https://unsplash.com/@davidpisnoy">David Pisnoy</a>, <a href="https://unsplash.com/license">Unsplash license</a> (quite similar to public domain)</p>
</small>
<p class="tags">
<span>Tagged in </span>:
<a href="/blog/tag/advent/">advent</a>,
<a href="/blog/tag/theme/">theme</a>
</p>
devdata/https_mojolicious.io_blog_2018_12_09_add-a-theme-system-to-your-mojolicious-app_ view on Meta::CPAN
<li class="next"><a href="/blog/2018/12/10/minion-stands-alone/index.html" rel="next"><strong>Next Article</strong> Day 10: Minion Stands Alone </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_2018_12_10_minion-stands-alone_ view on Meta::CPAN
</div>
<div class="post-thumb">
<!-- theme suggests 1300x500 -->
<img alt="Minion logo in front of a faded Mojolicious cloud, original artwork by Doug Bell" src="/blog/2018/12/10/minion-stands-alone/banner.jpg">
</div>
<div class="post-content">
<section id="section-1">
<p>The <a href="https://mojolicious.org/perldoc/Minion">Minion job queue</a> is an
incredibly useful tool, but sometimes I need to use it for non-web
projects. So, how can I use Minion without needing
a <a href="http://mojolicious.org">Mojolicious</a> web application?</p>
</section>
<section id="section-2">
<p>If I don't have a large enough set of jobs to need the task organization
provided by <a href="https://metacpan.org/pod/Beam::Minion">Beam::Minion</a>, and although
Minion can be used as a <a href="https://mojolicious.org/perldoc/Minion#SYNOPSIS">fully stand-alone
library</a>, the easiest solution
is just to build a Mojolicious app. Lucky for me, a Mojolicious app can be just
2 lines:</p>
<pre><code>use Mojolicious::Lite;
app->start;
</code></pre>
devdata/https_mojolicious.io_blog_2018_12_10_minion-stands-alone_ view on Meta::CPAN
plugin Minion => {
SQLite => 'sqlite:' . app->home->child('minion.db'),
};
app->minion->add_task(
check_url => sub( $job, $url ) {
my $start = time;
my $tx = $job->app->ua->head( $url );
my $elapsed = time - $start;
$job->app->log->info(
sprintf 'Fetching %s took %.3f seconds', $url, $elapsed
);
# If there's an error loading the web page, fail the job
if ( $tx->error ) {
$job->app->log->error(
sprintf 'Error loading URL (%s): %s (%s)',
$url, @{ $tx->error }{qw( code message )},
);
return $job->fail(
sprintf '%s: %s', @{ $tx->error }{qw( code message )}
);
devdata/https_mojolicious.io_blog_2018_12_10_minion-stands-alone_ view on Meta::CPAN
<pre><code>$ perl myapp.pl minion worker
</code></pre>
<p>Once the worker starts up, it will immediately begin processing the jobs
I told it to run.</p>
<p>And that's it! I'm using Minion without a Mojolicious
web application. View the source of the <a href="minion.pl">Minion app</a> and the
<a href="enqueue.pl">enqueue.pl script</a>.</p>
</section>
<small><p>Original artwork by Doug Bell, released under CC-BY-SA 4.0. It includes
a screenshot of the Mojolicious.org website (fair use), the Mojolicious
logo (CC-BY-SA 4.0), and the Minion logo (CC-BY-SA 4.0)</p>
</small>
<p class="tags">
<span>Tagged in </span>:
<a href="/blog/tag/advent/">advent</a>,
<a href="/blog/tag/minion/">minion</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_2018_12_10_minion-stands-alone_ view on Meta::CPAN
<li class="next"><a href="/blog/2018/12/11/who-watches-the-minions/index.html" rel="next"><strong>Next Article</strong> Day 11: Who Watches The Minions </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_2018_12_11_who-watches-the-minions_ view on Meta::CPAN
</div>
<div class="post-thumb">
<!-- theme suggests 1300x500 -->
<img alt="Minion logo in the middle of binocular circles, original artwork by Doug Bell" src="/blog/2018/12/11/who-watches-the-minions/banner.jpg">
</div>
<div class="post-content">
<section id="section-1">
<p>Now that I have a <a href="https://mojolicious.org/perldoc/Minion">Minion job
queue</a>, I need to take care of
it properly. Are the workers working (have they seized the means of
production)? Are jobs completing successfully? Are there any errors?
What are they?</p>
</section>
<section id="section-2">
<h2>Minion Jobs Command</h2>
<p>Minion comes with a <a href="https://mojolicious.org/perldoc/Minion/Command/minion/job"><code>job</code>
command</a> that
lists the jobs and their statuses.</p>
<pre><code>$ perl myapp.pl minion job
6 inactive default check_url
5 active default check_url
4 failed default check_url
devdata/https_mojolicious.io_blog_2018_12_11_who-watches-the-minions_ view on Meta::CPAN
<p>When looking at a list of jobs, I can click the buttons on top left to
manage the job queue, or click on the caret on the right of each job row
to view the details of that job (the same as the <code>job</code> command shows).</p>
<p><img alt="A web browser showing the details of a single Minion job as
JSON" src="03-job-details.png"></p>
<p>The Minion Admin UI is a great addition to a great tool! <a href="minion.pl">View the entire
source of the Minion app</a></p>
</section>
<small><p>Original artwork by Doug Bell, released under CC-BY-SA 4.0. It includes
the Minion logo (CC-BY-SA 4.0)</p>
</small>
<p class="tags">
<span>Tagged in </span>:
<a href="/blog/tag/advent/">advent</a>,
<a href="/blog/tag/minion/">minion</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_2018_12_11_who-watches-the-minions_ view on Meta::CPAN
<li class="next"><a href="/blog/2018/12/12/dancer-and-minion/index.html" rel="next"><strong>Next Article</strong> Day 12: Using Minion in Dancer Apps </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_2018_12_12_dancer-and-minion_ view on Meta::CPAN
</div>
<div class="post-thumb">
<!-- theme suggests 1300x500 -->
<img alt="Stylistic photograph of Disney-style minion toys" src="/blog/2018/12/12/dancer-and-minion/banner.jpg">
</div>
<div class="post-content">
<section id="section-1">
<p>At <code>$work</code>, we have built an API with <a href="https://metacpan.org/pod/Dancer">Dancer</a> that generates PDF documents and XML files. This API is a critical component of an insurance enrollment system: PDFs are genera...
immediately, and the XML is delivered to the carrier as soon as it becomes available. Since the XML often takes a significant amount of time to generate, the job is generated in the background so as not to tie up the
application server for an extended amount of time. When this was done, a homegrown process management system was developed, and works by <code>fork()</code>ing a process, tracking its pid, and hoping we can later successfully
reap the completed process.</p>
<p>There have been several problems with this approach:
- it's fragile
- it doesn't scale
- it's too easy to screw something up as a developer</p>
<p>In 2019, we have to ramp up to take on a significantly larger workload. The current solution simply will not handle the amount of work we anticipate needing to handle. Enter <a href="https://metacpan.org/pod/Minion">Minion</a>.</p>
<p><em>Note:</em> The techniques used in this article work equally well with Dancer or <a href="https://metacpan.org/pod/Dancer2">Dancer2</a>.</p>
</section>
<section id="section-2">
<h2>Why Minion?</h2>
<p>We looked at several alternatives to Minion, including <a href="https://beanstalkd.github.io/">beanstalkd</a> and <a href="http://www.celeryproject.org/">celeryd</a>. Using either one of these meant involving our already over-taxed
infrastructure team, however; using Minion allowed us to use expertise that my team already has without having to burden someone else with assisting us. From a development standpoint, using a product that
was developed in Perl gave us the quickest time to implementation.</p>
<p>Scaling our existing setup was near impossible. It's not only difficult to get a handle on what resources are consumed by processes we've forked, but it was impossible to run the jobs on more than one server.
Starting over with Minion also gave us a much needed opportunity to clean up some code in sore need of refactoring. With a minimal amount of work, we were able to clean up our XML rendering code and make it work
from Minion. This cleanup allowed us to more easily get information as to how much memory and CPU was consumed by an XML rendering job. This information is vital for us in planning future capacity.</p>
devdata/https_mojolicious.io_blog_2018_12_12_dancer-and-minion_ view on Meta::CPAN
if( exists $minion_config->{ $hostname }) {
return $minion_config->{ $hostname };
} else {
return $minion_config->{ default };
}
}
</code></pre>
<h2>Monitoring the Workers</h2>
<p>Our Minion dashboard was virtually identical to the one that @preaction posted in <a href="https://mojolicious.io/blog/2018/12/11/who-watches-the-minions/#section-2">Who Watches the Minions?</a>.
If you'd like to know more, I highly recommend reading his article.</p>
<h2>Outcome</h2>
<p>Within about a two-week timespan, we went from having zero practical knowledge of Minion to having things up and running. We've made some refinements and improvements along the way, but the quick turnaround
is a true testament to the simplicity of working with Minion.</p>
<p>We now have all the necessary pieces in place to scale our XML rendering both horizontally and vertically: thanks to Minion, we can easily run XML jobs across multiple boxes, and can more efficiently run
more jobs concurrently on the same hardware as before. This setup allows us to grow as quickly as our customer base does.</p>
<h2>Further Reading</h2>
<ul>
<li><a href="https://metacpan.org/pod/Dancer">Dancer</a></li>
<li><a href="https://metacpan.org/pod/Dancer2">Dancer2</a></li>
<li><a href="https://metacpan.org/pod/Minion">Minion</a></li>
</ul>
</section>
<small><p>Banner image: <a href="https://www.flickr.com/photos/enerva/9068467267">One Eyed Minion</a> by <a href="https://www.flickr.com/photos/enerva/">Sonny Abesamis</a> licensed <a href="https://creativecommons.org/licenses/by/2.0/">...
</small>
<p class="tags">
<span>Tagged in </span>:
<a href="/blog/tag/advent/">advent</a>,
<a href="/blog/tag/development/">development</a>,
<a href="/blog/tag/dancer/">dancer</a>,
<a href="/blog/tag/minion/">minion</a>
</p>
devdata/https_mojolicious.io_blog_2018_12_12_dancer-and-minion_ view on Meta::CPAN
<li class="next"><a href="/blog/2018/12/13/taking-on-roles/index.html" rel="next"><strong>Next Article</strong> Day 13: Taking on 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_2018_12_13_taking-on-roles_ view on Meta::CPAN
</div>
<div class="post-thumb">
<!-- theme suggests 1300x500 -->
<img alt="Elgin Theater" src="/blog/2018/12/13/taking-on-roles/banner.jpg">
</div>
<div class="post-content">
<section id="section-1">
<p>In my previous Advent article, I created <a href="/blog/2018/12/03/higher-order-promises/">higher-order promises</a> and showed you how to use them. I didn't show you the magic of how they work. Now I'll develop another e...
</section>
<section id="section-2">
<p>There are times that I want <a href="https://mojolicious.org/perldoc/Mojo/File">Mojo::File</a> to act a bit differently than it does. Often I have a path where I want to combine only the basename with a different directory. I end...
<pre><code>use Mojo::File qw(path);
my $path = Mojo::File->new( '/Users/brian/bin/interesting.txt' );
my $dir = Mojo::File->new( '/usr/local/bin' );
my $new_path = $dir->child( $path->basename );
say $new_path; # /usr/local/bin/interesting.txt
</code></pre>
devdata/https_mojolicious.io_blog_2018_12_13_taking-on-roles_ view on Meta::CPAN
my $file = Mojo::File
->with_roles( '+MyUtils' )
->new(shift);
say $file->sha1;
say $file->md5;
</code></pre>
<p>You can read more about roles in Joel Berger's 2017 Mojolicious Advent Calendar entry <a href="https://mojolicious.io/blog/2017/12/13/day-13-more-about-roles/">Day 13: More About Roles</a>. Curiously that was on Day 13 too, although I don'...
</section>
<small><p><a class="external text" href="https://www.flickr.com/photos/eskimo_jo/27387510917/in/photolist-HJ99Q6-fziGbA-fypQyz-7pCEK2-e6kG1-8NxgJh-9gKfaE-eEhB2w-9wc7yk-fwnRyf-62b1R6-27u47Nh-4ohfrN-9o2vut-2xyVmv-2yas82-ctV3fq-nBYJN4-q6zk...
</small>
<p class="tags">
<span>Tagged in </span>:
<a href="/blog/tag/roles/">roles</a>,
<a href="/blog/tag/advent/">advent</a>
</p>
<div class="bio cf">
<div class="gravatar">
<img alt="author image" src="https://secure.gravatar.com/avatar/168427dea0a034607ee7850f3de98ea2.jpg">
</div>
<div class="about">
<h5>brian d foy</h5>
<p><a href="http://www252.pair.com/~comdog/">brian d foy</a> is the author of <a href="https://www.masteringperl.org/">Mastering Perl</a> and <a href="https://www.learningperl6.com/">Learning Perl 6</a>, and the co-author of <...
</div>
</div>
<ul class="post-nav cf">
devdata/https_mojolicious.io_blog_2018_12_13_taking-on-roles_ view on Meta::CPAN
<li class="next"><a href="/blog/2018/12/14/a-practical-example-of-mojo-dom/index.html" rel="next"><strong>Next Article</strong> Day 14: A Practical Example of Mojo::DOM </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_2018_12_14_a-practical-example-of-mojo-dom_ view on Meta::CPAN
</div>
<div class="post-thumb">
<!-- theme suggests 1300x500 -->
<img alt="A typical industrial platform model overlaid with a laser scan" src="/blog/2018/12/14/a-practical-example-of-mojo-dom/banner.png">
</div>
<div class="post-content">
<section id="section-1">
<p>With recent versions of Mojolicious, <a href="https://mojolicious.org/perldoc/Mojo/DOM">Mojo::DOM</a> gained a lot of power that I have been excited to try, but haven't had the time for. Recently, I had a problem at my real ...
</section>
<section id="section-2">
<h2>The task - simple, but tedious.</h2>
<p>3D models and drawings are fantastic tools, but in reality things are not so perfect. Construction tolerances being what they are, our company relies a lot on <a href="https://www.youtube.com/watch?v=H-uNzEmt5sw">laser scanning</a>, where we go o...
<p>The problem is when our 3D modeling software (<a href="https://www.tekla.com/products/tekla-structures">Tekla Structures</a>) processes the point clouds, it changes the file names of each one from something human readable, such as <code>Pipe Rack ...
<p><img alt="Point clouds add information that is not available in the 3D model" src="pointcloud1.jpg">
<em>Point clouds provide critical information that is either too difficult or too costly to model directly</em></p>
<p>Fortunately, Tekla uses a lot of standard file formats that anyone can edit â including using XML to describe each point cloud it has processed. Of course, I could just hand edit them to change the names, but that would have to be done for e...
devdata/https_mojolicious.io_blog_2018_12_14_a-practical-example-of-mojo-dom_ view on Meta::CPAN
<p><img alt="Point clouds are not perfect, but are still a valuable tool" src="pointcloud2.jpg">
<em>Note the grainy nature of the point cloud - since they are just points with no area, the closer you get, the grainier it looks</em></p>
<h2>Useful for all skill levels</h2>
<p>This is just one example of how I have used Mojolicious in my day job. Sometimes, existing software doesn't do what you want, or does it in a format that's not useful - problems that can be solved with the many tools Mojolicious provides....
<p>My next project idea is to rebuild a reporting tool I wrote for Material Take Offs (MTOs) to work with Tekla, which our engineers loved with our old modeling software - and I'm sure I will continue to find good uses for Mojolicious well into t...
</section>
<small><p>Original screenshots by maschine, released under CC-BY-SA 4.0.</p>
</small>
<p class="tags">
<span>Tagged in </span>:
<a href="/blog/tag/advent/">advent</a>,
<a href="/blog/tag/xml/">xml</a>,
<a href="/blog/tag/non-web/">non-web</a>
</p>
devdata/https_mojolicious.io_blog_2018_12_14_a-practical-example-of-mojo-dom_ view on Meta::CPAN
<li class="next"><a href="/blog/2018/12/15/practical-web-content-munging/index.html" rel="next"><strong>Next Article</strong> Day 15: Practical Web Content Munging </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_2018_12_15_practical-web-content-munging_ view on Meta::CPAN
</div>
<div class="post-thumb">
<!-- theme suggests 1300x500 -->
<img alt="An eyeball of alarming size" src="/blog/2018/12/15/practical-web-content-munging/banner.jpg">
</div>
<div class="post-content">
<section id="section-1">
<p>Following brian d foy's great <a href="https://mojolicious.io/blog/2018/12/05/compound-selectors/">write-up of using Mojo::DOM selectors from Day 5</a>, I thought it'd be fun to talk about some website migration scripts I...
<h2>From Static Site to Static Site Generator</h2>
<p>The problem I set out to solve was taking an old static website that was once hosted on SourceForge.net and migrating it to an exciting new...um...static website. But, this time, it'll be a modern take on a static website. Instead of editing H...
</section>
<section id="section-2">
<p>Hugo, like most modern static site generators, expects content to be in Markdown format with some metadata at the top of the file. I want to convert our crusty old HTML, as you'll see an example of below, into something that ...
<pre><code>---
title: "Frobnitz 3.141593 released"
date: 2016-10-10
description: "This release includes a fog-flavored bauble of three equal sides, providing the restless..."
categories: []
aliases: []
toc: false
draft: false
devdata/https_mojolicious.io_blog_2018_12_15_practical-web-content-munging_ view on Meta::CPAN
<p>This will display the response body with its HTML contents. But, that's not really very interesting. But, we can do much more interesting and powerful things very easily with a Mojo response.</p>
<h2>CSS Selectors</h2>
<p>The <code>res</code> response object provides a <code>dom</code> object, that gives the ability to select parts of an HTML document using CSS selectors. So, if I have a document with a <code>#main</code> div, I can retrieve just the contents of th...
<pre><code>my $main = $tx->res->dom->find("#main");
</code></pre>
<p>Of course, if you're familiar with CSS selectors, you know it can be more precise than that. So, let's talk about something concrete. In my case, I have a couple of different types of page. One is a page of news items, which is lots of sec...
<p>I want to divide those news items out into their own individual pages, which can then be aggregated in whatever way I like, such as having them available in a paginated list or having the most recent items included in a div on the front page of th...
<p>Those news items look something like this on the old site:</p>
<pre><code><h1>Latest News</h1>
<h3>Frobnitz 4.5 released</h3>
<p>
This release improves castigation of the widely formed sonterols.
devdata/https_mojolicious.io_blog_2018_12_15_practical-web-content-munging_ view on Meta::CPAN
</code></pre>
<p>There's a lot going on here, and I'll only briefly explain some of it, since it's not Mojo-related.</p>
<p>The first line of the loop creates a description, which is usually a summary or whatever. In my case, the main site will show the description as a clickable link, so the user will get a short summary of the news item on the main page, and then the...
<p>Then, in the here document, I fill in all the metadata, using values from <code>$e</code>, each of which is just a reference to a hash. Then we write it to a file using the <code>spurt</code> method of <a href="https://mojolicious.org/perldoc/Mojo...
<p>In the interest of clarity and brevity (and because it's basic Perl and not Mojo-related) I've left out the loops and building of the data structure that I used when generating metadata. If you want to see it all in one place, with some ug...
</section>
<small><p>Banner image: <a href="https://flic.kr/p/Rqj9Jj">An eyeball looking at Dallas</a> by <a href="https://www.flickr.com/photos/nerdnomad/">Joe Cooper</a> licensed <a href="https://creativecommons.org/licenses/by-nc-sa/2.0/">CC BY...
</small>
<p class="tags">
<span>Tagged in </span>:
<a href="/blog/tag/advent/">advent</a>,
<a href="/blog/tag/css/">css</a>,
<a href="/blog/tag/html/">html</a>
</p>
devdata/https_mojolicious.io_blog_2018_12_15_practical-web-content-munging_ view on Meta::CPAN
<li class="next"><a href="/blog/2018/12/16/browser-diet/index.html" rel="next"><strong>Next Article</strong> Day 16: A pre-Christmas Diet for Mojolicious - A Children's Story </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_2018_12_16_browser-diet_ view on Meta::CPAN
</div>
<div class="post-thumb">
<!-- theme suggests 1300x500 -->
<img alt="Too many nuts. I'm gonna need to slim down" src="/blog/2018/12/16/browser-diet/squirrel.jpg">
</div>
<div class="post-content">
<section id="section-1">
<p>You've just read
<a href="https://browserdiet.com">How to lose Weight in the Browser</a>
and you want to know to slim down your Mojo app.
Part of that process is preventing the browser from requesting files
that hardly change.
I spent a well-caffeinated afternoon trying to do that with
Mojolicious.
I've been 'round the houses, and <em>spoiler alert</em> I didn't find
the answer until the very end, kind of like your favourite Christmas
animated special with a small woodland creature narrating
devdata/https_mojolicious.io_blog_2018_12_16_browser-diet_ view on Meta::CPAN
Mojolicious could prepare the webpages with the correct JSON feed for each user.
With some JavaScript libraries to display the web calendar,
all would be well in the forest.</p>
<p>Everything except the JavaScript libraries are lightweight.
And everyone knows a page reload goes <em>so</em> much faster if it doesn't have to download the
JavaScript every time. Those libraries won't change for months!
If only the client browser knew that it could use the file that it had downloaded
last time.</p>
<p>The secret, of course, is to set the <code>Cache-Control</code> field of the HTTP header, but <em>how</em>?</p>
</section>
<section id="section-2">
<h2>First, there was a <a href="https://httpd.apache.org/">Horse</a> ...</h2>
<p>Everybody using Apache would be thinking about using
<a href="https://httpd.apache.org/docs/2.4/mod/mod_expires.html">mod_expires</a>
which looks quite easy, except that Apache wasn't being used to serve the webpages.</p>
<p>... but the Horse mentioned where there were some sweet
<a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control">Cache-Control directives</a>
to munch on and while continuing to graze on some
<a href="https://developers.google.com/web/fundamentals/performance/optimizing-content-efficiency/http-caching">HTTP Caching</a>
devdata/https_mojolicious.io_blog_2018_12_16_browser-diet_ view on Meta::CPAN
user-configurable limits on what you think is acceptable.</p>
<p>Google's <a href="https://developers.google.com/speed/pagespeed/insights">PageSpeed Insights</a>
measures performance on both mobile and desktop.</p>
<p>Hopefully, the increasingly awkward attempt at writing in a narrative style
didn't get in the way of a new idea or two. <a href="https://github.com/duffee/Mojolicious_session_example">Let me
know</a> if I've missed
something.</p>
</section>
<small><p><a href="https://www.flickr.com/photos/55426027@N03/16915881989">Image</a> by <a href="https://www.flickr.com/photos/55426027@N03">Peter G Trimming</a> <a href="https://creativecommons.org/licenses/by/2.0"> CC BY 2.0 </a></p>
</small>
<p class="tags">
<span>Tagged in </span>:
<a href="/blog/tag/advent/">advent</a>,
<a href="/blog/tag/caching/">caching</a>,
<a href="/blog/tag/headers/">headers</a>
</p>
devdata/https_mojolicious.io_blog_2018_12_16_browser-diet_ view on Meta::CPAN
<li class="next"><a href="/blog/2018/12/17/a-website-for-yancy/index.html" rel="next"><strong>Next Article</strong> Day 17: A Website For Yancy </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_2018_12_17_a-website-for-yancy_ view on Meta::CPAN
</div>
<div class="post-thumb">
<!-- theme suggests 1300x500 -->
<img alt="Code on a computer screen" src="/blog/2018/12/17/a-website-for-yancy/banner.jpg">
</div>
<div class="post-content">
<section id="section-1">
<p>For this year, I decided that Yancy needed a website. Rather than build
a website with a <a href="http://preaction.me/statocles">static site generator like
Statocles</a>, which is so popular these
days, I decided to do something wild and unpredictable: A dynamic
website! Lucky for me, I have the perfect project to easily build
a dynamic website: Yancy!</p>
</section>
<section id="section-2">
<p>The key part of any dynamic website is the database. Since I just want
to write Markdown and render HTML, my schema is quite simple: A place to
store the page's path, a place to store the page's Markdown for editing,
and a place to put the rendered HTML. I set up a SQLite database and
build the pages table using
<a href="https://metacpan.org/pod/Mojo::SQLite::Migrations">Mojo::SQLite::Migrations</a>.</p>
<pre><code>#!/usr/bin/env perl
use Mojolicious::Lite;
use Mojo::SQLite;
devdata/https_mojolicious.io_blog_2018_12_17_a-website-for-yancy_ view on Meta::CPAN
</html>
</code></pre>
<p>Now I can open my website and see the index page I created!</p>
<p><img alt="Screenshot showing the index page for the site" src="view-index.png"></p>
<p>Now I have a basic website! <a href="myapp.pl">Here's the code so far</a>. This is
a good start, but I'll need more if it's going to be useful...</p>
</section>
<small><p>Banner image CC0 Public Domain</p>
</small>
<p class="tags">
<span>Tagged in </span>:
<a href="/blog/tag/advent/">advent</a>,
<a href="/blog/tag/yancy/">yancy</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_2018_12_17_a-website-for-yancy_ view on Meta::CPAN
<li class="next"><a href="/blog/2018/12/18/a-view-to-a-pod/index.html" rel="next"><strong>Next Article</strong> Day 18: A View To A POD </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_2018_12_18_a-view-to-a-pod_ view on Meta::CPAN
</div>
<div class="post-thumb">
<!-- theme suggests 1300x500 -->
<img alt="Books on a library shelf" src="/blog/2018/12/18/a-view-to-a-pod/banner.jpg">
</div>
<div class="post-content">
<section id="section-1">
<p>In order for Yancy to have a good documentation site, it needs to
actually render the documentation. To render Perl documentation in
<a href="http://mojolicious.org">Mojolicious</a>, I can use the
<a href="http://metacpan.org/pod/Mojolicious::Plugin::PODViewer">PODViewer</a>
plugin (a fork of the now-deprecated
<a href="http://mojolicious.org/perldoc/Mojolicious/Plugin/PODRenderer">PODRenderer</a>
plugin).</p>
</section>
<section id="section-2">
<p>Adding PODViewer to the existing site is easy!</p>
<pre><code>use Mojolicious::Lite;
plugin 'PODViewer';
app->start;
</code></pre>
<p>Now when I visit <a href="http://127.0.0.1:3000/perldoc">http://127.0.0.1:3000/perldoc</a> I see the POD for
<a href="http://mojolicious.org/perldoc">Mojolicious::Guides</a>. That's great and
all, but this is a documentation site for Yancy, not Mojolicious. Let's
devdata/https_mojolicious.io_blog_2018_12_18_a-view-to-a-pod_ view on Meta::CPAN
</html>
</code></pre>
<p>Now our documentation looks good!</p>
<p><img alt="Screenshot of Yancy module documenation with new style" src="good-docs.png"></p>
<p><a href="myapp.pl">Here's the full source</a>. Now that I have a beautiful
website, I just need to deploy the new site to the Internet...</p>
</section>
<small><p>Banner image CC0 Public Domain</p>
</small>
<p class="tags">
<span>Tagged in </span>:
<a href="/blog/tag/advent/">advent</a>,
<a href="/blog/tag/documentation/">documentation</a>,
<a href="/blog/tag/yancy/">yancy</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_2018_12_18_a-view-to-a-pod_ view on Meta::CPAN
<li class="next"><a href="/blog/2018/12/19/you-only-export-twice/index.html" rel="next"><strong>Next Article</strong> Day 19: You Only Export Twice </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_2018_12_19_you-only-export-twice_ view on Meta::CPAN
</div>
<div class="post-thumb">
<!-- theme suggests 1300x500 -->
<img alt="Container ship leaving port" src="/blog/2018/12/19/you-only-export-twice/banner.jpg">
</div>
<div class="post-content">
<section id="section-1">
<p>With my Yancy documentation site built, with <a href="/blog/2018/12/17/a-website-for-yancy">a custom landing
page</a> and <a href="/blog/2018/12/18/a-view-to-a-pod">a POD
viewer</a>, I just need to deploy the site. I
could deploy the site using <a href="https://mojolicious.org/perldoc/Mojolicious/Guides/Cookbook#Hypnotoad">hypnotoad, Mojolicious's preforking server with
hot
deployment</a>,
but that would require me to have a server and keep it online. It'd be a lot
better if I could just deploy a <a href="https://pages.github.com">static website to
Github</a> like all the cool people are doing.</p>
<p>But to do that, I'd need to take my dynamic website and turn it into a static
one, and that's impossible! Or is it? Why am I asking me, when I'm the one who
wrote a way to do it: The <a href="https://metacpan.org/pod/Mojolicious::Command::export">Mojolicious export
command</a>.</p>
</section>
<section id="section-2">
<p>The export command takes a set of paths as input, fetches those pages, and
writes the result to a directory. It then looks at all the links on those pages
and writes those pages, too. In this way, it exports an entire Mojolicious
website as static files.</p>
<p>All I need to do to be able to use the export command is to install it:</p>
<pre><code>$ cpanm Mojolicious::Command::export
</code></pre>
devdata/https_mojolicious.io_blog_2018_12_19_you-only-export-twice_ view on Meta::CPAN
broken links. If anyone is interested in helping out with this work, let me
know and I can help get them started!</p>
<p>Now, with <a href="http://preaction.me/yancy">the Yancy CMS</a>, <a href="http://metacpan.org/pod/Mojolicious::Plugin::PODViewer">the PODViewer
plugin</a>, and <a href="http://metacpan.org/pod/Mojolicious::Command::export">the
Mojolicious export
command</a>, I've got a
good-looking documentation website for Yancy! <a href="https://github.com/MojoliciousDotIO/mojolicious.io/blob/master/blog/2018/12/19/you-only-export-twice/myapp.pl">View the full, completed
application</a>.</p>
</section>
<small><p>Banner image CC0 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/yancy/">yancy</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_2018_12_19_you-only-export-twice_ view on Meta::CPAN
<li class="next"><a href="/blog/2018/12/20/testing-dancer/index.html" rel="next"><strong>Next Article</strong> Day 20: Testing Dancer </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_2018_12_20_testing-dancer_ view on Meta::CPAN
</div>
<div class="post-thumb">
<!-- theme suggests 1300x500 -->
<img alt="Dancers and judges at a dance competition" src="/blog/2018/12/20/testing-dancer/banner.jpg">
</div>
<div class="post-content">
<section id="section-1">
<p>Authors of Dancer (and other) PSGI applications are probably accustomed to <a href="https://metacpan.org/pod/distribution/Dancer2/lib/Dancer2/Manual.pod#TESTING">testing</a> with <a href="https://metacpan.org/pod/Plack::Test">Pla...
<p>During advent last year, I wrote about <a href="https://mojolicious.org/perldoc/Test/Mojo">Test::Mojo</a>, showing the many easy and (dare I say) fun ways that you can use it to test your Mojolicious applications.
If you missed it, go <a href="https://mojolicious.io/blog/2017/12/09/day-9-the-best-way-to-test/">check it out</a>.</p>
<p>I expect there are at least a few of you out there who read that and think, "I'd love to use that, but I don't use Mojolicious!"; well, you're in luck!
With just a little role to bridge the gap, you can use Test::Mojo to test your PSGI applications too!</p>
</section>
<section id="section-2">
<h2>Mounting PSGI Applications</h2>
<p>Mojolicious itself doesn't use the <a href="https://metacpan.org/pod/PSGI">PSGI</a> protocol, owing to certain features that it doesn't provide and which are necessary for certain asynchronous operations.
That said, you can serve a Mojolicious application on a PSGI server by using <a href="https://mojolicious.org/perldoc/Mojo/Server/PSGI">Mojo::Server::PSGI</a>.
This Mojolicious-core module is automatically used for you when your Mojolicious-based app detects that it has started under a PSGI server (e.g. plackup or Starman).</p>
<p>While translating between a Mojo app and a PSGI server is core functionality, doing the opposite, translating between a PSGI app and a Mojolicious server (or app, as you'll see) is available as a third party module.
<a href="https://metacpan.org/pod/Mojolicious::Plugin::MountPSGI">Mojolicious::Plugin::MountPSGI</a>, as it's name implies, can mount a PSGI application into a Mojolicious-based one.
To do so, it builds a new, empty Mojolicious application that translates all requests to PSGI environments before dispatching to it as with any <a href="https://mojolicious.org/perldoc/Mojolicious/Plugin/Mount">mount</a>-ed application.</p>
devdata/https_mojolicious.io_blog_2018_12_20_testing-dancer_ view on Meta::CPAN
We can the test that JSON reply with <code>json_message_is</code> (like <code>json_is</code> above but for websocket messages).
Finally we close the connection, testing that it closes correctly.</p>
<p>Testing WebSockets, even from a Dancer application, is easy!</p>
<h2>Conclusion</h2>
<p>Although there are some great testing options in the PSGI space, Test::Mojo has lots of benefits for Dancer and PSGI users.
By using <code>Test::Mojo::Role::PSGI</code> or by running against a locally-bound server, Test::Mojo can be a tool in the toolbox of any PSGI developer.</p>
</section>
<small><p>Banner image adapted from <a href="https://www.flickr.com/photos/louisepalanker/6848788290">Ballroom Dance Competition in Aukland, New Zealand</a> by <a href="https://www.flickr.com/photos/louisepalanker/">Louise Palanker</a>,...
</small>
<p class="tags">
<span>Tagged in </span>:
<a href="/blog/tag/advent/">advent</a>,
<a href="/blog/tag/testing/">testing</a>,
<a href="/blog/tag/psgi/">psgi</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_2018_12_20_testing-dancer_ view on Meta::CPAN
<li class="next"><a href="/blog/2018/12/21/a-little-christmas-template-cooking/index.html" rel="next"><strong>Next Article</strong> Day 21: A Little Christmas Template Cooking </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_2018_12_21_a-little-christmas-template-cooking_ view on Meta::CPAN
</div>
<div class="post-thumb">
<!-- theme suggests 1300x500 -->
<img alt="Peanut Butter Kisses cookies" src="/blog/2018/12/21/a-little-christmas-template-cooking/banner.jpg">
</div>
<div class="post-content">
<section id="section-1">
<p>The Advent Calendar has shown you many great ways to use Mojolicious, and since you already have Mojo installed you can use it for things besides web processing. Today's recipe uses The templating rendering engine for somethi...
</section>
<section id="section-2">
<p>First, process some string templates. Here's an example lifted from the <a href="https://mojolicious.org/perldoc/Mojo/Template">Mojo::Template</a>, using the <a href="https://www.effectiveperlprogramming.com/2016/12/strip-lea...
<pre><code>use Mojo::Template;
my $mt = Mojo::Template->new;
say $mt->render(<<~'EOF');
% use Time::Piece;
<div>
% my $now = localtime;
devdata/https_mojolicious.io_blog_2018_12_21_a-little-christmas-template-cooking_ view on Meta::CPAN
{ time => localtime->hms }
)
);
};
find( { no_chdir => 1, wanted => $wanted }, @ARGV );
</code></pre>
<p>That's about it. Your <code>$wanted</code> subroutine can be more sophisticated to put the cooked files in a different directories, skip directories, and many other things. You don't even need to use <a href="https://perldoc.perl.org/File/...
</section>
<small><p>Banner image: <a href="https://www.flickr.com/photos/39908901@N06/11412118604/in/photolist-ios6gA-5LGoKq-PnBoBQ-ibEPHM-7qUncc-SSGFhT-SCYSD9-7pwexw-2doKrZi-b18y32-acMecE-91MNrB-ogyG6P-LX7iMB-ShNXEj-8ZydMc-qdCE4G-4gn2We-qeqCfM-v...
</small>
<p class="tags">
<span>Tagged in </span>:
<a href="/blog/tag/templates/">templates</a>,
<a href="/blog/tag/advent/">advent</a>
</p>
<div class="bio cf">
<div class="gravatar">
<img alt="author image" src="https://secure.gravatar.com/avatar/168427dea0a034607ee7850f3de98ea2.jpg">
</div>
<div class="about">
<h5>brian d foy</h5>
<p><a href="http://www252.pair.com/~comdog/">brian d foy</a> is the author of <a href="https://www.masteringperl.org/">Mastering Perl</a> and <a href="https://www.learningperl6.com/">Learning Perl 6</a>, and the co-author of <...
</div>
</div>
<ul class="post-nav cf">
devdata/https_mojolicious.io_blog_2018_12_21_a-little-christmas-template-cooking_ view on Meta::CPAN
<li class="next"><a href="/blog/2018/12/22/use-carton-for-your-mojolicious-app-deployment/index.html" rel="next"><strong>Next Article</strong> Day 22: Use Carton for your Mojolicious app deployment </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_2018_12_22_use-carton-for-your-mojolicious-app-deployment_ view on Meta::CPAN
</div>
<div class="post-thumb">
<!-- theme suggests 1300x500 -->
<img alt="Brown cardboard boxes on a white floor" src="/blog/2018/12/22/use-carton-for-your-mojolicious-app-deployment/banner.jpg">
</div>
<div class="post-content">
<section id="section-1">
<p>You have a lovely Mojolicious app, itâÂÂs time to deploy it!</p>
<p>But⦠itâÂÂs not working on the production server! What is going on? Oh no, the modules you rely on are not on the same version that on your development server. What can you do?</p>
</section>
<section id="section-2">
<p>Indeed, some modules evolve fast (Hello Mojolicious!) which is not bad but can lead to incompatible changes.</p>
<p>ThereâÂÂs also the bugs which can be resolved or introduced in a version and that you encounter if you have the wrong version.</p>
<h2>Cpanfile to the rescue</h2>
<p><a href="https://metacpan.org/pod/cpanfile">Cpanfile</a> is a format for describing CPAN dependencies for Perl applications.</p>
<p>With <code>cpanfile</code>, we can list the modules we need, but we can also force the minimal versions of the modules, their maximum versions⦠or say "I want this exact version of that module".</p>
devdata/https_mojolicious.io_blog_2018_12_22_use-carton-for-your-mojolicious-app-deployment_ view on Meta::CPAN
<p>but then you will need to add the <code>local/lib/perl5</code> directory to <code>@INC</code> to start your application, since you canâÂÂt use <code>carton exec</code>.
You can do so using the core <a href="https://metacpan.org/pod/lib">lib</a> module, the handy <a href="https://metacpan.org/pod/lib::relative">lib::relative</a> from CPAN, <a href="https://perldoc.pl/perlrun#PERL5LIB">PERL5LIB</a> environment variabl...
<h2>Conclusion</h2>
<p>Carton and cpanfile are a great way to ease Mojolicious apps deployment.
Not only it avoids to list all the dependencies needed by your application in the README or the INSTALL file, but it speeds up deployments and make them more safer, since it sure lowers the risks of bugs due to bad versions of dependencies.</p>
<p><small id="footnote-1">1: or INSTALL, or wherever you put your installation documentation <a href="#back-to-1">â©ï¸Â</a><small></small></small></p>
</section>
<small><p><a href="https://unsplash.com/photos/mTkXSSScrzw">Photo</a> by <a href="https://unsplash.com/@fempreneurstyledstock">Leone Venter</a>, <a href="https://unsplash.com/license">Unsplash license</a> (quite similar to public domain...
</small>
<p class="tags">
<span>Tagged in </span>:
<a href="/blog/tag/advent/">advent</a>,
<a href="/blog/tag/deployment/">deployment</a>,
<a href="/blog/tag/carton/">carton</a>
</p>
devdata/https_mojolicious.io_blog_2018_12_22_use-carton-for-your-mojolicious-app-deployment_ view on Meta::CPAN
<li class="next"><a href="/blog/2018/12/23/mojolicious-and-angular/index.html" rel="next"><strong>Next Article</strong> Day 23: Mojolicious and Angular </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_2018_12_23_mojolicious-and-angular_ view on Meta::CPAN
</div>
<div class="post-thumb">
<!-- theme suggests 1300x500 -->
<img alt="Spider in web" src="/blog/2018/12/23/mojolicious-and-angular/banner.jpg">
</div>
<div class="post-content">
<section id="section-1">
<p><a href="https://angular.io/">Angular</a> is one of the most popular front-end web application frameworks, helping you build modern applications for the web, mobile, or desktop.
<a href="https://mojolicious.org/">Mojolicious</a> is a next generation web framework for the Perl programming language.
Mojolicious and Angular together can certainly build a next generation web application.</p>
<p>At work, we have been using these two to build a very responsive, scalable and fantastic web apps.
Mojolicious as a backend gives a lot of fun to work stuffs like <a href="https://mojolicious.org/perldoc/Minion">Minion</a>, <a href="https://mojolicious.org/perldoc/Mojo/DOM">Mojo::DOM</a>, <a href="https://mojolicious.org/perldoc/Test/Mojo">Test::M...
It has many plugins, including easy implementation of <a href="https://metacpan.org/pod/Mojolicious::Plugin::OpenAPI">OpenAPI</a>, <a href="https://metacpan.org/pod/Mojolicious::Plugin::OAuth2">OAuth</a>, utility modules and of many others on CPAN.</...
<p>One of the reasons you want to have this kind of web development set up is that front-end Angular developers and backend Mojolicious developers can work independently.</p>
<p>Angular is backend agnostic. Node.js Express is often used as backend for Angular, but we love Perl and Mojolicious.</p>
<p>We will see how these two can be married to make a web application today.</p>
</section>
<section id="section-2">
<p>I will be using the default auto-generated apps from both Mojolicious using <a href="https://mojolicious.org/perldoc/Mojolicious/Commands">mojo</a> and Angular using <a href="https://angular.io/cli">Angular CLI</a>.</p>
<h2>Generate Mojolicious Full App</h2>
<p>First I generate mojo full app using <code>mojo</code> CLI's <a href="https://mojolicious.org/perldoc/Mojolicious/Command/generate/app">generate app</a> command.</p>
<pre><code>Sachin@01:07 PM[~/workspace/project/mojo_angular]$ mojo generate app MojoAngularApp
[mkdir] /Users/Sachin/workspace/project/mojo_angular/mojo_angular_app/script
[write] /Users/Sachin/workspace/project/mojo_angular/mojo_angular_app/script/mojo_angular_app
[chmod] /Users/Sachin/workspace/project/mojo_angular/mojo_angular_app/script/mojo_angular_app 744
devdata/https_mojolicious.io_blog_2018_12_23_mojolicious-and-angular_ view on Meta::CPAN
<p>As a sidenote, you may have to allow <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS">Cross Origin Resource Sharing (CORS)</a> if the Angular app throws an error while accessing the mojo API endpoint.
In that case you may want to make use of the <a href="https://mojolicious.org/perldoc/Mojolicious/#before_dispatch"><code>before_dispatch</code></a> app hook:</p>
<pre><code>$self->hook(before_dispatch => sub {
my $c = shift;
$c->res->headers->header('Access-Control-Allow-Origin' => '*');
});
</code></pre>
<p>But please note, in a real-world application <code>*</code> is defeating the security feature.</p>
<h3>Changes in Angular side</h3>
<p>An Angular app's core code files reside in <code>src/app</code> directory.
I will be making changes to following 4 files under <code>src/app</code> directory and explain changes:</p>
<ul>
<li>app.module.ts</li>
<li>app.component.ts</li>
<li>app.component.html</li>
devdata/https_mojolicious.io_blog_2018_12_23_mojolicious-and-angular_ view on Meta::CPAN
<p>This was just a quick example, if you're interested, keep going with these resourses:</p>
<ul>
<li><a href="https://angular.io/docs">Angular guide</a></li>
<li><a href="https://angular.io/tutorial">Angular tutorial</a></li>
<li>For more example code to see more Angular and Mojolicious in action, please have a look at my git repo:
<a href="https://github.com/tryorfry/mojolicious-ng4">https://github.com/tryorfry/mojolicious-ng4</a></li>
</ul>
</section>
<small><p>Banner <a href="https://commons.wikimedia.org/w/index.php?curid=646036">photo</a> by <a href="http://www.videgro.net/">Vincent de Groot</a>, licensed <a href="https://creativecommons.org/licenses/by-sa/4.0/">CC BY SA 4.0</a></...
</small>
<p class="tags">
<span>Tagged in </span>:
<a href="/blog/tag/advent/">advent</a>,
<a href="/blog/tag/angular/">Angular</a>,
<a href="/blog/tag/javascript/">JavaScript</a>
</p>
devdata/https_mojolicious.io_blog_2018_12_23_mojolicious-and-angular_ view on Meta::CPAN
<li class="next"><a href="/blog/2018/12/24/async-await-the-mojo-way/index.html" rel="next"><strong>Next Article</strong> Day 24: Async/Await the Mojo Way </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_2018_12_24_async-await-the-mojo-way_ view on Meta::CPAN
</div>
<div class="post-thumb">
<!-- theme suggests 1300x500 -->
<img alt="Vancouver Symphony Orchestra with Bramwell Tovey" src="/blog/2018/12/24/async-await-the-mojo-way/banner.jpg">
</div>
<div class="post-content">
<section id="section-1">
<h2>The Problems with Thinking in Asynchronous Code</h2>
<p>I've thought a lot about asynchronous code.
Learning it, writing it, teaching it.
Async is hard.</p>
<blockquote>
<p>Learning async programming is about being completely confused and overcomplicating everything and eventually having an 'aha' moment and then being utterly frustrated you don't have a way to teach other people without them needing to ...
<cite><a href="https://shadow.cat/blog/matt-s-trout/">Matt S. Trout</a></cite></p>
</blockquote>
devdata/https_mojolicious.io_blog_2018_12_24_async-await-the-mojo-way_ view on Meta::CPAN
<li>Organize your promises using <a href="https://mojolicious.org/perldoc/Mojo/Promise#all">all</a>, <a href="https://mojolicious.org/perldoc/Mojo/Promise#race">race</a> (only wait for the first resolved promise) or some <a href="https://mojolicious....
</ul>
<p>Hopefully with Mojo::AsyncAwait, writing asynchronous code is finally going to be accessible to those users that haven't yet had Matt's "aha" moment.
And for those of us who have, don't worry, you'll love it too.</p>
<p><em>Another excellent resource is <a href="https://www.youtube.com/watch?v=gB-OmN1egV8">The Evolution of Async JavaScript: From Callbacks, to Promises, to Async/Await</a> by Tyler McGinnis.
It is for JavaScript, but nearly everything applies except they syntax.
Highly recommended.</em></p>
</section>
<small><p><a href="https://commons.wikimedia.org/w/index.php?curid=15521095">Banner image</a> by <a href="https://www.flickr.com/people/56355577@N06">Vancouver 125 - The City of Vancouver</a> <a href="https://www.flickr.com/photos/vanco...
</small>
<p class="tags">
<span>Tagged in </span>:
<a href="/blog/tag/advent/">advent</a>,
<a href="/blog/tag/non-blocking/">non-blocking</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_2018_12_24_async-await-the-mojo-way_ view on Meta::CPAN
<li class="next"><a href="/blog/2018/12/25/special-thanks/index.html" rel="next"><strong>Next Article</strong> Day 25: Special Thanks </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_2018_12_25_special-thanks_ view on Meta::CPAN
</div>
<div class="post-thumb">
<!-- theme suggests 1300x500 -->
<img alt="Baby Jude Carl Berger in Mojo gear" src="/blog/2018/12/25/special-thanks/jude_mojo.jpg">
</div>
<div class="post-content">
<section id="section-1">
<p>This advent calendar, I have special thanks to offer to all the people who helped make it possible.
I'll list them shortly, but before I do, I'd like to introduce you to the newest unofficial member of the Mojolicious Core Team: Jude Carl Berger!
Jude was born on the first day of this calendar, December 1st, at 2:15 am Chicago time.
If you're looking at timestamps, yes, that's about 4 hours after the first blog post went live.</p>
<p>After a one week stay in the NICU for a relatively minor condition, he's now home with myself and his mother, my wonderful wife Carolyn, who I have to thank first.
Not too many partners would put up with someone flitting out to edit a blog post or hit "publish" at the right moment during this time in our lives.
And thanks for Jude.</p>
<p>Armed with that knowledge, you can surely see that even more than usual I couldn't have done this without help!
devdata/https_mojolicious.io_blog_2018_12_25_special-thanks_ view on Meta::CPAN
<p>I want to thank Doug again for creating and maintaining <a href="http://preaction.me/statocles/">Statocles</a>, the static blog engine that powers this site.
I want to thank my employer <a href="https://www.servercentral.com/">ServerCentral</a> who not only are great to work for and support open source, but who gave me lots of time to get settled in with the newest member of my family (and a few cute gift...
I want to thank Sebastian Riedel for writing Mojolicious and for the outfit you see on Jude in the picture above (as far as I know, it is a unique piece), and the entire Mojolicious Core Team and community.</p>
<p>I want to thank Jude for being a reasonably happy newborn and sleeping for longer-than-average stretches at night.</p>
<p>Finally, I extend my warmest thanks to the doctors, nurses and staff of Northwest Community Hospital in Arlington Heights, Illinois and especially the NICU nurses who are beyond amazing.</p>
<p>Merry Christmas, Happy Holidays, Happy New Year, and Happy Perling!</p>
</section>
<small><p>Image: "Jude Carl Berger", original work by Joel Berger, licensed <a href="https://creativecommons.org/licenses/by-nc-nd/4.0/">CC BY-NC-ND 4.0</a>.</p>
</small>
<p class="tags">
<span>Tagged in </span>:
<a href="/blog/tag/advent/">advent</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_2018_12_25_special-thanks_ view on Meta::CPAN
<li class="prev"><a href="/blog/2018/12/24/async-await-the-mojo-way/index.html" rel="prev"><strong>Previous Article</strong> Day 24: Async/Await the Mojo Way</a></li>
</ul>
</div>
</article>
</div>
<div class="four columns end" id="secondary">
<aside id="sidebar">
<div class="widget widget_tag_cloud">