Acme-CPANModulesBundle-Import-MojoliciousAdvent-2017

 view release on metacpan or  search on metacpan

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

260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
Because of that, headers are omitted from the output unless you pass <code>-v</code>.</p>
 
<p>Let&#39;s see what it can do!
You can find the latest version of <code>IO::Socket::SSL</code> using the <a href="https://github.com/metacpan/metacpan-api/blob/master/docs/API-docs.md">Meta::CPAN JSON API</a>.
The response is parsed as JSON and only the <code>version</code> element is output.</p>
 
</code></pre>
 
<p>You can fetch the Perl headlines from reddit.
To do so we fetch the url (following redirects with <code>-r</code>), then we give it a <a href="http://mojolicious.org/perldoc/Mojo/DOM/CSS">CSS3 selector</a>, and finally extract the text from each found element.</p>
 
<pre><code>mojo get -r reddit.com/r/perl &#39;p.title &gt; a.title&#39; text
</code></pre>
 
<p>How fun is that?!</p>
 
<ul>
<li>You can POST or PUT or DELETE data.</li>
<li>It handles HTTP basic authentication using <code>username:password@</code> in the URL.</li>
<li>You can submit forms, even with file uploads using the standard <code>@filename</code> syntax.</li>

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

306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
<p>These methods allow the (optional) first argument to be a <a href="http://mojolicious.org/perldoc/Mojo/JSON/Pointer">JSON Pointer</a> to &quot;dive in&quot; to the data structure.
Very handy when you only care about subsets of the data.</p>
 
<pre><code>$t-&gt;get_ok(&#39;/santa_list/joel.json&#39;)
  -&gt;json_is(&#39;/status&#39;, &#39;nice&#39;);
</code></pre>
 
<p>Of course there are methods to test HTML responses.
Since it makes little sense to test the whole thing (and if you wanted to you could use <code>content_</code>), these take a <a href="http://mojolicious.org/perldoc/Mojo/DOM/CSS">CSS3 Selector</a> to narrow their focus in a similar manner to the JSON...
To inspect the textual portions of the HTML response, use the <code>text_</code> methods with a selector.
For other tests, there might not be text to test, or the value doesn&#39;t matter.
For those cases there are <code>element_exists</code>, <code>element_exists_not</code>, and <code>element_count_is</code>, which, as their names indicate, take a selector and tries to find if or how many elements match it.
These really need a post of their own, but as a few examples</p>
 
<pre><code>$t-&gt;text_is(&#39;div.main-content p:nth-of-type(2)&#39;, &#39;This is the third paragraph of the main-section of text&#39;);
$t-&gt;element_exists(&#39;img[src=&quot;kitten.jpg&quot;]&#39;);
</code></pre>
 
<h2>Testing Websockets</h2>
 
<p>Websockets are an intersting challenge to test, however Test::Mojo makes them easy.
We&#39;ve already seen that you open a websocket with <code>websocket_ok</code>.</p>

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

146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
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;;
 
has custom_selector =&gt; &#39;a&#39;;
 
sub find_custom {
  my $self = shift;
  return $self-&gt;find($self-&gt;custom_selector);
}
</code></pre>
 
<p>This example shows three interesting features.
First is that even though it is not a class, the package still gets Mojo::Base&#39;s <a href="http://mojolicious.org/perldoc/Mojo/Base#has">has</a> keyword, used to make accessors for attributes.
Second is that a new keyword, <code>requires</code>, has been added, coming from <a href="https://metacpan.org/pod/Role::Tiny#requires">Role::Tiny</a>.
This keyword tells the role that it can only be composed into a class that provides a <code>find</code> method.
Consider the new <code>find_custom</code> method, since it uses <code>find</code> if the class it is composed into didn&#39;t provide that method our new method couldn&#39;t behave as expected.</p>
 
<p>Indeed several keywords are imported from Role::Tiny including <code>with</code> to compose other roles and several method modifiers coming from <a href="https://metacpan.org/pod/Class::Method::Modifiers">Class::Method::Modifiers</a> (which is an ...

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

233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
    -&gt;db
    -&gt;insert(
      &#39;<span class="hljs-string">users</span>&#39;,
      {name =&gt; <span class="hljs-type">$name</span>},
    )-&gt;last_insert_id;
}
 
<span class="hljs-keyword">sub </span><span class="hljs-function">user</span> {
  <span class="hljs-keyword">my</span> (<span class="hljs-type">$self</span>, <span class="hljs-type">$name</span>) = <span class="hljs-type">@_</span>;
  <span class="hljs-keyword">my</span> <span class="hljs-type">$sql</span> = &lt;&lt;<span class="hljs-keyword">&#39;  SQL&#39;;</span>
    select
      user.id,
      user.name,
      (
        select
          json_group_array(item)
        from (
          select json_object(
            &#39;id&#39;,        items.id,
            &#39;title&#39;,     items.title,
            &#39;url&#39;,       items.url,
            &#39;purchased&#39;, items.purchased
          ) as item
          from items
          where items.user_id=user.id
        )
      ) as items
    from users user

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

266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
    -&gt;query(<span class="hljs-type">$sql</span>, <span class="hljs-type">$name</span>)
    -&gt;expand(json =&gt; &#39;<span class="hljs-string">items</span>&#39;)
    -&gt;hash;
}
 
<span class="hljs-keyword">sub </span><span class="hljs-function">list_user_names</span> {
  <span class="hljs-keyword">my</span> <span class="hljs-type">$self</span> = <span class="hljs-function">shift</span>;
  <span class="hljs-keyword">return</span> <span class="hljs-type">$self</span><span class="hljs-type">
</span>    -&gt;sqlite
    -&gt;db
    -&gt;<span class="hljs-function">select</span>(
      &#39;<span class="hljs-string">users</span>&#39; =&gt; [&#39;<span class="hljs-string">name</span>&#39;],
      <span class="hljs-function">undef</span>,
      {-asc =&gt; &#39;<span class="hljs-string">name</span>&#39;},
    )
    -&gt;arrays
    -&gt;<span class="hljs-function">map</span>(<span class="hljs-keyword">sub</span>{ <span class="hljs-variable">$_</span>-&gt;[0] });
}
 
<span class="hljs-keyword">sub </span><span class="hljs-function">add_item</span> {
  <span class="hljs-keyword">my</span> (<span class="hljs-type">$self</span>, <span class="hljs-type">$user</span>, <span class="hljs-type">$item</span>) = <span class="hljs-type">@_</span>;

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

315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
    )-&gt;rows;
}
 
<span class="hljs-number">1</span>;
 
</code></pre>
 
<p><small>lib/Wishlist/Model.pm</small></p>
 
<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.

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

270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
done_testing;
 
</code></pre>
 
 
<p>Because the template expects the result to be an object we have to build a tiny class to contain our mock results.
Also whenever you are mocking, it is important to check the input your mock received as well as the results that the calling code derives from your mock return value.</p>
 
<p>In the test you can also see some examples of how to use selectors to test for both text and attribute values.
The text test is especially important because it shows that the html value that I got back from the LinkEmbedder isn&#39;t being escaped by the template and will render as HTML to the client.</p>
 
<p>A few more tests and some documentation and our application will really be taking final shape!</p>
 
              </section>
              <small><p><a href="https://commons.wikimedia.org/w/index.php?curid=11337658">Image</a> by Hawaii Volcano Observatory, USGS - <a class="external text" href="http://hvo.wr.usgs.gov/kilauea/update/archive/2009/2009_Jun-Oct.html" rel="nofol...
</small>
 
              <p class="tags">
                <span>Tagged in </span>:

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

152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
<p>Mojo is an amazing toolkit for web development, as shown in previous
calendar entries, but using components of it can also solve problems in other
non-web spaces like these. Why use Mojo for this? Because it makes it <em>easy</em>.</p>
 
              </section>
              <section id="section-2">
                  <h2>Down By The Riverside</h2>
 
<p>First of all, we need the stream of data.
Initially, I used <code>tshark</code> for this, though another member of the OpenHMD team
built another application, OpenHMD-Dumper, which has both a device selection
interface and opens the device to read the packets, which makes this much
easier.
Doing so allows us to ask others who have HMDs to send us these logs, so we
can add driver support for devices none of the team have access to!
Otherwise, we use something else to open the device and read data and <code>tshark</code>
to capture and output the packet data.</p>
 
<pre><code>tshark -i usbmon1 -Y &#39;usb.src == &quot;1.22.1&quot;&#39; -T fields -e usb.capdata
</code></pre>

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

403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
various sizes until you see a (rough) sine wave, indicating you&#39;ve got the
right offset and number of bytes for that part of the puzzle!</p>
 
<h2>Moving On To Greater Things</h2>
 
<p>This tool could easily be improved (and will be, when it is next called upon).
For example, both the extraction and fixing of the headers could be made into
commands, as demonstrated in
 
<p>It could also be made into a proper web application where the user can select
the action they want to do and an animation shows the movement that is wanted
(not everyone is familiar with nautical terms after all!).
Perhaps even with a device select?
A UI that allows the user to select the offset, size and unpack method and
render the graphs as appropriate could cut down the time to analyse.
Better yet, if it could detect which combinations result in a rough sine wave,
it could narrow down and present the user with likely candidates for each
movement..</p>
 
<p>.. but those are improvements for another day!</p>
 
              </section>
              <small><p><a href="https://www.pexels.com/photo/sky-woman-clouds-girl-123335/">Image</a> by Bradley Hook, in the Public Domain.</p>
</small>



( run in 1.099 second using v1.01-cache-2.11-cpan-49f99fa48dc )