Acme-CPANModulesBundle-Import-MojoliciousAdvent-2017

 view release on metacpan or  search on metacpan

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

      <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/languages/yaml.min.js"></script>
      <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/languages/xml.min.js"></script>
      <script>
        hljs.configure({"languages":["perl","bash","yaml","xml"]});
        hljs.initHighlightingOnLoad();
      </script>

    <script>
      (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
      (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
      m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
      })(window,document,'script','//www.google-analytics.com/analytics.js','ga');
      ga('create', 'UA-110569629-1', 'auto');
      ga('send', 'pageview');
    </script>

</body>

</html>

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

      <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/languages/yaml.min.js"></script>
      <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/languages/xml.min.js"></script>
      <script>
        hljs.configure({"languages":["perl","bash","yaml","xml"]});
        hljs.initHighlightingOnLoad();
      </script>

    <script>
      (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
      (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
      m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
      })(window,document,'script','//www.google-analytics.com/analytics.js','ga');
      ga('create', 'UA-110569629-1', 'auto');
      ga('send', 'pageview');
    </script>

</body>

</html>

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

      <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/languages/yaml.min.js"></script>
      <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/languages/xml.min.js"></script>
      <script>
        hljs.configure({"languages":["perl","bash","yaml","xml"]});
        hljs.initHighlightingOnLoad();
      </script>

    <script>
      (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
      (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
      m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
      })(window,document,'script','//www.google-analytics.com/analytics.js','ga');
      ga('create', 'UA-110569629-1', 'auto');
      ga('send', 'pageview');
    </script>

</body>

</html>

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

      <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/languages/yaml.min.js"></script>
      <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/languages/xml.min.js"></script>
      <script>
        hljs.configure({"languages":["perl","bash","yaml","xml"]});
        hljs.initHighlightingOnLoad();
      </script>

    <script>
      (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
      (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
      m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
      })(window,document,'script','//www.google-analytics.com/analytics.js','ga');
      ga('create', 'UA-110569629-1', 'auto');
      ga('send', 'pageview');
    </script>

</body>

</html>

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

      <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/languages/yaml.min.js"></script>
      <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/languages/xml.min.js"></script>
      <script>
        hljs.configure({"languages":["perl","bash","yaml","xml"]});
        hljs.initHighlightingOnLoad();
      </script>

    <script>
      (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
      (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
      m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
      })(window,document,'script','//www.google-analytics.com/analytics.js','ga');
      ga('create', 'UA-110569629-1', 'auto');
      ga('send', 'pageview');
    </script>

</body>

</html>

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

      <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/languages/yaml.min.js"></script>
      <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/languages/xml.min.js"></script>
      <script>
        hljs.configure({"languages":["perl","bash","yaml","xml"]});
        hljs.initHighlightingOnLoad();
      </script>

    <script>
      (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
      (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
      m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
      })(window,document,'script','//www.google-analytics.com/analytics.js','ga');
      ga('create', 'UA-110569629-1', 'auto');
      ga('send', 'pageview');
    </script>

</body>

</html>

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

      <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/languages/yaml.min.js"></script>
      <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/languages/xml.min.js"></script>
      <script>
        hljs.configure({"languages":["perl","bash","yaml","xml"]});
        hljs.initHighlightingOnLoad();
      </script>

    <script>
      (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
      (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
      m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
      })(window,document,'script','//www.google-analytics.com/analytics.js','ga');
      ga('create', 'UA-110569629-1', 'auto');
      ga('send', 'pageview');
    </script>

</body>

</html>

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

      <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/languages/yaml.min.js"></script>
      <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/languages/xml.min.js"></script>
      <script>
        hljs.configure({"languages":["perl","bash","yaml","xml"]});
        hljs.initHighlightingOnLoad();
      </script>

    <script>
      (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
      (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
      m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
      })(window,document,'script','//www.google-analytics.com/analytics.js','ga');
      ga('create', 'UA-110569629-1', 'auto');
      ga('send', 'pageview');
    </script>

</body>

</html>

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

      <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/languages/yaml.min.js"></script>
      <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/languages/xml.min.js"></script>
      <script>
        hljs.configure({"languages":["perl","bash","yaml","xml"]});
        hljs.initHighlightingOnLoad();
      </script>

    <script>
      (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
      (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
      m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
      })(window,document,'script','//www.google-analytics.com/analytics.js','ga');
      ga('create', 'UA-110569629-1', 'auto');
      ga('send', 'pageview');
    </script>

</body>

</html>

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

      <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/languages/yaml.min.js"></script>
      <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/languages/xml.min.js"></script>
      <script>
        hljs.configure({"languages":["perl","bash","yaml","xml"]});
        hljs.initHighlightingOnLoad();
      </script>

    <script>
      (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
      (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
      m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
      })(window,document,'script','//www.google-analytics.com/analytics.js','ga');
      ga('create', 'UA-110569629-1', 'auto');
      ga('send', 'pageview');
    </script>

</body>

</html>

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

      &#39;<span class="hljs-string">Content-Type</span>&#39; =&gt; &#39;<span class="hljs-string">image/jpeg</span>&#39;,
      content =&gt; <span class="hljs-type">$file</span>-&gt;<span class="hljs-type">slurp</span>,
    }
  ]
);


</code></pre>

<p>Though you have to form the parts a little more manually (no, generators don&#39;t call other generators), this is still a much simpler use than building the message manually.
Most notably, the length calculations and all of the boundary handling is done transparently.</p>

<h2>Adding New Content Generators</h2>

<p>So if you are reading this and thinking that Content Generators look great but the type you need isn&#39;t available, take heart!
Adding content generators is easy too!
As seen in the <a href="http://mojolicious.org/perldoc/Mojo/UserAgent/Transactor#add_generator">documentation</a> adding a generator is as simple as adding a callback that will build the request.</p>

<p>To motivate this discussion, I&#39;ll introduce another module.
At work, I had to use <a href="http://xmlrpc.scripting.com/spec.html">XML-RPC</a> to interact with a remote service.
XML-RPC defines an XML schema for asking the service to call a method, just as you would locally, by method name and with some arguments.

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

      <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/languages/yaml.min.js"></script>
      <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/languages/xml.min.js"></script>
      <script>
        hljs.configure({"languages":["perl","bash","yaml","xml"]});
        hljs.initHighlightingOnLoad();
      </script>

    <script>
      (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
      (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
      m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
      })(window,document,'script','//www.google-analytics.com/analytics.js','ga');
      ga('create', 'UA-110569629-1', 'auto');
      ga('send', 'pageview');
    </script>

</body>

</html>

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


            <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>

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

Therefore the primary feature of Mojo::Base classes is speed!</p>

<p>The object system is spartan even when compared to Moo.
You get a hash-based object with declarative read/write lazy accessors and a constructor.
When considering Moose vs Moo, you trade lesser-used features for a noticable performance gain.
Likewise when you consider Mojo::Base vs Moo, you strip down futher, this time to the bare essentials, but again get a performance gain.</p>

<p>Now if you need more functionality, you are more than welcome to use Moo or other object systems in your applications (though the Mojo internals will of course continue to use Mojo::Base).
That said, much of the real world usage of Moo is very similar to Mojo::Base: lazy accessor generation; this might be all you need.</p>

<p>To declare a new class with Mojo::Base, one with no other parent classes, you use the <code>-base</code> flag.</p>

<pre><code>package My::Class;
use Mojo::Base -base;
</code></pre>

<p>This adds the <code>has</code> keyword to your package which, as we will see soon, declares the class&#39;s attributes.
This will cause your new class to inherit from Mojo::Base, meaning it will get the methods from Mojo::Base as well, which you will also see.
Of course, the module also acquires the pragmas and functionality listed above and may add <code>-signatures</code> if desired.</p>

<p>If you want your class to derive from some other parent class, you can pass that name rather than <code>-base</code>.</p>

<pre><code>package My::Class::Subclass;
use Mojo::Base &#39;My::Class&#39;;
</code></pre>

<p>You saw this usage quite a bit in the Full app example on <a href="/blog/2017/12/06/day-6-adding-your-own-commands">Day 6</a>.
Mojo::Base only supports single-inheritance because we don&#39;t want to encourage bad practices.
If you know why you might want to use multipe-inheritance, you probably know how to get around this limitation as well.</p>

<h3>Attributes and Constructor</h3>

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

      <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/languages/yaml.min.js"></script>
      <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/languages/xml.min.js"></script>
      <script>
        hljs.configure({"languages":["perl","bash","yaml","xml"]});
        hljs.initHighlightingOnLoad();
      </script>

    <script>
      (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
      (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
      m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
      })(window,document,'script','//www.google-analytics.com/analytics.js','ga');
      ga('create', 'UA-110569629-1', 'auto');
      ga('send', 'pageview');
    </script>

</body>

</html>

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

              </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>

<p>Let&#39;s look at a (contrived) example.
Say we want to make a role that finds all the tags matching elements in a <a href="http://mojolicious.org/perldoc/Mojo/DOM">Mojo::DOM</a> based on a selector stored in an attribute.</p>

<pre><code>package Mojo::DOM::Role::FindCustom;
use Mojo::Base -role;

requires &#39;find&#39;;

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

      <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/languages/yaml.min.js"></script>
      <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/languages/xml.min.js"></script>
      <script>
        hljs.configure({"languages":["perl","bash","yaml","xml"]});
        hljs.initHighlightingOnLoad();
      </script>

    <script>
      (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
      (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
      m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
      })(window,document,'script','//www.google-analytics.com/analytics.js','ga');
      ga('create', 'UA-110569629-1', 'auto');
      ga('send', 'pageview');
    </script>

</body>

</html>

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

      <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/languages/yaml.min.js"></script>
      <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/languages/xml.min.js"></script>
      <script>
        hljs.configure({"languages":["perl","bash","yaml","xml"]});
        hljs.initHighlightingOnLoad();
      </script>

    <script>
      (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
      (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
      m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
      })(window,document,'script','//www.google-analytics.com/analytics.js','ga');
      ga('create', 'UA-110569629-1', 'auto');
      ga('send', 'pageview');
    </script>

</body>

</html>

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

      <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/languages/yaml.min.js"></script>
      <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/languages/xml.min.js"></script>
      <script>
        hljs.configure({"languages":["perl","bash","yaml","xml"]});
        hljs.initHighlightingOnLoad();
      </script>

    <script>
      (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
      (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
      m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
      })(window,document,'script','//www.google-analytics.com/analytics.js','ga');
      ga('create', 'UA-110569629-1', 'auto');
      ga('send', 'pageview');
    </script>

</body>

</html>

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

      <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/languages/yaml.min.js"></script>
      <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/languages/xml.min.js"></script>
      <script>
        hljs.configure({"languages":["perl","bash","yaml","xml"]});
        hljs.initHighlightingOnLoad();
      </script>

    <script>
      (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
      (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
      m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
      })(window,document,'script','//www.google-analytics.com/analytics.js','ga');
      ga('create', 'UA-110569629-1', 'auto');
      ga('send', 'pageview');
    </script>

</body>

</html>

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

      <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/languages/yaml.min.js"></script>
      <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/languages/xml.min.js"></script>
      <script>
        hljs.configure({"languages":["perl","bash","yaml","xml"]});
        hljs.initHighlightingOnLoad();
      </script>

    <script>
      (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
      (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
      m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
      })(window,document,'script','//www.google-analytics.com/analytics.js','ga');
      ga('create', 'UA-110569629-1', 'auto');
      ga('send', 'pageview');
    </script>

</body>

</html>

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

<p>This class define the ways that the application can alter the data in the database.
Rather than the familiar DBI methods like <code>selectrow_arrayref</code>, Mojo-Flavored DBI make a query and then ask for the result shape they want returned.
The user can ask for a row as a hash or an array.
They can also ask for and array of all thr rows, again as a hash or an array.
Sometimes there are other data you want rather than the actual results, like the <code>last_insert_id</code> or the number of <code>rows</code> affected.</p>

<p>Most of the methods are simple enough to employ the SQL::Abstract forms: add, update, remove, even listing the users.
However for getting a user we want to make a more complex <code>query</code> by hand.
It looks up the user row by name, and aggregates the items that user is wishing for as JSON.</p>

<p>Before fetching the results we tell Mojo::SQLite that we would like to expand the JSON back into Perl data transparently.
This <a href="https://metacpan.org/pod/Mojo::SQLite::Results#expand"><code>expand</code></a> method differs slightly from the other flavors since SQLite doesn&#39;t have metadata to give Mojo::SQLite hints about which column to expand.
Once setup, when we call <code>hash</code> we get a nice Perl structure as a result.</p>

<h2>The Application Class</h2>

<p>The application class might look quite different but its behavior is very similar to yesterday.
Don&#39;t fret over every line, I will only cover the important things for our purposes.</p>

<pre><code class="hljs"><span class="hljs-keyword">package</span> Wishlist;
<span class="hljs-keyword">use</span> <span class="hljs-function">Mojo::Base</span> &#39;<span class="hljs-string">Mojolicious</span>&#39;;

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

      <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/languages/yaml.min.js"></script>
      <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/languages/xml.min.js"></script>
      <script>
        hljs.configure({"languages":["perl","bash","yaml","xml"]});
        hljs.initHighlightingOnLoad();
      </script>

    <script>
      (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
      (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
      m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
      })(window,document,'script','//www.google-analytics.com/analytics.js','ga');
      ga('create', 'UA-110569629-1', 'auto');
      ga('send', 'pageview');
    </script>

</body>

</html>

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

As we saw in the Cookbook entry, one other consideration for installable applications is its <code>home</code>.</p>

<p>Apart from setting the above paths, which we no longer need it to do, the other main job of the <code>home</code> is to locate data from the application user rather than the application&#39;s own files.
Here it is still amply useful!</p>

<p>The first and most import example of this is loading configuration via say <a href="http://mojolicious.org/perldoc/Mojolicious/Plugin/Config#file">Mojolicious::Plugin::Config</a>.
The user will be provide configuration and almost certainly not from the installed location of the application, unlike its bundled support files.</p>

<p>This also provides another conundrum, if the home is used to load the configuration, then it cannot be set by via the configuration.
No, the home really needs to be set by the user via the <code>MOJO_HOME</code> environment variable <a href="http://mojolicious.org/perldoc/Mojo/Home#detect">as documented</a>.
If this isn&#39;t desirable, some other environment variable could be used by providing your own in your class, overriding the one from the parent.</p>

<pre><code>has home =&gt; sub {
  Mojo::Home-&gt;new($ENV{WISHLIST_HOME});
};
</code></pre>

<p>Though <code>MOJO_HOME</code> is likely a fine place to start.</p>

<p>From there, you might (in some cases) want the users to be able to provide their own static files and/or templates.
Say if your application could be themed.

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

      <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/languages/yaml.min.js"></script>
      <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/languages/xml.min.js"></script>
      <script>
        hljs.configure({"languages":["perl","bash","yaml","xml"]});
        hljs.initHighlightingOnLoad();
      </script>

    <script>
      (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
      (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
      m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
      })(window,document,'script','//www.google-analytics.com/analytics.js','ga');
      ga('create', 'UA-110569629-1', 'auto');
      ga('send', 'pageview');
    </script>

</body>

</html>

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

      <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/languages/yaml.min.js"></script>
      <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/languages/xml.min.js"></script>
      <script>
        hljs.configure({"languages":["perl","bash","yaml","xml"]});
        hljs.initHighlightingOnLoad();
      </script>

    <script>
      (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
      (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
      m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
      })(window,document,'script','//www.google-analytics.com/analytics.js','ga');
      ga('create', 'UA-110569629-1', 'auto');
      ga('send', 'pageview');
    </script>

</body>

</html>

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

      <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/languages/yaml.min.js"></script>
      <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/languages/xml.min.js"></script>
      <script>
        hljs.configure({"languages":["perl","bash","yaml","xml"]});
        hljs.initHighlightingOnLoad();
      </script>

    <script>
      (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
      (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
      m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
      })(window,document,'script','//www.google-analytics.com/analytics.js','ga');
      ga('create', 'UA-110569629-1', 'auto');
      ga('send', 'pageview');
    </script>

</body>

</html>

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

      <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/languages/yaml.min.js"></script>
      <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/languages/xml.min.js"></script>
      <script>
        hljs.configure({"languages":["perl","bash","yaml","xml"]});
        hljs.initHighlightingOnLoad();
      </script>

    <script>
      (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
      (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
      m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
      })(window,document,'script','//www.google-analytics.com/analytics.js','ga');
      ga('create', 'UA-110569629-1', 'auto');
      ga('send', 'pageview');
    </script>

</body>

</html>

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

      <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/languages/yaml.min.js"></script>
      <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/languages/xml.min.js"></script>
      <script>
        hljs.configure({"languages":["perl","bash","yaml","xml"]});
        hljs.initHighlightingOnLoad();
      </script>

    <script>
      (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
      (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
      m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
      })(window,document,'script','//www.google-analytics.com/analytics.js','ga');
      ga('create', 'UA-110569629-1', 'auto');
      ga('send', 'pageview');
    </script>

</body>

</html>

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

      <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/languages/yaml.min.js"></script>
      <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/languages/xml.min.js"></script>
      <script>
        hljs.configure({"languages":["perl","bash","yaml","xml"]});
        hljs.initHighlightingOnLoad();
      </script>

    <script>
      (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
      (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
      m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
      })(window,document,'script','//www.google-analytics.com/analytics.js','ga');
      ga('create', 'UA-110569629-1', 'auto');
      ga('send', 'pageview');
    </script>

</body>

</html>



( run in 0.749 second using v1.01-cache-2.11-cpan-4d50c553e7e )