view release on metacpan or search on metacpan
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
free software which everyone can redistribute and change under these
terms.
To do so, attach the following notices to the program. It is safest to
attach them to the start of each source file to most effectively convey
the exclusion of warranty; and each file should have at least the
"copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) 19yy <name of author>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 1, or (at your option)
any later version.
devdata/https_mojolicious.io_blog_2017_12_02_day-2-the-stash view on Meta::CPAN
</div>
<div class="post-content">
<section id="section-1">
<p>In Mojolicious, when processing a request and preparing a response one of the most important concepts is "the stash".
Since it is a non-blocking framework, your code can't use global variables to store any state during processing.
If you did and some other code were to run, it could very easily get cross-talk between requests.</p>
<p>The stash is the place you can store information while you process it.
It is just a simple hash reference that is attached to the controller object that is processing the request.
It lives and dies with that one transaction.</p>
<p>While you can and should use it as a scratchpad, it really is much more.
The stash controls almost every aspect of the response that you generate.
Let's look a little closer to see how it works</p>
</section>
<section id="section-2">
<h2>Using the Stash for Rendering Text</h2>
devdata/https_mojolicious.io_blog_2017_12_04_day-4-dont-fear-the-full-app view on Meta::CPAN
my $protected = $r->under('/protected' => sub {
# check authentication
});
# /protected/safe
$protected->get('/safe' => 'safe');
$r->get('/another_unsafe' => ...);
</code></pre>
<p>Since Lite app keywords don't have a way to attach to another route, they basically always add them to the "current global route".
That's where the confusion comes in.</p>
<p>Speaking of which, I'm going to let you in even deeper on my secret.
I like the chained type of routing so much more than using <code>group</code> that I actually use it in my Lite apps.
Sure I still use <code>app</code> and <code>plugin</code>, but one of the first things I do is <code>my $r = app->routes</code>.
Then, I use that instead of the routing keywords in all but the simplest of cases.</p>
<h2>Conclusion</h2>
<p>That's it, with the exception of using <code>group</code> for nested routing, it is just direct translation.
devdata/https_mojolicious.io_blog_2017_12_06_day-6-adding-your-own-commands view on Meta::CPAN
<p>It defines the moniker, which in turn defines the configuration file name.
It then loads configuration; this is necessary since we need your appid for OpenWeatherMap.
It tells the app that we are going to define some application-specific commands under <a href="https://github.com/jberger/MyWeatherApp/tree/master/lib/MyWeatherApp/Command">MyWeatherApp::Command</a>.</p>
<p>Then there's something I haven't shown you before, a helper.
Helpers are like methods but they are available to the app and the controllers and even to templates.
They always receive a controller, even if they are called on the app.
Helpers are very useful for tying parts of your application together.
In this case we use one to build and return an instance of our model class.
It attaches that required data that we noted earlier.</p>
<p>Moving on, the application now defines a route.
As we'll see later it is attached to the <a href="https://github.com/jberger/MyWeatherApp/blob/master/lib/MyWeatherApp/Controller/Weather.pm">Weather controller class</a> and more specifically its <code>recall</code> action method.
This is much like the action callbacks we saw before, but by keeping it in a separate class the application class is easier to read.</p>
<p>Finally we define the database schema.
This is a format common to the Mojo-flavored database modules, like <a href="http://mojolicious.org/perldoc/Mojo/Pg">Mojo::Pg</a>, <a href="https://metacpan.org/pod/Mojo::mysql">Mojo::mysql</a>, and <a href="https://metacpan.org/pod/Mojo::SQLite">Moj...
Each section is defined with a version number and the word <code>up</code> or <code>down</code>.
When migrating versions, it will apply each change set from the current version (beginning at 0) until the version you request.
If you don't request a version it gets the highest version.</p>
<p>Now that all that is done, we can try it out!</p>
devdata/https_mojolicious.io_blog_2017_12_11_day-11-useragent-content-generators view on Meta::CPAN
<p>At the time of this writing, Mojo::UserAgent comes with three <a href="http://mojolicious.org/perldoc/Mojo/UserAgent/Transactor#tx">built-in Content Generators</a>, including the <code>json</code> one as we've already seen.</p>
<p>The <code>form</code> generator creates urlencoded or multipart requests depending on the data passed.
The form generator is, unsurprisingly, useful for submittng forms, often used to login to sites, search for content or upload files.
It is even smart enought to use query parameters for <code>GET</code> and <code>HEAD</code> requests (which cannot take a body), while using body parameters for others.</p>
<p>Finally, the recently-added <code>multipart</code> generator is for building your own generic multipart requests.
Though not common, some APIs allow or even require users to upload multiple files in the same request.</p>
<p>This was the case presented to us by a user not too long ago.
They were interacting with the <a href="https://developers.google.com/drive/v3/web/multipart-upload">Google Drive API</a> that wanted them to upload a file as part of a multipart message with a JSON document attached containing metadata.
The overall request was to be marked at <a href="https://tools.ietf.org/html/rfc2387"><code>multipart/related</code></a> while each part should have its own <code>Content-Type</code>.
Google's documented example is</p>
<pre><code>POST https://www.googleapis.com/upload/drive/v3/files?uploadType=multipart HTTP/1.1
Authorization: Bearer [YOUR_AUTH_TOKEN]
Content-Type: multipart/related; boundary=foo_bar_baz
Content-Length: [NUMBER_OF_BYTES_IN_ENTIRE_REQUEST_BODY]
--foo_bar_baz
Content-Type: application/json; charset=UTF-8
devdata/https_mojolicious.io_blog_2017_12_16_day-16-the-secret-life-of-sessions view on Meta::CPAN
<img alt="Pile of Scrabble tiles" src="/blog/2017/12/16/day-16-the-secret-life-of-sessions/scrabble.jpg">
</div>
<div class="post-content">
<section id="section-1">
<p>As you all know, HTTP is a stateless protocol.
In Mojolicious applications the session is used to maintain state between requests.
These sessions are managed by the application's <a href="http://mojolicious.org/perldoc/Mojolicious/#sessions">session manager</a>.</p>
<p>During each request, the <a href="http://mojolicious.org/perldoc/Mojolicious/Controller#session">session</a> is just another hash reference attached to the controller, in some ways like the <a href="/blog/2017/12/02/day-2-the-stash">stash</a>, exc...
Mojolicious does this by encoding the structure, first as JSON then Base64.
It then signs the resulting string using HMAC-SHA1 and the application's <a href="http://mojolicious.org/perldoc/Mojolicious#secrets">secret</a> to prevent tampering and stores it as a cookie on the response to the client.</p>
<p>On subsequent requests, the client sends the cookie along with the request (as cookies do).
Mojolicious then checks if the document and signature validate against the secret, if so the cookie is decoded and made available again via the session method.</p>
<p>Two important things to note.
First, though the data is safe from tampering, it isn't encrypted; a savvy user can decode the cookie and see the stored data, so don't put anything in it that shouldn't be seen.
Second, this is only useful if the secret is strong and safe.
If not, the client could forge a cookie that appeared to come from your application, possibly with catastrophic results!
devdata/https_mojolicious.io_blog_2017_12_18_day-18-the-wishlist-model view on Meta::CPAN
<span class="hljs-type">$file</span> = <span class="hljs-function">Mojo::File</span>->new(<span class="hljs-type">$file</span>);
<span class="hljs-keyword">unless</span> (<span class="hljs-type">$file</span>-><span class="hljs-type">is_abs</span>) {
<span class="hljs-type">$file</span> = <span class="hljs-type">$app</span>-><span class="hljs-type">home</span>-><span class="hljs-type">child</span>("<span class="hljs-type">$file</span>");
}
}
<span class="hljs-keyword">my</span> <span class="hljs-type">$sqlite</span> = <span class="hljs-function">Mojo::SQLite</span>->new
->from_filename("<span class="hljs-type">$file</span>")
->auto_migrate(<span class="hljs-number">1</span>);
<span class="hljs-comment"># attach migrations file</span><span class="hljs-comment">
</span> <span class="hljs-type">$sqlite</span>-><span class="hljs-type">migrations</span>-><span class="hljs-type">from_file</span>(
<span class="hljs-type">$app</span>-><span class="hljs-type">home</span>-><span class="hljs-type">child</span>('<span class="hljs-string">wishlist.sql</span>')
)->name('<span class="hljs-string">wishlist</span>');
<span class="hljs-keyword">return</span> <span class="hljs-type">$sqlite</span>;
};
<span class="hljs-keyword">sub </span><span class="hljs-function">startup</span> {
<span class="hljs-keyword">my</span> <span class="hljs-type">$app</span> = <span class="hljs-function">shift</span>;
devdata/https_mojolicious.io_blog_2017_12_18_day-18-the-wishlist-model view on Meta::CPAN
</code></pre>
<p><small>lib/Wishlist.pm</small></p>
<p>There is an application attribute which holds the Mojo::SQLite instance.
Its initializer pulls the name of the database file from configuration or defaults to <code>wishlist.db</code> as before.
Unlike with DBM::Deep we now also have to tell it where to find the migrations file.
To target these files we use the application's <a href="http://mojolicious.org/perldoc/Mojolicious#home"><code>home</code></a> object and <a href="http://mojolicious.org/perldoc/Mojo/File">Mojo::File</a> which is a topic for another day.</p>
<p>The application's <code>startup</code> method establishes a <code>model</code> helper which creates an instance of Wishlist::Model and attaches the Mojo::SQLite instance to it.
This is a very important concept because this very thin helper is what ties the model into the application as a whole.
Any part of the application that needs data from the model ends up using this helper.</p>
<p>For example, there are still the <code>user</code> and <code>users</code> helpers that behave just as their counterparts from yesterday.
This time however they work via the model to do their business.</p>
<p>Finally the routes use the Full app declaration style but they do basically the same thing as before once they dispatch to their controllers.</p>
<h2>The List Controller</h2>
devdata/https_mojolicious.io_blog_2017_12_19_day-19-make-your-app-installable view on Meta::CPAN
my $app = shift;
# determine the storage location
my $file = $app->config->{database} || 'wishlist.db';
...
my $sqlite = Mojo::SQLite->new
->from_filename("$file")
->auto_migrate(1);
# attach migrations file
$sqlite->migrations->from_file(
$app->dist_dir->child('wishlist.sql')
)->name('wishlist');
return $sqlite;
};
sub startup {
my $app = shift;
devdata/https_mojolicious.io_blog_2017_12_20_day-20-practical-testing view on Meta::CPAN
And you have to clean up after yourself otherwise the next time the test is run it will be affected by the remaining data.</p>
<h2>Mocking Helpers</h2>
<p>If you have done any testing you've probably dealt with mocking, but if you haven't, mocking is the act of replacing functionality from essentially unrelated code with test-specific code.
Doing this lets you test one section of code (called a unit) in isolation from others.</p>
<p>Everyone has their favorite mock library.
There are so many tastes and styles that in the end Many people make their own, including <a href="https://metacpan.org/pod/Mock::MonkeyPatch">yours truly</a>.
Of course you can use those libraries in Mojolicious when appropriate.
As I mentioned before you can also mock out services by attaching tiny Mojolicious applications to a UserAgent's <a href="http://mojolicious.org/perldoc/Mojo/UserAgent#server"><code>server</code></a> attribute or making an entire external service...
<p>In some cases however, the natural place to mock is in the place of a helper.
When you think about it, this is actually rather obvious since helpers are often the glue used in Mojolicious applications to combine disparate code, like models or in this case the <a href="https://github.com/jberger/Wishlist/blob/blog_post/practica...
<p>To test this we could actually do any of the mentioned options from mocking <a href="https://metacpan.org/pod/LinkEmbedder#get">LinkEmbedder->get</a> to attaching a mock service.
That said it is sufficient here to just replace the helper, which is as easy as assigning over it.</p>
<pre><code class="hljs"><span class="hljs-keyword">use</span> <span class="hljs-function">Mojo::Base</span> -strict;
<span class="hljs-keyword">use</span> <span class="hljs-function">Test::More</span>;
<span class="hljs-keyword">use</span> <span class="hljs-function">Test::Mojo</span>;
<span class="hljs-keyword">my</span> <span class="hljs-type">$t</span> = <span class="hljs-function">Test::Mojo</span>->new(
'<span class="hljs-string">Wishlist</span>',
{database => '<span class="hljs-string">:temp:</span>'}