Acme-CPANModulesBundle-Import-MojoliciousAdvent-2017

 view release on metacpan or  search on metacpan

LICENSE  view on Meta::CPAN

MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.

  10. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.

                     END OF TERMS AND CONDITIONS

        Appendix: How to Apply These Terms to Your New Programs

  If you develop a new program, and you want it to be of the greatest
possible use to humanity, the best way to achieve this is to make it

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


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

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

__DATA__

@@ hello.html.ep
hello &lt;%= $name %&gt;
</code></pre>

<p>In the latter you see the first example of calling render with only one argument.
When it is called with an odd number of arguments, the first one is the identifier (name) of a template.
This is the same as stashing <code>template =&gt; &#39;hello&#39;</code>, which you could even do in the route defaults.</p>

<h2>Special/Reserved Stash Keys</h2>

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

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

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

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

app-&gt;start;

__DATA__

@@ staff.html.ep
&lt;p&gt;This is &lt;%= ucfirst $name %&gt;.&lt;/p&gt;

@@ home.html.ep
&lt;p&gt;Welcome to The North Pole!&lt;/p&gt;

&lt;p&gt;
  Say hi to &lt;%= link_to &#39;Santa&#39; =&gt; staff =&gt; {name =&gt; &#39;santa&#39;} %&gt;
  and &lt;%= link_to &#39;Rudolph&#39; =&gt; staff =&gt; {name =&gt; &#39;rudolph&#39;} %&gt;.

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

What he really needed to do was move all of the staff pages to keep the urls consistent.</p>

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

get &#39;/toy/:toy_name&#39; =&gt; {template =&gt; &#39;toy&#39;} =&gt; &#39;toy&#39;;
get &#39;/meet/:name&#39; =&gt; {template =&gt; &#39;staff&#39;} =&gt; &#39;staff&#39;;
get &#39;/&#39; =&gt; {template =&gt; &#39;home&#39;} =&gt; &#39;home&#39;;

app-&gt;start;

__DATA__

@@ toy.html.ep
&lt;p&gt;Look at this amazing &lt;%= $toy_name %&gt;.&lt;/p&gt;

@@ staff.html.ep
&lt;p&gt;This is &lt;%= ucfirst $name %&gt;.&lt;/p&gt;

@@ home.html.ep
&lt;p&gt;Welcome to The North Pole!&lt;/p&gt;

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

      units =&gt; $config-&gt;{units} || &#39;metric&#39;,
    );
  });

  my $r = $app-&gt;routes;
  $r-&gt;get(&#39;/weather&#39;)-&gt;to(&#39;Weather#recall&#39;);
}

1;

__DATA__

@@ migrations

-- 1 up

CREATE TABLE weather (
  id INTEGER PRIMARY KEY,
  search TEXT NOT NULL,
  time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
  temperature REAL NOT NULL

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

</code></pre>

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

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

<pre><code class="hljs"><span class="hljs-comment"># test-api.pl</span><span class="hljs-comment">
</span><span class="hljs-keyword">use</span> <span class="hljs-function">Mojolicious::Lite</span>;
any &#39;<span class="hljs-string">/*path</span>&#39; =&gt; <span class="hljs-keyword">sub </span>{
    <span class="hljs-keyword">my</span> ( <span class="hljs-type">$c</span> ) = <span class="hljs-type">@_</span>;
    <span class="hljs-keyword">return</span> <span class="hljs-type">$c</span>-&gt;<span class="hljs-type">render</span>(
        template =&gt; <span class="hljs-type">$c</span>-&gt;<span class="hljs-type">stash</span>( &#39;<span class="hljs-string">path</span>&#39; ),
        <span class="hljs-function">format</span> =&gt; &#39;<span class="hljs-string">json</span>&#39;,
    );
};
app-&gt;start;
<span class="hljs-keyword">__DATA__</span>
@@ servers.json.ep
[
    { &quot;ip&quot;: &quot;10.0.0.1&quot;, &quot;os&quot;: &quot;Debian 9&quot; },
    { &quot;ip&quot;: &quot;10.0.0.2&quot;, &quot;os&quot;: &quot;Debian 8&quot; }
]
</code></pre>

<p>Again, we can use the <code>get</code> command to test that we get the right data:</p>

<pre><code>$ perl test-api.pl get /servers

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

<pre><code class="hljs"><span class="hljs-comment"># test-api.pl</span><span class="hljs-comment">
</span><span class="hljs-keyword">use</span> <span class="hljs-function">Mojolicious::Lite</span>;
any &#39;<span class="hljs-string">/*path</span>&#39; =&gt; <span class="hljs-keyword">sub </span>{
    <span class="hljs-keyword">my</span> ( <span class="hljs-type">$c</span> ) = <span class="hljs-type">@_</span>;
    <span class="hljs-keyword">return</span> <span class="hljs-type">$c</span>-&gt;<span class="hljs-type">render</span>(
        template =&gt; <span class="hljs-type">$c</span>-&gt;<span class="hljs-type">stash</span>( &#39;<span class="hljs-string">path</span>&#39; ),
        <span class="hljs-function">format</span> =&gt; &#39;<span class="hljs-string">json</span>&#39;,
    );
};
app-&gt;start;
<span class="hljs-keyword">__DATA__</span>
@@ servers.json.ep
[
    &lt;%== include &#39;servers/1&#39; %&gt;,
    &lt;%== include &#39;servers/2&#39; %&gt;
]
@@ servers/1.json.ep
{ &quot;ip&quot;: &quot;10.0.0.1&quot;, &quot;os&quot;: &quot;Debian 9&quot; }
@@ servers/2.json.ep
{ &quot;ip&quot;: &quot;10.0.0.2&quot;, &quot;os&quot;: &quot;Debian 8&quot; }
</code></pre>

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

<pre><code class="hljs"><span class="hljs-comment"># test-api.pl</span><span class="hljs-comment">
</span><span class="hljs-keyword">use</span> <span class="hljs-function">Mojolicious::Lite</span>;
any &#39;<span class="hljs-string">/*path</span>&#39; =&gt; <span class="hljs-keyword">sub </span>{
    <span class="hljs-keyword">my</span> ( <span class="hljs-type">$c</span> ) = <span class="hljs-type">@_</span>;
    <span class="hljs-keyword">return</span> <span class="hljs-type">$c</span>-&gt;<span class="hljs-type">render</span>(
        template =&gt; <span class="hljs-function">join</span>( &#39;<span class="hljs-string">/</span>&#39;, <span class="hljs-function">uc</span> <span class="hljs-type">$c</span>-&gt;<span class="hljs-type">req</span>-&gt;<span class="hljs-type">m...
        <span class="hljs-function">format</span> =&gt; &#39;<span class="hljs-string">json</span>&#39;,
    );
};
app-&gt;start;
<span class="hljs-keyword">__DATA__</span>
@@ GET/servers.json.ep
[
    &lt;%== include &#39;GET/servers/1&#39; %&gt;,
    &lt;%== include &#39;GET/servers/2&#39; %&gt;
]
@@ GET/servers/1.json.ep
{ &quot;ip&quot;: &quot;10.0.0.1&quot;, &quot;os&quot;: &quot;Debian 9&quot; }
@@ GET/servers/2.json.ep
{ &quot;ip&quot;: &quot;10.0.0.2&quot;, &quot;os&quot;: &quot;Debian 8&quot; }
@@ POST/servers.json.ep

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

</span><span class="hljs-keyword">use</span> <span class="hljs-function">Mojolicious::Lite</span>;
any &#39;<span class="hljs-string">/*path</span>&#39; =&gt; <span class="hljs-keyword">sub </span>{
    <span class="hljs-keyword">my</span> ( <span class="hljs-type">$c</span> ) = <span class="hljs-type">@_</span>;
    <span class="hljs-keyword">return</span> <span class="hljs-type">$c</span>-&gt;<span class="hljs-type">render</span>(
        template =&gt; <span class="hljs-function">join</span>( &#39;<span class="hljs-string">/</span>&#39;, <span class="hljs-function">uc</span> <span class="hljs-type">$c</span>-&gt;<span class="hljs-type">req</span>-&gt;<span class="hljs-type">m...
        variant =&gt; <span class="hljs-type">$c</span>-&gt;<span class="hljs-type">app</span>-&gt;<span class="hljs-type">mode</span>,
        <span class="hljs-function">format</span> =&gt; &#39;<span class="hljs-string">json</span>&#39;,
    );
};
app-&gt;start;
<span class="hljs-keyword">__DATA__</span>
@@ GET/servers.json.ep
[
    &lt;%== include &#39;GET/servers/1&#39; %&gt;,
    &lt;%== include &#39;GET/servers/2&#39; %&gt;
]
@@ GET/servers/1.json.ep
{ &quot;ip&quot;: &quot;10.0.0.1&quot;, &quot;os&quot;: &quot;Debian 9&quot; }
@@ GET/servers/2.json.ep
{ &quot;ip&quot;: &quot;10.0.0.2&quot;, &quot;os&quot;: &quot;Debian 8&quot; }
@@ POST/servers.json.ep

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

    <span class="hljs-keyword">my</span> ( <span class="hljs-type">$c</span> ) = <span class="hljs-type">@_</span>;
    <span class="hljs-comment"># Allow preflight OPTIONS request for XmlHttpRequest to succeed</span><span class="hljs-comment">
</span>    <span class="hljs-keyword">return</span> <span class="hljs-type">$c</span>-&gt;<span class="hljs-type">rendered</span>( <span class="hljs-number">204</span> ) <span class="hljs-keyword">if</span> <span class="hljs-type">$c</span>-&gt;<span...
    <span class="hljs-keyword">return</span> <span class="hljs-type">$c</span>-&gt;<span class="hljs-type">render</span>(
        template =&gt; <span class="hljs-function">join</span>( &#39;<span class="hljs-string">/</span>&#39;, <span class="hljs-function">uc</span> <span class="hljs-type">$c</span>-&gt;<span class="hljs-type">req</span>-&gt;<span class="hljs-type">m...
        variant =&gt; <span class="hljs-type">$c</span>-&gt;<span class="hljs-type">app</span>-&gt;<span class="hljs-type">mode</span>,
        <span class="hljs-function">format</span> =&gt; &#39;<span class="hljs-string">json</span>&#39;,
    );
};
app-&gt;start;
<span class="hljs-keyword">__DATA__</span>
@@ GET/servers.json.ep
[
    &lt;%== include &#39;GET/servers/1&#39; %&gt;,
    &lt;%== include &#39;GET/servers/2&#39; %&gt;
]
@@ GET/servers/1.json.ep
{ &quot;ip&quot;: &quot;10.0.0.1&quot;, &quot;os&quot;: &quot;Debian 9&quot; }
@@ GET/servers/2.json.ep
{ &quot;ip&quot;: &quot;10.0.0.2&quot;, &quot;os&quot;: &quot;Debian 8&quot; }
@@ POST/servers.json.ep

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

<span class="hljs-type">$t</span>-&gt;<span class="hljs-type">get_ok</span>(&#39;<span class="hljs-string">/rudolph</span>&#39;, {<span class="hljs-function">Accept</span> =&gt; &#39;<span class="hljs-string">text/xml</span>&#39;})
  -&gt;status_is(<span class="hljs-number">200</span>)
  -&gt;text_is(&#39;<span class="hljs-string">Reindeer Name</span>&#39; =&gt; &#39;<span class="hljs-string">Rudolph</span>&#39;);

<span class="hljs-type">$t</span>-&gt;<span class="hljs-type">get_ok</span>(&#39;<span class="hljs-string">/rudolph?format=txt</span>&#39;)
  -&gt;status_is(<span class="hljs-number">200</span>)
  -&gt;content_like(qr/<span class="hljs-string">^</span>Rudolph:/);

done_testing;

<span class="hljs-keyword">__DATA__</span>

@@ reindeer.xml.ep
&lt;?xml version=&quot;1.0&quot;?&gt;
&lt;Reindeer&gt;
  &lt;Name&gt;&lt;%= $reindeer-&gt;{name} =%&gt;&lt;/Name&gt;
  &lt;Description&gt;&lt;%= $reindeer-&gt;{description} =%&gt;&lt;/Description&gt;
&lt;/Reindeer&gt;

</code></pre>

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

--foo_bar_baz
Content-Type: application/json; charset=UTF-8

{
  &quot;name&quot;: &quot;myObject&quot;
}

--foo_bar_baz
Content-Type: image/jpeg

[JPEG_DATA]
--foo_bar_baz--
</code></pre>

<p>While this was possible using the lower level tools, we decided that adding a generator for it would make using that API much easier for them.
Thus the <code>multipart</code> generator was added to the mix.
Using it, one can make a compliant request by writing something like</p>

<pre><code class="hljs"><span class="hljs-keyword">use</span> <span class="hljs-function">Mojo::Base</span> -strict;
<span class="hljs-keyword">use</span> <span class="hljs-function">Mojo::UserAgent</span>;
<span class="hljs-keyword">use</span> <span class="hljs-function">Mojo::JSON</span> &#39;<span class="hljs-string">encode_json</span>&#39;;

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

called &quot;blog&quot; with fields for an ID, a title, a date, some markdown, and
some HTML.</p>

<pre><code class="hljs"><span class="hljs-comment"># myapp.pl</span><span class="hljs-comment">
</span><span class="hljs-keyword">use</span> <span class="hljs-function">Mojolicious::Lite</span>;
<span class="hljs-keyword">use</span> <span class="hljs-function">Mojo::Pg</span>;

<span class="hljs-keyword">my</span> <span class="hljs-type">$pg</span> = <span class="hljs-function">Mojo::Pg</span>-&gt;new( &#39;<span class="hljs-string">postgres://localhost/blog</span>&#39; );
<span class="hljs-type">$pg</span>-&gt;<span class="hljs-type">migrations</span>-&gt;<span class="hljs-type">from_data</span>-&gt;<span class="hljs-type">migrate</span>;

<span class="hljs-keyword">__DATA__</span>
@@ migrations
-- 1 up
CREATE TABLE blog (
    id SERIAL PRIMARY KEY,
    title VARCHAR NOT NULL,
    created TIMESTAMP NOT NULL DEFAULT NOW(),
    markdown TEXT NOT NULL,
    html TEXT NOT NULL
);
-- 1 down

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

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

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

__DATA__

@@ pgm_header
P2
00000000 00000000
255
</code></pre>

<p>This script will create 0_START.pgm, add a PGM header to it (which will need
fixing later) and writes the bytes it receives from STDIN into that file in
the correct format.</p>



( run in 1.035 second using v1.01-cache-2.11-cpan-cdf2f3d4e48 )