Dancer Advent Calendar 2014 http://advent.perldancer.org/ Past and future http://advent.perldancer.org/2014/24 perl http://advent.perldancer.org/2014/24 Wed, 24 Dec 2014 00:00:00 -0000 <div class="pod-document"><h1><a name="past_and_future"></a>Past and future</h1> <p>This last article is meant to reflect on the past, in the present, and speculate about the future, perhaps even - with the cover of darkness - offer some future plans, in quiet murmur, of course. :)</p> <h2><a name="popularity"></a>Popularity</h2> <p>We all care about popularity. Popularity isn't just cool factor, it's also a measurement of success - doing well, going in the right direction.</p> <p>But how do you measure popularity? It's <a href="http://blog.timbunce.org/2008/04/12/tiobe-or-not-tiobe-lies-damned-lies-and-statistics/">hard</a>.</p> <p>We have different mechanisms made just to measure success. In our world that would Github stars, Github watchers, and even MetaCPAN votes. However, if you take a look at Moose, it only has 78 stars on Github, and only 15 watchers. Would you say Moose is less successful than Dancer? Not at all. This measurement simply is far from accurate.</p> <p>However, there is another way to measure popularity.</p> <p>One of my favorite and most respected authors provides the following comment in all of his projects:</p> <p><i>All complex software has bugs lurking in it, and this module is no exception. If you find a bug please either email me, or add the bug to cpan-RT.</i></p> <p>Complex software accumulates tickets. These are bugs, feature requests, failing tests, missing tests, questions, and so on. Hopefully authors will collect these in a ticket system like RT or Github.</p> <p>The amount of tickets you have indicates how many of these came up. While some authors will open a staggering amount of tickets for their projects (which is nothing short of being thorough and responsible) and projects may have a devoted user who opens tickets upon tickets, most tickets are opened by the audience of users. The number indicates how many have used your software to a degree of contacting you, providing input, and found you or your project approachable and tried to help improve it.</p> <p>You can count the number of tickets for a project, remove the core authors (and check for when they weren't core authors yet - it happens sometimes), normalize to amount of users opening the issues, and look at the numbers.</p> <p>Dancer has two main repositories: Dancer 1 and Dancer 2. Together they have accumulated around 1,900 tickets. Yes, that's close to <b>two thousand</b> tickets. About 1,000 of them are pull requests. Yes, that's right. Over <b>one thousand</b> pull requests. Actually, my numbers are off. I only took into account Github. Dancer has been running on RT earlier and there's a quite a few there as well. That would also be off, because we accept tickets through any medium. We get them in personal emails, on the mailing list, at conferences, on IRC, and so on.</p> <p>Beyond all measurements, I'd say we reached people. More importantly, I would say these people reached us. I cannot be more proud of this achievement.</p> <p>I can talk about <a href="http://www.booking.com">Booking</a> using Dancer. I can talk about <a href="http://www.shutterstock.com">Shutterstock</a> using Dancer. I can talk about <a href="http://www.moonfruit.com">MoonFruit</a>, <a href="http://www.uk2.net">UK2</a>, <a href="https://www.tilt.com">Tilt</a>, <a href="https://www.financejobs.co">FinanceJobs</a>, <a href="http://perlmaven.com">PerlMaven</a>, <a href="http://geekuni.com">Geekuni</a>, the <a href="http://www.strehler-cms.org">Strehler CMS</a>, and even a <a href="http://www.finchleyspiritualistchurch.org.uk">spiritual church</a> and an <a href="http://theanarchistlibrary.org">anarchist library</a> using Dancer.</p> <p>I can talk about all of these, but that's not the great part. The great part is our contributors.</p> <h2><a name="contribution_is_key"></a>Contribution is key</h2> <p>Having someone contributing their time and skill is priceless. Contributors are the life-force of a project - not the core developers. Almost any core developer in Free and Open Source will undoubtedly tell you that development's gratitude is someone using it, thanking you for it, or better yet, improving it further by contributing something - a test, a documentation patch, or even opening tickets.</p> <p>Except for Dancer's founder, Alexis (<i>@sukria</i>) Sukrieh, all Dancer core developers started as contributors. This includes yours truly and everyone else in the team. This hasn't changed since. We always saw and see ourselves simply as contributors with more responsibility.</p> <p>Dancer has enjoyed the help of an astonishing amount of contributors. Overall, the Dancer project has received contributions from over 270 people. While this seems big it fails to account for many contributors and many forms of contribution. It's merely the number of recognized code committers.</p> <p>Sam Batschelet organized the Dancer conference, Gabor Szabo took the Dancer website under his care, Peter Martini provided a Dancer Docker image, David Dick packages the project for Fedora, Paul Cochrane is working on improving the documentation for beginners, and there are numerous other examples for tremendous work done by the community.</p> <p>Let me take a moment to thank you all for the work you've done and the work that you do, in the community and for the community.</p> <p>So now, where is all of this heading?</p> <h2><a name="what_the_future_holds___"></a>What the future holds...</h2> <p>It's hard to say what the future holds for Dancer, but we do have quite a few plans.</p> <p>The short list contains:</p> <ul> <li><a name="item_Thorough_documentation_overhaul"></a><b>Thorough documentation overhaul</b> </li> <li><a name="item_Improve_the_plugin_system_for_Dancer2"></a><b>Improve the plugin system for Dancer2</b> </li> <li><a name="item_Port_all_useful_plugins_to_Dancer2"></a><b>Port all useful plugins to Dancer2</b> </li> <li><a name="item_Rewrite_fair_portions_of_the_testing_suite"></a><b>Rewrite fair portions of the testing suite</b> </li> <li><a name="item_Many_core_cleanups"></a><b>Many core cleanups</b> </li> <li><a name="item_Additional_functionality"></a><b>Additional functionality</b> </li> <li><a name="item_Speed_optimizations"></a><b>Speed optimizations</b> </li> <li><a name="item_Compatibility_shims"></a><b>Compatibility shims</b> </li> <li><a name="item_Code_linting"></a><b>Code linting</b> </li> </ul> <p>We even have some idea regarding features we want to introduce:</p> <ul> <li><a name="item_Full_asynchronous_support"></a><b>Full asynchronous support</b> </li> <li><a name="item_Route_naming"></a><b>Route naming</b> </li> <li><a name="item_Chained_hooks"></a><b>Chained hooks</b> </li> <li><a name="item_Stronger_command_line_tooling"></a><b>Stronger command line tooling</b> </li> <li><a name="item_More_decoupling_of_components"></a><b>More decoupling of components</b> </li> </ul> <p>As you can see, there are plenty of ideas and the opportunities are abound.</p> <p>While we want to add some of these features as quickly as possible, we need to make sure we get them right, that we design them well, that we do not overlap with other features, and that we don't have to revert them.</p> <p>In fact, what we need is your help.</p> <p>I can promise some will be difficult to implement, some will take considerable time, and some will be like trudging through mud (especially any OS compatibility work), but above all, I can promise you will have a good time. :)</p> <p>I would like to thank everyone for an amazing year. I hope to see you and work with you this new year and provide you all with another set of articles at the next Advent Calendar.</p> <p>Have a merry Christmas, a wonderful Hanukkah, and a tremendous Festivus, for the rest of us!</p> <h2><a name="author"></a>Author</h2> <p>This article has been written by Sawyer X for the Perl Dancer Advent Calendar 2014.</p> <h2><a name="copyright"></a>Copyright</h2> <p>No copyright retained. Enjoy.</p> <p>2014 // Sawyer X <code>&lt;xsawyerx@cpan.org&gt;</code></p> </div> Dynamic routing in Dancer is dynamic http://advent.perldancer.org/2014/23 perl http://advent.perldancer.org/2014/23 Tue, 23 Dec 2014 00:00:00 -0000 <div class="pod-document"><h1><a name="dynamic_routing_in_dancer_is_dynamic"></a>Dynamic routing in Dancer is dynamic</h1> <p>Dancer provides with a number of ways to do dynamic routing, A.K.A., chained actions. Let's take a look at situations that lead to such a requirement and how to achieve it.</p> <h2><a name="the_use_case"></a>The use-case</h2> <p>Let's say you were building a message board that supported any number of boards - each with a custom URL. For example, if this were something for a Beethoven fan site you might have a board for discussing each genre of work composed by him, with URLs like:</p> <ul> <li><a name="item_http___www_beethovenfans_com_string_quartets_"></a><b>http://www.beethovenfans.com/string-quartets/</b> </li> <li><a name="item_http___www_beethovenfans_com_symphonies_"></a><b>http://www.beethovenfans.com/symphonies/</b> </li> <li><a name="item_http___www_beethovenfans_com_piano_sonatas_"></a><b>http://www.beethovenfans.com/piano-sonatas/</b> </li> </ul> <p>Visiting the top-level board url would show you a list of all posts under that board. You could start a discussion by simply using <i>/new-post</i> under the board name. So to start a discussion under string-quartets, you'd go to:</p> <pre class="prettyprint">http://www.beethovenfans.com/string-quartets/new-post</pre> <p>Similarly, you could view or permalink to a specific post as:</p> <pre class="prettyprint">http://www.beethovenfans.com/string-quartets/opus-18-no-6</pre> <p>Where <i>opus-18-no-6</i> is the unique identifier of the post - possibly generated from the title of the post.</p> <p>Similarly, to upvote a post on the board:</p> <pre class="prettyprint">http://www.beethovenfans.com/string-quartets/opus-18-no-6/upvote</pre> <p>Each time someone accesses one of these URLs, you first need to check if the discussion board exists. To put it in code:</p> <pre class="prettyprint">get '/:board' =&gt; sub { my $board = param('board'); # validation code for $board ... }; get '/:board/new-post' =&gt; sub { my $board = param('board'); # validation code for $board }; get '/:board/opus-18-no-6/upvote' =&gt; sub { my $board = param('board'); # validation code for $board };</pre> <p>Each of these handlers have to start by validating the existence of a discussion board before they do anything else. It makes sense to have the discussion board validation logic in one place.</p> <h2><a name="setup_method"></a>Setup method</h2> <p>One way to do this is by defining a special setup method which you call when the application starts up. This method can use the <b><code>prefix</code></b> keyword to set up routes for each board.</p> <pre class="prettyprint">sub get_boards { # in a real life application this would come from a # database. for the sake of simplicity, we simply return # a hard-coded list return qw(string-quartets symphonies piano-sonatas piano-trios); } sub setup_routes { my @boards = get_boards; foreach my $board (@boards) { prefix "/$board" =&gt; sub { # any variables here will be accessible to the handlers # defined below my $welcome_message = "Welcome to the group for discussing: $board"; get '/' =&gt; sub { # show a list of all the posts under the board $board # for demo's sake simply return the welcome message return $welcome_message; }; get '/:post_id' =&gt; sub { # do the work here or delegate to a specialised class my $post_id = param('post_id'); # check if the ID is valid and do something with it # for demo's sake show variables you have access to: return "I was called with board: $board, post id: $post_id" . " and have access to the welcome_message variable: $welcome_message"; }; }; } }</pre> <p>Then in your app.pl:</p> <pre class="prettyprint">#!/usr/bin/env perl use FindBin; use lib "$FindBin::Bin/../lib"; use beethoven; beethoven-&gt;setup_routes; beethoven-&gt;to_app;</pre> <p>Calling setup_routes essentially materialises the routes beforehand based on what <code>get_boards</code> returns. If the user enters a board that doesn't exist, it will automatically get picked up by Dancer's default handling of missing routes and a 404 error will be returned to the user.</p> <p>This approach works well if the number of boards is small. Say in hundreds, or may be in thousands, but not in hundreds of thousands. After a certain point the Dancer process will grow too big in memory. That might or might not be a problem depending on your infrastructure.</p> <p>Also if boards are not fixed and are created all the time then this approach will not work very well as it would required an app restart to pick up all the new boards (or for that matter changes to the URL slugs for the existing boards, or deletions).</p> <h2><a name="the_hook"></a>The hook</h2> <p>There is another way that allows us to dynamically check for a board rather than materialising all our routes up front. The basic idea is to combine <b><code>prefix</code></b> with a <b><code>before</code></b> handler. Let's put together some code to illustrate this idea:</p> <pre class="prettyprint">hook before =&gt; sub { my $board = param('board'); if ($board &amp;&amp; board_is_valid($board)) { var board =&gt; $board; } }; prefix '/:board' =&gt; sub { get '/' =&gt; sub { # show a list of all the posts under the board $board # for demo's sake simply return the welcome message my $board = var('board') or pass; my $welcome_message = "Welcome to the group for discussing: $board"; return $welcome_message; }; get '/:post_id' =&gt; sub { my $board = var('board') or pass; # do the work here my $post_id = param('post_id'); # check if the ID is valid and do something with it # for demo's sake show variables you have access to: return "I was called with board: $board, post id: $post_id"; }; }; sub board_is_valid { my $board = shift; return if not defined $board; # in a real life application we would check this against a table in # a database or through a backend service. for the sake of # simplicity, let's just check against a hardcoded list my %valid_boards = map { $_ =&gt; 1 } qw(string-quartets symphonies piano-sonatas piano-trios); return defined $valid_boards{$board}; }</pre> <p>This time, our <code>before</code> handler will catch the request first. It sets up the <code>board</code> variable using <b><code>var</code></b> that is automatically passed around to each handler. The handler first checks if the <code>board</code> variable exists and if it doesn't, it simply defers the handling to the Dancer's default route handling. Since no other routes to handle the <code>:board</code> exist, this results in a 404.</p> <p>While it alleviates the need to build all possible routes up front, the one downside to this approach is having to check for the presence of <code>board</code> variable in each handler. On the positive side, you can dynamically add boards without restarting the application for them to be available.</p> <h2><a name="even_more_ways"></a>Even more ways</h2> <p>Additional approaches for the dynamic route handling problem exist. Most notably, another approach was recently documented by Yanick Champoux uses <a href="http://www.perladvent.org/2013/2013-12-02.html">megasplat</a> to produce <a href="http://techblog.babyl.ca/entry/chained-dancer">chained actions</a>.</p> <h2><a name="minimum_version"></a>Minimum version</h2> <p>This article requires <a href="https://metacpan.org/module/Dancer2">Dancer2</a> version 0.159000.</p> <p><i>(hopefully released soon enough.)</i></p> <h2><a name="conclusion"></a>Conclusion</h2> <p>Dancer has many methods of producing dynamic routes (or "chained actions") and each of them has its benefits and drawbacks.</p> <h2><a name="author"></a>Author</h2> <p>This article has been written by Deepak Gulati for the Perl Dancer Advent Calendar 2014.</p> <h2><a name="copyright"></a>Copyright</h2> <p>Creative Commons Deepak Gulati 2014.</p> </div> The Dancer community policy http://advent.perldancer.org/2014/22 perl http://advent.perldancer.org/2014/22 Mon, 22 Dec 2014 00:00:00 -0000 <div class="pod-document"><h1><a name="the_dancer_community_policy"></a>The Dancer community policy</h1> <p>In October 2014 we have introduced our Dancer core and community policy and our Standards of Conduct. You can find them at <a href="https://metacpan.org/module/Dancer::Policy">Dancer::Policy</a> or <a href="https://metacpan.org/module/Dancer2::Policy">Dancer2::Policy</a> (identical documents).</p> <p>While the Dancer community has always pride itself of the warm feeling members have received, helpfulness and kindness were abundant, we still found it necessary to introduce a policy document.</p> <h2><a name="why_do_we_need_it"></a>Why do we need it?</h2> <p>While the policy is not an answer to a situation in the Dancer community, it is to behavior we've seen in other communities in and out of the tech industry.</p> <p>There are people who are not only discriminated against, but also marginalized daily. There are people who feel pushed out of the way, made small and insignificant, and dis-empowered by others who tend to have a more favorable starting point - what is usually referred to as "privileged".</p> <p>We felt it is absolutely crucial to provide a document that makes it absolutely clear, without a shadow of a doubt, that the Dancer community is maintained and owned by its members - all having a fair and equal stance in it. It is essential that everyone in the community feel and understand this space belongs to them just as much as it does to anyone else.</p> <h2><a name="introducing_a_problem_where_none_exists"></a>Introducing a problem where none exists?</h2> <p>So, are we really just fixing a situation that is not broken? If all is fine and well in the Dancer community, why provide such standards of conduct? That's a good question.</p> <p>Standards of conduct have multiple purposes:</p> <ul> <li><a name="item_Set_expectations_of_behavior"></a><b>Set expectations of behavior</b> <p>It is important that people in the community are aware of both what is expected from them (such as "you are expected to not be abusive towards anyone") and what they can expect from others (such as "you can expect not to be abused by anyone"). Setting these expectations allows people to let their guard down, enjoy their time, approach others, and be an active member without fearing abuse.</p> <p>The community, above all, should be a <b>safe space</b> for all of its members.</p> </li> <li><a name="item_Provide_a_stern_warning"></a><b>Provide a stern warning</b> <p>The document clearly explains that not only do we have expectations, but we will take measures against those who violate them. This helps defend the expectations we described above.</p> <p>If you will violate those standards, we will make sure you are held accountable. This makes sure these are not empty promises and that they won't be perceived as such.</p> </li> <li><a name="item_Enforcement_transparency"></a><b>Enforcement transparency</b> <p>While we provide these standards and a promise to enforce them, it is also important to provide transparency. You need to know <i>what</i> will be done and <i>how</i> decisions will be made.</p> </li> </ul> <h2><a name="can_i_still_be_me"></a>Can I still be me?</h2> <p>Many people worry that with a standards of conduct policy they will not be able to be themselves anymore. This is worth addressing.</p> <p>The standards of conduct clearly stipulate you may not, under any circumstance, be abusive to others. If violating that robs you of your being, it means you are an abusive person - a person we hope other community members will not have to experience or deal with.</p> <p>This, however, is not the same as "I will need to watch what I say". Having to make an effort to be kinder, more composed, or in general more respectful, is an understood effort. It is an effort we make every day. We make sure we're more respectful towards our friends, colleagues, peers, and we make sure we curse much less around our parents.</p> <p>While it is not always a simple task to work on our behavior, it is far different than violating your core principles.</p> <p>In short, if your core principles are to hurt others, and you feel like our standards of conduct negate that, we've done a good job.</p> <h2><a name="conclusion"></a>Conclusion</h2> <p>The community is maintained by the community members. Each and every single member should be regarded with respect, and we should all feel a sense of belonging to and in our community.</p> <p>The Dancer standards of conduct have been introduced to make sure new members understand this and know what we each expect from each other.</p> <p>We were thrilled with getting such positive results from a community. Members have unequivocally said we are happy to make this message clear to all current and future members.</p> <h2><a name="thanks"></a>Thanks</h2> <p>Praise should be given to <code>#p5p</code> (The Perl 5 Porters list) which provided the base for the policy document, to <a href="http://twitter.com/sungo">@sungo</a> for pushing to make community standards published clearly and for doing so with the Perl IRC servers, and to <a href="https://metacpan.org/author/RIBASUSHI">ribasushi</a> for helping revise and suggest improvements to the policy as it was being written.</p> <p>The biggest thanks is, as always, to the wonderful and loving Dancer community and all of its members. :)</p> <h2><a name="author"></a>Author</h2> <p>This article has been written by Sawyer X for the Perl Dancer Advent Calendar 2014.</p> <h2><a name="copyright"></a>Copyright</h2> <p>No copyright retained. Enjoy.</p> <p>2014 // Sawyer X <code>&lt;xsawyerx@cpan.org&gt;</code></p> </div> Middlewared Dancer: our usage of middlewares http://advent.perldancer.org/2014/21 perl http://advent.perldancer.org/2014/21 Sun, 21 Dec 2014 00:00:00 -0000 <div class="pod-document"><h1><a name="middlewared_dancer__our_usage_of_middlewares"></a>Middlewared Dancer: our usage of middlewares</h1> <p>Now that we understand what <a href="http://advent.perldancer.org/2014/20">middlewares</a> are and how to use them, we would like to share a small secret with which we ended the previous article.</p> <p>While much of the existing middlewares provide additional features, there are middlewares that can help supplement a web framework or reduce the amount of work it does.</p> <p>In <a href="https://metacpan.org/module/Dancer2">Dancer2</a> we rely heavily on Plack and therefore middlewares provide much-appreciated help which plays well with our framework, since it's all <a href="https://metacpan.org/module/PSGI">PSGI</a> at the end of the day.</p> <p>Here are the current middlewares we use internally in Dancer2:</p> <h2><a name="static"></a>Static</h2> <p>First, as described in <a href="http://advent.perldancer.org/2014/6">a previous article</a>, Dancer2 now uses <a href="https://metacpan.org/module/Plack::Middleware::Static">Plack::Middleware::Static</a> to provide static files.</p> <p>This helped provide consistency with both the previous behavior (a la Dancer 1) and with how users actually expect static file serving to work.</p> <h2><a name="head"></a>Head</h2> <p>Using <a href="https://metacpan.org/module/Plack::Middleware::Head">Plack::Middleware::Head</a>, we can provide correct <b>HEAD</b> requests much more easily. A <b>HEAD</b> request should not have a body, and the middleware simply deletes the body of a response if the request method is <b>HEAD</b>.</p> <p>This allows us to define every <b>GET</b> request as <b>HEAD</b> and have the middleware delete the response body to produce an appropriate response.</p> <p>One less concern!</p> <h2><a name="contentlength"></a>ContentLength</h2> <p>Originally Dancer2 would have to set the length of a response content body every time it was set. Although this could have been improved by only setting it at the very end, we would still have to account for three kinds of responses available in PSGI.</p> <p>Instead, we're using <a href="https://metacpan.org/module/Plack::Middleware::ContentLength">Plack::Middleware::ContentLength</a> to decide and set the <b>Content-Length</b> header for us after we've returned a response. Our code is thus cleaner and less error-prone.</p> <h2><a name="fixmissingbodyinredirect"></a>FixMissingBodyInRedirect</h2> <p>Having <a href="https://metacpan.org/module/Plack::Middleware::FixMissingBodyInRedirect">Plack::Middleware::FixMissingBodyInRedirect</a> provides the proper response body when a user returns a redirect. You don't have to care about it anymore, it's simply there, automagically.</p> <h2><a name="removeredundantbody"></a>RemoveRedundantBody</h2> <p>When returning a status of <b>204</b> or <b>304</b> the body needs to be stripped.</p> <p><a href="https://metacpan.org/module/Plack::Middleware::RemoveRedundantBody">Plack::Middleware::RemoveRedundantBody</a> takes care of that for us. Since it uses <a href="https://metacpan.org/module/Plack::Util">Plack::Util</a>'s <code>status_with_no_entity_body</code>, it also takes care of statuses <b>100</b> and <b>101</b>, which were not covered beforehand.</p> <h2><a name="conclusion"></a>Conclusion</h2> <p>When writing a web framework, you (or at least we) would like to focus on the features and richness of the DSL and syntax, and not the small details of HTTP implementations.</p> <p>Using middlewares reduces the amount of work we do to keep up with all of these small bits and does a damn fine job at it.</p> <p>We will continue to explore new middlewares we can make use of, and perhaps even push some of our code into middlewares so it could be decoupled and even used by non-Dancer code.</p> <h2><a name="author"></a>Author</h2> <p>This article has been written by Sawyer X for the Perl Dancer Advent Calendar 2014.</p> <h2><a name="copyright"></a>Copyright</h2> <p>No copyright retained. Enjoy.</p> <p>2014 // Sawyer X <code>&lt;xsawyerx@cpan.org&gt;</code></p> </div> Meddling with Middlewares http://advent.perldancer.org/2014/20 perl http://advent.perldancer.org/2014/20 Sat, 20 Dec 2014 00:00:00 -0000 <div class="pod-document"><h1><a name="meddling_with_middlewares"></a>Meddling with Middlewares</h1> <p><a href="https://metacpan.org/module/Plack">Plack</a> provides a useful component called a <a href="https://metacpan.org/module/Plack::Middleware">Middleware</a>, which wraps applications with functionality.</p> <p>You can use them to your advantage to tack on additional features and improvements to your application.</p> <h2><a name="middleware_usage"></a>Middleware usage</h2> <p>Adding middlewares can be breeze using the <a href="https://metacpan.org/module/Plack::Builder">Plack::Builder</a> syntax:</p> <pre class="prettyprint">use MyApp; use Plack::Builder; builder { enable 'Auth::Basic', authenticator =&gt; sub { my ( $user, $pass, $env ) = @_; # test $user and $pass somehow }; MyApp-&gt;to_app; };</pre> <p>Since <code>to_app</code> returns an app, you can use it as the last statement to <code>builder</code>. In this example we add <code>Plack::Middleware::Auth::Basic</code> middleware to our new application stack.</p> <p>We can add more:</p> <pre class="prettyprint">builder { enable 'Auth::Basic', authenticator =&gt; sub { ... }; enable 'Rewrite', rules =&gt; sub { return 301 if s{^/foo/?$}{/bar/} or s{^/baz/?$}{/quux/}; ... }; MyApp-&gt;to_app; };</pre> <p>Now having <code>Plack::Middleware::Rewrite</code> as well. Having it before <i>Auth::Basic</i> will assure the rewrites will happen first. Having it after <i>Auth::Basic</i> will assure authentication will happen first.</p> <h2><a name="multiple_dancer_applications"></a>Multiple Dancer applications</h2> <p>As explained in our <code>to_app</code> <a href="http://advent.perldancer.org/2014/9">article</a>, you can set up multiple <a href="https://metacpan.org/module/Dancer2">Dancer2</a> applications using the same syntax:</p> <pre class="prettyprint">use MyApp; use MyApp::Admin; use Plack::Builder; builder { mount '/' =&gt; MyApp-&gt;to_app; mount '/admin' =&gt; MyApp::Admin-&gt;to_app; };</pre> <p>We can still add middlewares to that stack:</p> <pre class="prettyprint">builder { enable 'Rewrite', rules =&gt; sub { ... }; mount '/' =&gt; MyApp-&gt;to_app; mount '/admin' =&gt; MyApp::Admin-&gt;to_app; };</pre> <p>Not bad, but there's one more situation to cover.</p> <h2><a name="going_nuts"></a>Going nuts</h2> <p>Let's take a look at another situation: adding authentication using a middleware:</p> <pre class="prettyprint">builder { enable 'Auth::Basic', authenticator =&gt; sub { ... }; mount '/' =&gt; MyApp-&gt;to_app; mount '/admin' =&gt; MyApp::Admin-&gt;to_app; };</pre> <p>But wait. This doesn't make sense. We want to only enable authentication for the <i>admin</i> application. This will set it up to both of them.</p> <p>Since the Dancer application is a callback, and <code>builder</code> wraps callbacks by providing another callback... you might see where this is heading:</p> <pre class="prettyprint">builder { mount '/' =&gt; MyApp-&gt;to_app; mount '/admin' =&gt; builder { enable 'Auth::Basic', authenticator =&gt; sub { ... }; MyApp::Admin-&gt;to_app; }; };</pre> <p>Pretty cool, huh? Very!</p> <h2><a name="conclusion"></a>Conclusion</h2> <p>Middlewares are awesome and very easy to integrate with Dancer. In fact, we use middlewares internally in <a href="https://metacpan.org/module/Dancer2">Dancer2</a>, which you will read about in the next article.</p> <h2><a name="author"></a>Author</h2> <p>This article has been written by Sawyer X for the Perl Dancer Advent Calendar 2014.</p> <h2><a name="copyright"></a>Copyright</h2> <p>No copyright retained. Enjoy.</p> <p>2014 // Sawyer X <code>&lt;xsawyerx@cpan.org&gt;</code></p> </div> Authentication for the masses http://advent.perldancer.org/2014/19 perl http://advent.perldancer.org/2014/19 Fri, 19 Dec 2014 00:00:00 -0000 <div class="pod-document"><h1><a name="authentication_for_the_masses"></a>Authentication for the masses</h1> <p>Just like at some point every developer writes a templating system, every web developer eventually writes a form for authentication.</p> <p>It's simple: we check the user credentials on a request and decide whether to continue or redirect them to a form. The form allows them to submit their username and password and we save that and create a session for them so when they now try the original request, we recognize them and allow them in.</p> <h2><a name="basic_application"></a>Basic application</h2> <p>The application is fairly simple. We have a route that needs authentication, we have a route for showing the login page, and we have a route for posting login information and creating a session.</p> <pre class="prettyprint">package MyApp; use Dancer2; get '/' =&gt; sub { session('user') or redirect('/login'); template index =&gt; {}; }; get '/login' =&gt; sub { template login =&gt; {}; }; post '/login' =&gt; sub { my $username = param('username'); my $password = param('password'); my $redir_url = param('redirect_url') || '/login'; $username eq 'john' &amp;&amp; $password eq 'correcthorsebatterystaple' or redirect $redir_url; session user =&gt; $username; redirect $redir_url; };</pre> <h2><a name="tiny_authentication_helper"></a>Tiny authentication helper</h2> <p><a href="https://metacpan.org/module/Dancer2::Plugin::Auth::Tiny">Dancer2::Plugin::Auth::Tiny</a> allows you to abstract away not only the part that checks whether the session exists, but to also generate a redirect with the right path and return URL.</p> <p>We simply have to define what routes needs a login using Auth::Tiny's <code>needs</code> keyword.</p> <pre class="prettyprint">get '/' =&gt; needs login =&gt; sub { template index =&gt; {}; };</pre> <p>It creates a proper return URL using <code>uri_for</code> and the address from which the user arrived - something we didn't do ourselves.</p> <p>We can thus decorate all of our private routes to require authentication in this simple manner. If a user does not have a session, it will automatically forward it to <code>/login</code>, in which we would render a form for the user to send a login request.</p> <p>Auth::Tiny even provides us with a new parameter, <code>return_url</code>, which we can use to send the user back to their original requested path.</p> <p>We will still need to handle the password verification, but we have yet another small helper for this.</p> <h2><a name="password_hashing"></a>Password hashing</h2> <p>Many web developers don't understand the importance of hashing passwords. There are many articles to explain this, but few spend the time to read and understand them. From the multitude of methods available, and the different hashing alogrithms out there, it's not a simple task to decide on which combination to use and how.</p> <p><a href="https://metacpan.org/module/Dancer2::Plugin::Passphrase">Dancer2::Plugin::Passphrase</a> (recently ported from Dancer 1) provides a simple passwords-as-objects interface with sane defaults for hashed passwords which you can use in your web application. It uses <b>bcrypt</b> as the default but supports anything the <a href="https://metacpan.org/module/Digest">Digest</a> interface does.</p> <p>Assuming we have the original user-creation form submitting a username and password:</p> <pre class="prettyprint">package MyApp; use Dancer2; use Dancer2::Plugin::Passphrase; post '/register' =&gt; sub { my $username = param('username'); my $password = passphrase( param('password') )-&gt;generate; # $password is now a hashed password object save_user_in_db( $username, $password-&gt;rfc2307 ); template registered =&gt; { success =&gt; 1 }; };</pre> <p>We can now add the <b>POST</b> method for verifying that username and password:</p> <pre class="prettyprint">post '/login' =&gt; sub { my $username = param('username'); my $password = param('password'); my $saved_pass = fetch_password_from_db($username); if ( passphrase($password)-&gt;matches($saved_pass) ) { session user =&gt; $username; redirect param('return_url') || '/'; } # let's render instead of redirect... template login =&gt; { error =&gt; 'Invalid username or password' }; };</pre> <h2><a name="conclusion"></a>Conclusion</h2> <p>Both <a href="https://metacpan.org/module/Dancer2::Plugin::Auth::Tiny">Dancer2::Plugin::Auth::Tiny</a> and <a href="https://metacpan.org/module/Dancer2::Plugin::Passphrase">Dancer2::Plugin::Passphrase</a> are simple wrappers around basic functionality. You can check their code, it's pretty simple and straight-forward.</p> <p>The strength of plugins are not necessarily in complicated and weird code, but rather in abstracting difficult things to remember and get right, and making them accessible in your web environment and integrated with your application configuration.</p> <p>Authentication is not just easier with these modules, but safer.</p> <p>You might also want to read up on <a href="https://metacpan.org/module/Dancer2::Plugin::Auth::Extensible">Dancer2::Plugin::Auth::Extensible</a>.</p> <h2><a name="author"></a>Author</h2> <p>This article has been written by Sawyer X for the Perl Dancer Advent Calendar 2014.</p> <h2><a name="copyright"></a>Copyright</h2> <p>No copyright retained. Enjoy.</p> <p>2014 // Sawyer X <code>&lt;xsawyerx@cpan.org&gt;</code></p> </div> The method of the setup method http://advent.perldancer.org/2014/18 perl http://advent.perldancer.org/2014/18 Thu, 18 Dec 2014 00:00:00 -0000 <div class="pod-document"><h1><a name="the_method_of_the_setup_method"></a>The method of the setup method</h1> <p>Load-time setup of application variables depends on the availability of the configuration options, but we often have the requirement of being able to defer these to later. But how do we do this?</p> <h2><a name="a_common_requirement"></a>A common requirement</h2> <p>Many applications set up variables on load-time:</p> <pre class="prettyprint">package MyApp; use Dancer2; my $dsn = config-&gt;{'dsn'}; my $schema = MyApp::Schema-&gt;connect($dsn); ...</pre> <p><i>(If you're using the <a href="https://metacpan.org/module/Dancer2::Plugin::Database">Dancer2::Plugin::Database</a>, a similar thing will happen behind the scenes.</i></p> <p>The problem we have with this is that it requires the information to be available in the configuration (accessed via the <code>config</code> keyword) before loading the application.</p> <pre class="prettyprint">use MyApp; # config() will be called</pre> <p>What happens when we want to set up the variables beforehand?</p> <p><i>I can do that</i>, you think to yourself. Here's the code:</p> <pre class="prettyprint">use Dancer2; # for config() keyword use MyApp; config-&gt;{'dsn'} = $new_dsn; # too late, hot plate!</pre> <p>Nope. Not going to work. When you call <code>use MyApp</code>, it will already use the <code>config</code> keyword to get the DSN.</p> <p>Alright, so you decide to change the configuration before you load the second application. Let's try that.</p> <pre class="prettyprint">use Dancer2; config-&gt;{'dsn'} = $new_dsn; use MyApp;</pre> <p>But that's not going to work, because <code>use</code> is compile-time, not run-time. The order is actually as following:</p> <pre class="prettyprint">use Dancer2; # happens first config-&gt;{'dsn'} = $new_dsn; # happens last use MyApp; # happens right after "use Dancer2"</pre> <p>You might think you could get around this with <code>BEGIN</code> by forcing the changes to happen before it loads the application:</p> <pre class="prettyprint">BEGIN { use Dancer2; config-&gt;{'dsn'} = $new_dsn; use MyApp; }</pre> <p>Sure. That will control the order of events by forcing the <code>config</code> statement to get called at compile-time, and because it's one line before the <code>use MyApp</code> line, it will be called before it. Oh wait...</p> <p>Now you've hit a major design issue with <a href="https://metacpan.org/module/Dancer2">Dancer2</a>. We no longer play with globals because globals are evil. This means that as soon as you called <code>use Dancer2</code>, we created an application based on your package name.</p> <p>When you change the configuration (using the <code>config</code> keyword), you change the configuration of the first application built. When you called <code>use MyApp</code>, <a href="https://metacpan.org/module/Dancer2">Dancer2</a> had created yet another application, solely for the <i>MyApp</i> package. This is fully intended and is a major leading design for Dancer2.</p> <p>But how do we still handle this reasonable requirement?</p> <h2><a name="moving_to_run_time"></a>Moving to run-time</h2> <p>Instead of trying to elevate the setup code to compile-time, why not just push the application setup to run-time instead?</p> <p>What if we loaded the code and imported it in runtime?</p> <pre class="prettyprint">package MyApp; use Dancer2; my $dsn; sub setup { $dsn = config-&gt;{'dsn'}; # do something with $dsn get '/' =&gt; sub {...}; }</pre> <p>Now we just call <code>setup</code> method when we want to start registering routes. It's a good start. Let's make it accept parameters:</p> <pre class="prettyprint">package MyApp; use Dancer2; my $dsn sub setup { my $opts = shift; $dsn = $opts-&gt;{'dsn'} || config-&gt;{'dsn'}; # do something with $dsn get '/' =&gt; sub {...}; }</pre> <p>Now we can call it from some other environment:</p> <pre class="prettyprint"># mytest.t: ... use MyApp; MyApp-&gt;setup({ dsn =&gt; 'dbi:SQLite:dbname=:memory:' });</pre> <p>We can even set up our own schema object if we put that functionality in our <code>setup</code> method:</p> <pre class="prettyprint">my $test_dsn = 'dbi:SQLite:dbname=t/corpus/test.sqlite'; my $schema = MyApp::Schema-&gt;connect($test_dsn); MyApp-&gt;setup({ schema =&gt; $schema }); $schema-&gt;deploy; ...</pre> <h2><a name="the_future"></a>The future</h2> <p>Since this is such a useful bootstrapping pattern, we are still considering adding this as a built-in feature in <a href="https://metacpan.org/module/Dancer2">Dancer2</a>. While you can roll your own this easily, we could envision making this even easier.</p> <p>Imagine having a <code>bootstrap</code> method which could be run before the routes are registered or when you actually call <code>to_app</code>, with optional bootstrap callbacks. It is possible and we might just blog about it in the future.</p> <p>Meanwhile, Dancer applications have just enough magic to do great things while still allowing you to make use of Perl to get around load-order and encapsulation issues.</p> <h2><a name="author"></a>Author</h2> <p>This article has been written by Sawyer X for the Perl Dancer Advent Calendar 2014.</p> <h2><a name="copyright"></a>Copyright</h2> <p>No copyright retained. Enjoy.</p> <p>2014 // Sawyer X <code>&lt;xsawyerx@cpan.org&gt;</code></p> </div> Hidden feature: Auto Pages http://advent.perldancer.org/2014/17 perl http://advent.perldancer.org/2014/17 Wed, 17 Dec 2014 00:00:00 -0000 <div class="pod-document"><h1><a name="hidden_feature__auto_pages"></a>Hidden feature: Auto Pages</h1> <p>One feature we love in Dancer (both <a href="https://metacpan.org/module/Dancer">Dancer 1</a> and <a href="https://metacpan.org/module/Dancer2">Dancer 2</a>) is the <i>AutoPage</i> feature.</p> <h2><a name="auto_what"></a>Auto-what?</h2> <p>Most websites provide web pages - multiple web pages. Many web pages will have a template and not just static content.</p> <p>Rendering a template is simple:</p> <pre class="prettyprint">get '/users/view' =&gt; sub { template 'view' =&gt; {...}; };</pre> <p>Assuming we have over 40 different pages, this becomes an arduous task of writing endpoints for each template, then keeping those up-to-date and continuing to add more.</p> <p>If only. If only someone would have come up with a feature that allowed automatically rendering templates by path. If only someone named <b>David Precious</b>, who is now handling the absurd responsibility of fatherhood while leaving <b>Sawyer X</b> to handle the <a href="http://advent.perldancer.org">Dancer Advent Calendar</a> all on his own, would have that idea and have already implemented it in Dancer 1, thus having it available from the early days of Dancer 2... oh wait, he did!</p> <h2><a name="how"></a>How</h2> <p><i>AutoPage</i> is a simple feature that you would love. Turning it on is as simple as:</p> <pre class="prettyprint">set auto_page =&gt; 1;</pre> <p>or in your configuration file:</p> <pre class="prettyprint">auto_page: 1</pre> <p>Dancer will take care of the rest.</p> <p>At this point, you might be wondering what it really does.</p> <h2><a name="behind_the_scenes"></a>Behind the scenes</h2> <p>What <i>AutoPage</i> does is very simple: when a request was not served by a static file or by a user defined route, it looks for a template that matches the path. If it finds one, it renders it.</p> <p>This means that the request <code>/users/edit</code> will first try to match a file, failing that it will try to match a route, and then, if still unsuccessful, it will go to <i>AutoPage</i>. <i>AutoPage</i> will search for a template under <code>views/users/</code> named <code>edit.tt</code>, assuming your <i>views</i> directory is <code>views</code> and your templating engine default extension is <code>.tt</code>.</p> <p><i>AutoPage</i> will adhere to your <code>views</code> and your templating system extension, so if those change, it will still work. It will also not render the layouts themselves, so you don't need to worry about someone being a smart-ass.</p> <h2><a name="another_reason_it_s_awesome"></a>Another reason it's awesome</h2> <p>By fully rendering a template, not just statically serving it, you have the full range of request variables. That means that any code in your templates that requires variables (or callbacks) will work:</p> <pre class="prettyprint"># in layout/main.tt: Served by [% dancer_version %]</pre> <p>This will work just fine. But what about variables we're adding in our code using the <code>before_template_render</code> hook?</p> <pre class="prettyprint"># in MyApp.pm: use Time::HiRes 'time'; hook before_template_render =&gt; sub { my $tokens = shift; $tokens-&gt;{'timestamp'} = time; }; # in users/edit.tt: Request timestamp: [% timestamp %]</pre> <p>Why would you put the timestamp there? I don't know. It's yet another contrived example that shows how you can add variables that will be accessible to the template rendered by <i>AutoPage</i>.</p> <h2><a name="conclusion"></a>Conclusion</h2> <p>The <i>AutoPage</i> feature is probably one of the nicest subtle features in Dancer. We don't hide it, but we also don't make it abundantly clear to users how awesome it is and how you most likely want to use it.</p> <p>At the end of the day, this feature also serves as yet another reason to buy David Precious a drink, which will finally force him to come to some public Perl event. This is all part of our secret plan.</p> <h2><a name="author"></a>Author</h2> <p>This article has been written by Sawyer X for the Perl Dancer Advent Calendar 2014.</p> <h2><a name="copyright"></a>Copyright</h2> <p>No copyright retained. Enjoy.</p> <p>2014 // Sawyer X <code>&lt;xsawyerx@cpan.org&gt;</code></p> </div> Command line dancing http://advent.perldancer.org/2014/16 perl http://advent.perldancer.org/2014/16 Tue, 16 Dec 2014 00:00:00 -0000 <div class="pod-document"><h1><a name="command_line_dancing"></a>Command line dancing</h1> <p>Some of the changes <a href="https://metacpan.org/module/Dancer2">Dancer2</a> has introduced were the removal of all import tags:</p> <pre class="prettyprint">use Dancer ':syntax'; # use Dancer2; use Dancer ':script'; # use Dancer2; use Dancer ':tests'; # use Dancer2;</pre> <p>Now you simply call <code>use Dancer2</code> for all of these. It will create an application and provide keywords. If you want to create a <a href="https://metacpan.org/module/PSGI">PSGI</a> application from it, simply call <code>to_app</code> on your class. Otherwise, it doesn't get in the way.</p> <h2><a name="but_i_need_it"></a>But I need it</h2> <p>While the last paragraph actually summed up this entire article, it probably wasn't very clear.</p> <p>A useful feature of going through Dancer itself is that it will read the configuration files, parse them, understand them, and even create objects lazily using them.</p> <p>People often write scripts that have to then duplicate what Dancer does. It's quite understandable that people wish to be able to use Dancer in their scripts to have access to the configuration and the generated objects.</p> <h2><a name="reaching_the_config"></a>Reaching the config</h2> <p>By importing <a href="https://metacpan.org/module/Dancer2">Dancer2</a> in your command line scripts, you have full access to the configuration using the imported keywords:</p> <pre class="prettyprint"># myscript.pl: use Dancer2; # strict &amp;&amp; warnings included # this works: my $appname = config-&gt;{'appname'}; # and so does this: my $appname = app-&gt;name;</pre> <p>You shouldn't worry about <i>myscript.pl</i> becoming an app and starting a web server. Yes, as soon as it hits <code>use Dancer2</code> it will create a Dancer2 application behind the scenes, and that app can be run at any given point in time by calling <code>dance</code> or the preferred method <code>to_app</code> on it, but unless you actually call those, this app will simply be created in the background.</p> <p>You will still be able to access all the configuration from it without having to run it under a web environment.</p> <h2><a name="small_example"></a>Small example</h2> <p>One small example of wanting to access the configurations from a command line script would be to run some sort of import to or export from a database.</p> <p>Being able to access the configuration file and having the classes that are automatically inflated from that configuration file is mighty useful.</p> <pre class="prettyprint"># myscript.pl: use Dancer2 use Dancer2::Plugin::Database; my $user_id = $ARGV[0] or die "$0 &lt;USER ID&gt;\n"; $user_id =~ /^[0-9]+$/ or die "User ID must be a positive number\n"; my $sth = database-&gt;prepare( 'select * from users where id = ?' ); $sth-&gt;execute($user_id); ...</pre> <h2><a name="conclusion"></a>Conclusion</h2> <p>If you want to create command line applications that use the Dancer2 structures, you can simply load Dancer2 and use the keywords it provides you.</p> <p>What does this give you access to?</p> <ul> <li><a name="item_Dancer_keywords"></a><b>Dancer keywords</b> <p><code>config</code> probably being the most helpful one, but <code>template</code> will also be available just like other engine-related keywords are - explained below under <i>Engines</i>.</p> </li> <li><a name="item_Keywords_created_by_plugins"></a><b>Keywords created by plugins</b> <p>This means you can make use of any functionality they provide outside of a request.</p> </li> <li><a name="item_Engines"></a><b>Engines</b> <p>This means you can use the facilities your web application has when logging events (using <code>debug</code>, <code>warning</code>, and <code>error</code>), accessing or setting session information, serializing, and even rendering templates (using the <code>template</code> keyword).</p> </li> </ul> <h2><a name="author"></a>Author</h2> <p>This article has been written by Sawyer X for the Perl Dancer Advent Calendar 2014.</p> <h2><a name="copyright"></a>Copyright</h2> <p>No copyright retained. Enjoy.</p> <p>2014 // Sawyer X <code>&lt;xsawyerx@cpan.org&gt;</code></p> </div> Outreach Program for Women (OPW) and Dancer http://advent.perldancer.org/2014/15 perl http://advent.perldancer.org/2014/15 Mon, 15 Dec 2014 00:00:00 -0000 <div class="pod-document"><h1><a name="outreach_program_for_women__opw__and_dancer"></a>Outreach Program for Women (OPW) and Dancer</h1> <p>The <a href="https://opw.gnome.org">Outreach Program for Women</a> (OPW) helps women work on Open Source and Free Software applications while receiving a salary and having a mentor by their side.</p> <p><a href="http://www.perlfoundation.org/">The Perl Foundation</a> (TPF) is <a href="http://www.perlfoundation.org/outreach_program_for_women">participating</a> this year again, and this year we have the pleasure of participating with Dancer!</p> <h2><a name="our_participant"></a>Our participant</h2> <p>Our applicant, Snigdha Dagar, has been accepted to work on <a href="https://metacpan.org/module/Dancer2">Dancer2</a>'s documentation overhaul!</p> <p>She had already contributed the first draft of the <a href="https://metacpan.org/module/Dancer2::Manual::Migration">Dancer2::Manual::Migration</a> document to help users with upgrading from <a href="https://metacpan.org/module/Dancer">Dancer</a> to <a href="https://metacpan.org/module/Dancer2">Dancer2</a>.</p> <h2><a name="the_documentation_overhaul"></a>The documentation overhaul</h2> <p>The documentation overhaul was deemed a crucial component in making the upgrading from Dancer 1 to Dancer 2 more attainable.</p> <p>The current documentation has been copied over from Dancer 1, but is not completely compatible. Some things have changed and many features have been added. Unfortunately in the frenzy of continuing upgrading Dancer and its abilities, along with important improvements, we lack the tuits to resolve the outstanding problems with the current documentation.</p> <p>Starting from scratch would be a tremendous amount of work, and whether it will be less or more work than going through the current documentation with a fine comb and sorting it out still does not resolve the problem with the lack of personnel for this task.</p> <p>What we need is human resources - and not the department. :)</p> <h2><a name="there_is_a_plan"></a>There is a plan</h2> <p>Snigdha has provided a plan for overhauling the documentation, which includes researching other FOSS projects, provide introductory material, How-to guides, and cohesiveness of the overall documentation.</p> <p>Her work will help resolve the documentation problems, assure consistency, accuracy, and above all, a well structured, helpful documentation for such an important project.</p> <h2><a name="there_will_be_updates"></a>There will be updates</h2> <p>We are excited and delighted to have her help in these upcoming months and we will be providing updates on the progress made.</p> <p>We are certain Snigdha would appreciate any guidance and assistance from the community. Feel free to suggest corrections, improvements, what to focus on, what to not focus on, and how to assure the success of her work and the project.</p> <h2><a name="author"></a>Author</h2> <p>This article has been written by Sawyer X for the Perl Dancer Advent Calendar 2014.</p> <h2><a name="copyright"></a>Copyright</h2> <p>No copyright retained. Enjoy.</p> <p>2014 // Sawyer X <code>&lt;xsawyerx@cpan.org&gt;</code></p> </div> Writing plugins for Dancer2 http://advent.perldancer.org/2014/14 perl http://advent.perldancer.org/2014/14 Sun, 14 Dec 2014 00:00:00 -0000 <div class="pod-document"><h1><a name="writing_plugins_for_dancer2"></a>Writing plugins for Dancer2</h1> <p>Plugins provide you with additional keywords to decouple predefined behavior to make it easier on you so you won't need to implement the same thing over and over again.</p> <p>Let me show you how simple it is to write a plugin of your own.</p> <p><i>(This explains the current API to plugins. Refer to <a href="https://metacpan.org/module/Dancer2::Plugin">Dancer2::Plugin</a> for up-to-date documentation.)</i></p> <h2><a name="a_plugin_that_does_nothing__so_far_"></a>A plugin that does nothing (so far)</h2> <p>All you need to do is use <a href="https://metacpan.org/module/Dancer2::Plugin">Dancer2::Plugin</a> and that will provide you with all the keywords you need to write the plugin.</p> <pre class="prettyprint">package Dancer2::Plugin::Kitteh; use Dancer2::Plugin; # we do nothing, just like most cats do register_plugin; 1;</pre> <h2><a name="introducing_keywords"></a>Introducing keywords</h2> <p>You can introduce new keywords the application will receive when it uses your plugin using the <code>register</code> keyword:</p> <pre class="prettyprint">register meow =&gt; sub { my ( $dsl ) = plugin_args(@_); my $app = $dsl-&gt;app; };</pre> <p>This is how we introduce the <code>meow</code> keyword to the user.</p> <p>We use <code>plugin_args</code> to make sure we get the plugin arguments. This is for compatibility.</p> <p>The keyword receives an object which represents the DSL object the app is connected to. You can use it in order to access the Dancer2 core application connected to the user's scope.</p> <p>We can also control whether a keyword is <i>app-global</i>, meaning it can be called from anywhere in an app or only from a route, which means during a request:</p> <pre class="prettyprint">register meow =&gt; sub { debug 'Meow!'; }, { is_global =&gt; 0 };</pre> <h2><a name="route_decorators"></a>Route decorators</h2> <p>Some plugins generate routes from other routes, which makes them look a little bit like route decorators. Take <a href="https://metacpan.org/module/Dancer2::Plugin::Auth::Tiny">Dancer2::Plugin::Auth::Tiny</a> for example:</p> <pre class="prettyprint">get '/private' =&gt; needs login =&gt; sub { ... };</pre> <p>The way it works is by taking the route sub as a parameter and creating its own route which calls it. We can do the same.</p> <pre class="prettyprint">package Dancer2::Plugin::OnTuesday; # ABSTRACT: Make sure a route only works on Tuesday use Dancer2::Plugin; register on_tuesday =&gt; sub { my ( $dsl, $route_sub, @args ) = plugin_args(@_); my $day = (localtime)[6]; $day == 2 or return pass; return $route_sub-&gt;( $dsl, @args ); }; register_plugin;</pre> <p>Now we can use this plugin as such:</p> <pre class="prettyprint">package MyApp; use Dancer2; use Dancer2::Plugin::OnTuesday; get '/' =&gt; on_tuesday =&gt; sub { ... }; # every other day get '/' =&gt; sub { ... };</pre> <h2><a name="reading_the_configuration"></a>Reading the configuration</h2> <p>While a user can change the configuration using both the configuration file and the <code>set</code> keyword, we need a single source for all configuration options for our plugin. This is handled automatically using the <code>plugin_setting</code> keyword:</p> <pre class="prettyprint">register meow =&gt; sub { my $dsl = shift; my $vol = plugin_setting-&gt;{'volume'} || 3; };</pre> <h2><a name="extra_tricks"></a>Extra tricks</h2> <p>There are a few additional tricks available which weren't covered here, such as running code on import, registering additional hooks, and executing hooks. They are all documented in <a href="https://metacpan.org/module/Dancer2::Plugin">Dancer2::Plugin</a>.</p> <h2><a name="conclusion"></a>Conclusion</h2> <p>The plugin infrastructure in the upgrade from Dancer 1 to Dancer 2 has been problematic. We've tried various methods to allow plugins to coexist, then to specify how they work, and finally to provide a proper shim layer to enable working with both smealessly.</p> <p>Unfortunately all of these methods had problems and we resulted in separating the plugins. This does not mean that writing a plugin for Dancer 2 is difficult. In fact it's fairly simple.</p> <p>We're working on making them even more comfortable and remove any lingering problems, but as you can see they are already easy to write.</p> <h2><a name="author"></a>Author</h2> <p>This article has been written by Sawyer X for the Perl Dancer Advent Calendar 2014.</p> <h2><a name="copyright"></a>Copyright</h2> <p>No copyright retained. Enjoy.</p> <p>2014 // Sawyer X <code>&lt;xsawyerx@cpan.org&gt;</code></p> </div> The test core: How we test in Dancer2 core http://advent.perldancer.org/2014/13 perl http://advent.perldancer.org/2014/13 Sat, 13 Dec 2014 00:00:00 -0000 <div class="pod-document"><h1><a name="the_test_core__how_we_test_in_dancer2_core"></a>The test core: How we test in Dancer2 core</h1> <p>The Dancer2 core test suite is improving significantly. We have made vast changes in how we <a href="http://advent.perldancer.org/2014/8">sort our tests</a> and we now use <a href="https://metacpan.org/module/Plack::Test">Plack::Test</a> to <a href="http://advent.perldancer.org/12">write tests</a>.</p> <p>If you're interested in contributing, we would not only praise you for years to come, but also shower you and your family with gifts. But before you can contribute tests, it's important you understand our practices and conventions when writing tests.</p> <h2><a name="basics"></a>Basics</h2> <p>There are a few guidelines for the tests which we try to maintain when writing tests:</p> <ul> <li><a name="item__code_use_ok__code__for_testing_classes_load"></a><b><code>use_ok</code> for testing classes load</b> </li> <li><a name="item_Declare_the_number_of_tests"></a><b>Declare the number of tests</b> </li> <li><a name="item_Use__i_subtests__i__or_code_blocks_for_scoping"></a><b>Use <i>subtests</i> or code blocks for scoping</b> </li> <li><a name="item_Try_to_reach_as_much_coverage_as_possible"></a><b>Try to reach as much coverage as possible</b> </li> <li><a name="item_Reduce_convenience_modules_and_don_t_make_them_mandatory"></a><b>Reduce convenience modules and don't make them mandatory</b> </li> <li><a name="item_Thus__skip_if_those_modules_aren_t_available"></a><b>Thus, skip if those modules aren't available</b> </li> <li><a name="item_Provide_each_test_with_a_test_name___no_empty_tests"></a><b>Provide each test with a test name - no empty tests</b> </li> </ul> <h2><a name="testing_classes"></a>Testing classes</h2> <p>The main tests are actually for classes. As <a href="http://advent.perldancer.org/2014/8">explained</a>, we store these tests in <i>t/classes/</i>, under a directory for each class we test.</p> <p>Let's take a look at the <a href="https://metacpan.org/module/Dancer2::Core::Factory">Dancer2::Core::Factory</a> object tests. Since it simply creates engine objects and contains only a single method, the test is rather simple.</p> <p>Boilerplate:</p> <pre class="prettyprint">use strict; use warnings; use Test::More tests =&gt; 5;</pre> <p>As explained, this is not a fast and hard rule, but we prefer to count the number of tests we have, to make sure the test doesn't miss a test someone has accidentally put on a condition.</p> <p>We test loading:</p> <pre class="prettyprint">use_ok('Dancer2::Core::Factory');</pre> <p>Then we test the object itself:</p> <pre class="prettyprint">my $factory = Dancer2::Core::Factory-&gt;new; isa_ok( $factory, 'Dancer2::Core::Factory' ); can_ok( $factory, 'create' );</pre> <p>You might notice we pick descriptive names. We try to avoid variables names <code>$f</code> in our core code as well as in our tests.</p> <p>Now we can test the <code>create</code> method, which is actually a class method, so holding the factory object is not required. We generally avoid class methods, but in this class we're a bit more lax about it:</p> <pre class="prettyprint">my $template = Dancer2::Core::Factory-&gt;create( 'template', 'template_toolkit', layout =&gt; 'mylayout' ); isa_ok( $template, 'Dancer2::Template::TemplateToolkit' ); is( $template-&gt;{'layout'}, 'mylayout', 'Correct layout set in the template' );</pre> <p>That's it. Pretty simple.</p> <h2><a name="testing_dsl"></a>Testing DSL</h2> <p>In order to test DSL keywords, we need to have a valid application who uses <code>Dancer2</code> and then try its DSL keywords. That's actually simple enough.</p> <p>The test <i>t/dsl/app.t</i> provides our test for the <code>app</code> keyword, which returns the current <a href="https://metacpan.org/module/Dancer2::Core::App">Dancer2::Core::App</a> a package is using.</p> <p>First we have our boilerplate:</p> <pre class="prettyprint">use strict; use warnings; use Test::More tests =&gt; 2; use Plack::Test; use HTTP::Request::Common;</pre> <p>Now we define an application in the code in its own scope so it doesn't interfere with the test itself, but be available to it:</p> <pre class="prettyprint">{ package App; use Dancer2; get '/' =&gt; sub { my $app = app; ::isa_ok( $app, 'Dancer2::Core::App' ); ::is( $app-&gt;name, 'App', 'Correct app name' ); }; }</pre> <p>This application uses <code>Dancer2</code> and thus receives the keywords. Since our test is written in the implicit <code>main</code> package, the double colon shorthand for <code>main::</code> class resolution allows it to call <code>::isa_ok</code> to reach the test's <code>isa_ok</code> function (provided by <a href="https://metacpan.org/module/Test::More">Test::More</a>) and <code>::is</code> allows it to reach the test's <code>is</code> function (also provided by <a href="https://metacpan.org/module/Test::More">Test::More</a>).</p> <p>This test checks that if you reach the main path, it will call the <code>app</code> keyword and check it received an instance, that it is the right instance, and that the name was even set correctly.</p> <p>We still need to write the code to reach it:</p> <pre class="prettyprint">Plack::Test-&gt;create( App-&gt;to_app )-&gt;request( GET '/' );</pre> <p>There.</p> <p>Often we return values from a web request, but in this specific case we're really interested in an object which the route receives and doing it by sending it back as a response would just be overengineering.</p> <h2><a name="what_about_external_files"></a>What about external files?</h2> <p>Some tests might require some additional files to work. Perhaps you're checking the side-effect of reading from the configuration file or a piece of code that works with the file system.</p> <p>One example is <i>t/issues/gh-639</i> which has additional directories, each have their own <i>config.yml</i> and test file to check against different configuration files as part of a general issue opened.</p> <h2><a name="conclusions"></a>Conclusions</h2> <p>Following the guidelines you will be able to help us improve our tests, move our old ones, and provide new tests for issues you or others might open.</p> <p>We're very interested in having a good test coverage and providing reliable behavior. Tests are a major component of it and we would always be more than happy to receive more help in that field.</p> <p>Next time you open an issue, consider writing a test for it. If you're not sure how, please contact us. We would love to help. :)</p> <h2><a name="author"></a>Author</h2> <p>This article has been written by Sawyer X for the Perl Dancer Advent Calendar 2014.</p> <h2><a name="copyright"></a>Copyright</h2> <p>No copyright retained. Enjoy.</p> <p>2014 // Sawyer X <code>&lt;xsawyerx@cpan.org&gt;</code></p> </div> A test to remember: testing your web application http://advent.perldancer.org/2014/12 perl http://advent.perldancer.org/2014/12 Fri, 12 Dec 2014 00:00:00 -0000 <div class="pod-document"><h1><a name="a_test_to_remember__testing_your_web_application"></a>A test to remember: testing your web application</h1> <p>Perl has an extensive culture of testing which originated in the Perl language itself, carrying a staggering number of tests for its own features.</p> <p>We write a multitude of tests for every single bit in our distributions and we test them across different platforms, setups, versions of modules and applications, and even on different versions of perl[1] itself.</p> <p>For non-Perl regulars, you might think I'm exaggerating. Oh no, I'm not. Check out <a href="http://cpants.cpanauthors.org/">CPANTS, our CPAN Testing Service</a> for more details on our amazing free Perl testing service.</p> <p>It's safe to say: we love tests.</p> <p><i>[1] We use <b>Perl</b> (uppercase) for the language and <b>perl</b> (lowercase) for the interpreter</i>.</p> <h2><a name="but_in_the_land_of_web___"></a>But in the land of web...</h2> <p>In the world of web, testing is trickier. A web application runs on a web server. That is usually an application written in another language (often C or C++), a long-running process with lots of configuration files and behavior that is hard to decouple.</p> <p><a href="https://metacpan.org/module/LWP">LWP</a> Gave us <a href="https://metacpan.org/module/LWP::UserAgent">LWP::UserAgent</a> which gave us <a href="https://metacpan.org/module/WWW::Mechanize">WWW::Mechanize</a>. As long as we had a web server running, we could just write some tests (turned on with an environment variable) that will make requests and test the results, producing proper TAP. There's even <a href="https://metacpan.org/module/Test::WWW::Mechanize">Test::WWW::Mechanize</a> to make it smoother.</p> <p>However, these don't handle the problem with testing in a web environment: the web server itself.</p> <h2><a name="enter_psgi"></a>Enter PSGI</h2> <p>Any web application built on a <a href="https://metacpan.org/module/PSGI">PSGI</a> framework allows to approach the problem from an entirely different perspective.</p> <p><a href="https://metacpan.org/module/PSGI">PSGI</a> applications (such as those created with Dancer) are actually code references fed to a web server. This means that as long as you create the proper request (specified by the <a href="https://metacpan.org/module/PSGI">PSGI</a> docs), you can call that application code reference with it and receive a response. No server is actually necessary. The server is merely there to create a proper request.</p> <p><a href="https://metacpan.org/module/Plack">Plack</a>, the set of utilities for <a href="https://metacpan.org/module/PSGI">PSGI</a> applications, comes with a special module to help this process: <a href="https://metacpan.org/module/Plack::Test">Plack::Test</a>.</p> <p>What <a href="https://metacpan.org/module/Plack::Test">Plack::Test</a> does is truly fantastic: it receives a common web request (using standard <a href="https://metacpan.org/module/HTTP::Request">HTTP::Request</a> objects), fakes a web server in order to create a proper PSGI request, and sends it to the web application. When the web application returns a PSGI response (which Dancer applications do), it will then convert it to a common web response (as a standard <a href="https://metacpan.org/module/HTTP::Response">HTTP::Response</a> object).</p> <p>This allows you to then create requests in your test, create the code reference for your web application, call them, and receive a response object, which you can then test to your heart's delight.</p> <p>Let's take a look at a few examples.</p> <h2><a name="basic_example"></a>Basic example</h2> <p>Assuming we have a web application:</p> <pre class="prettyprint"># MyApp.pm package MyApp; use Dancer2; get '/' =&gt; sub {'OK'}; 1;</pre> <p>Now we want to write a test for it. Let's create <i>base.t</i>:</p> <pre class="prettyprint"># base.t use strict; use warnings; use Test::More tests =&gt; 2; use Plack::Test; use HTTP::Request; use MyApp;</pre> <p>Now let's create a coderef for our application using the <code>to_app</code> keyword:</p> <pre class="prettyprint">my $app = MyApp-&gt;to_app;</pre> <p>That was easy. Now let's create a test object from <a href="https://metacpan.org/module/Plack::Test">Plack::Test</a> for our application:</p> <pre class="prettyprint">my $test = Plack::Test-&gt;create($app);</pre> <p>Now we can call requests on it. We'll create our first request object and send it to our test object to receive a response:</p> <pre class="prettyprint">my $request = HTTP::Request-&gt;new( GET =&gt; '/' ); my $response = $test-&gt;request($request);</pre> <p>We can now test it:</p> <pre class="prettyprint">ok( $response-&gt;is_success, '[GET /] Successful request' ); is( $response-&gt;content, 'OK', '[GET /] Correct content' );</pre> <h2><a name="putting_it_all_together"></a>Putting it all together</h2> <p>If we put all our code together and remove some excess, we can come up with the following test file:</p> <pre class="prettyprint"># base.t use strict; use warnings; use Test::More; use Plack::Test; use HTTP::Request::Common; use MyApp; my $test = Plack::Test-&gt;create( MyApp-&gt;to_app ); my $response = $test-&gt;request( GET '/' ); ok( $response-&gt;is_success, '[GET /] Successful request' ); is( $response-&gt;content, 'OK', '[GET /] Correct content' ); done_testing();</pre> <p>It might seem like too much boilerplate, but there's enough modules to help you reduce that.</p> <h2><a name="subtests"></a>Subtests</h2> <p>We also separate our tests using <a href="https://metacpan.org/module/Test::More">Test::More</a>'s <code>subtest</code> functionality, thus creating multiple self-contained tests that don't overwrite each other.</p> <p>Assuming we have a different app that has two states we want to test.</p> <pre class="prettyprint"># MyApp.pm package MyApp; use Dancer2; set serializer =&gt; 'JSON'; get '/' =&gt; sub { my $user = param('user'); $user and return { user =&gt; $user }; return {}; }; 1;</pre> <p>This is a very contrived example of a route that checks for a user parameter. If it exists, it returns it in a hash with the key 'user'. If not, it returns an empty hash. Useful? Probably not, but a good example for having two tests.</p> <pre class="prettyprint"># param.t use strict; use warnings; use Test::More; use Plack::Test; use HTTP::Request::Common; use MyApp; my $test = Plack::Test-&gt;create( MyApp-&gt;to_app ); subtest 'A empty request' =&gt; sub { my $res = $test-&gt;request( GET '/' ); ok( $res-&gt;is_success, 'Successful request' ); is( $res-&gt;content '{}', 'Empty response back' ); }; subtest 'Request with user' =&gt; sub { my $res = $test-&gt;request( GET '/?user=sawyer_x' ); ok( $res-&gt;is_success, 'Successful request' ); is( $res-&gt;content '{"user":"sawyer_x"}', 'Empty response back' ); }; done_testing();</pre> <p>We could, of course, use <a href="https://metacpan.org/module/JSON">JSON</a> to decode and check for a proper object, which would be the right thing for a bigger response. Did I say <i>contrived</i> yet? :)</p> <h2><a name="cookies"></a>Cookies</h2> <p>One interesting requirement is being able to handle cookies, mostly used for maintaining sessions. We can use <a href="https://metacpan.org/module/Test::WWW::Mechanize::PSGI">Test::WWW::Mechanize::PSGI</a> or <a href="https://metacpan.org/module/LWP::Protocol::PSGI">LWP::Protocol::PSGI</a>, I personally prefer using <a href="https://metacpan.org/module/HTTP::Cookies">HTTP::Cookies</a> directly.</p> <p>Taking the previous test, assuming it actually creates and uses cookies for sessions, all we would need is the following:</p> <pre class="prettyprint"># ... all the use statements use HTTP::Cookies; my $jar = HTTP::Cookies-&gt;new; my $test = Plack::Test-&gt;create( MyApp-&gt;to_app ); my $host = 'http://127.0.0.1'; subtest 'A empty request' =&gt; sub { my $res = $test-&gt;request( GET "$host/" ); ok( $res-&gt;is_success, 'Successful request' ); is( $res-&gt;content '{}', 'Empty response back' ); $jar-&gt;extract_cookies($res); ok( $jar-&gt;as_string, 'We have cookies!' ); }; subtest 'Request with user' =&gt; sub { my $req = GET "$host/?user=sawyer_x"; $jar-&gt;add_cookie_header($req); my $res = $test-&gt;request($req); ok( $res-&gt;is_success, 'Successful request' ); is( $res-&gt;content '{"user":"sawyer_x"}', 'Empty response back' ); $jar-&gt;extract_cookies($res); ok( ! $jar-&gt;as_string, 'All cookies deleted' ); }; done_testing();</pre> <p>Here we create a cookie jar, make sure all our requests and responses work with it, and we can even check for existing cookies, as well as cookies that were deleted by the response, since <a href="https://metacpan.org/module/HTTP::Cookies">HTTP::Cookies</a> will understand a delete request (by setting an older time) and delete it.</p> <p>You will notice that we use a full domain. This is because <a href="https://metacpan.org/module/HTTP::Cookies">HTTP::Cookies</a> needs the entire URL (including the scheme part) to make the cookies work.</p> <h2><a name="accessing_the_configuration_file"></a>Accessing the configuration file</h2> <p>By importing <a href="https://metacpan.org/module/Dancer2">Dancer2</a> in your command line scripts, you have full access to the configuration using the imported keywords:</p> <pre class="prettyprint">use strict; use warnings; use Test::More; use Plack::Test; use HTTP::Request::Common; use MyApp; use Dancer2; my $appname = config-&gt;{'appname'}; diag "Testing $appname"; # ...</pre> <p>In this example we use the <code>config</code> keyword to access the configuration. That's all you have to do if you want to access it as part of your test.</p> <h2><a name="testing_environment"></a>Testing environment</h2> <p>You can also set your own environment file for testing, such as <code>environments/testing.yml</code> and then load it in your test script:</p> <pre class="prettyprint">BEGIN { $ENV{'DANCER_ENV'} = 'testing' } # ...</pre> <p>Now you can insert your own configurations.</p> <h2><a name="setup_method"></a>Setup method</h2> <p>My current favorite method for dynamically handling onfigurations in my <a href="https://metacpan.org/module/Dancer2">Dancer2</a> applications is by having a <code>setup</code> method. When loading my applications in my handlers, I call that method, and it then checks the configuration for variables.</p> <p>This allows me to tweak and change the configuration before calling the <code>setup</code> method, thus letting me bootstrap my own changes, such as in testing scripts.</p> <p>A separate article about this trick just might appear on the Advent Calendar this year.</p> <h2><a name="where_are_the_test_helpers"></a>Where are the test helpers?</h2> <p>Both Dancer 1 and 2 have <a href="https://metacpan.org/module/Dancer::Test">Dancer::Test</a> and <a href="https://metacpan.org/module/Dancer2::Test">Dancer2::Test</a>, respectively, but in <a href="https://metacpan.org/module/Dancer2">Dancer2</a> it is currently not recommended.</p> <p>The reason is that, because they weren't written with PSGI in mind, they are bending over backwards in order to fake the request, run it against a fake dispatcher, and then return a fake response.</p> <p>At the end of the day, it isn't only buggy and took a lot of our time and efforts into maintaining it, but it is also counter-intuitive.</p> <p>We might reinstate it later, once we've redesigned it to simply be a helper layer on top of <a href="https://metacpan.org/module/Plack::Test">Plack::Test</a>.</p> <p>For now, we suggest to avoid it and go directly for <a href="https://metacpan.org/module/Plack::Test">Plack::Test</a>.</p> <h2><a name="conclusion"></a>Conclusion</h2> <p>Writing tests is a lot of fun and they help us make sure our applications work the way we want them to work. They help flesh out features, APIs, and maintain their correctness throughout changes, big and small.</p> <p>Writing tests for web application used to be difficult, but now, with the magic of <a href="https://metacpan.org/module/PSGI">PSGI</a>, it is simple and straight-forward.</p> <p>You can read more about testing in <a href="https://metacpan.org/module/Dancer2::Manual::Testing">Dancer2::Manual::Testing</a>.</p> <p>Our next article will cover how we write tests ourselves in the <a href="https://metacpan.org/module/Dancer2">Dancer2</a> core.</p> <h2><a name="author"></a>Author</h2> <p>This article has been written by Sawyer X for the Perl Dancer Advent Calendar 2014.</p> <h2><a name="copyright"></a>Copyright</h2> <p>No copyright retained. Enjoy.</p> <p>2014 // Sawyer X <code>&lt;xsawyerx@cpan.org&gt;</code></p> </div> Serial Serializer - making API writing easier http://advent.perldancer.org/2014/11 perl http://advent.perldancer.org/2014/11 Thu, 11 Dec 2014 00:00:00 -0000 <div class="pod-document"><h1><a name="serial_serializer___making_api_writing_easier"></a>Serial Serializer - making API writing easier</h1> <p>One of Dancer's engines is the <b>serializer</b>, which helps you with writing APIs.</p> <p>Serializers essentially do two things:</p> <ul> <li><a name="item_Deserialize_incoming_requests"></a><b>Deserialize incoming requests</b> <p>When a user makes a request with serialized input, the serializer automatically deserializes it into actual input parameters.</p> </li> <li><a name="item_Serialize_outgoing_responses"></a><b>Serialize outgoing responses</b> <p>When you return a data structure from a route, it will automatically serialize it for you before returning it to the user.</p> </li> </ul> <h2><a name="configuring"></a>Configuring</h2> <p>In order to configure a serializer, you just need to pick which format you want for encoding/decoding (from the available Serializer namespace - <code>Dancer::Serializer</code> for Dancer 1 and <code>Dancer2::Serializer</code> for Dancer2) and set it up using the <code>serializer</code> configuration keyword.</p> <p>It's recommended to explicitly add it in the actual code instead of the configuration file so it doesn't apply automatically to every app that reads the configuration file (unless that's what you want):</p> <pre class="prettyprint">package MyApp; use Dancer2; set serializer =&gt; 'JSON'; # Dancer2::Serializer::JSON ...</pre> <h2><a name="using"></a>Using</h2> <p>Now that we have a serializer set up, we can just return data structures:</p> <pre class="prettyprint">get '/' =&gt; sub { return { resources =&gt; \%resources }; };</pre> <p>When we return this data structure, it will automatically be serialized into JSON. No other code is necessary.</p> <p>We also now receive requests in JSON:</p> <pre class="prettyprint">post '/:entity/:id' =&gt; sub { my $entity = param('entity'); my $id = param('id'); # input which was sent serialized my $user = param('user'); ... };</pre> <p>We can now make a serialized request:</p> <pre class="prettyprint">$ curl -X POST http://ourdomain/person/16 -d '{"user":"sawyer_x"}'</pre> <p>It's all automatic.</p> <h2><a name="always_or_never"></a>Always or never</h2> <p>In previous versions of <a href="https://metacpan.org/module/Dancer2">Dancer2</a> (and in <a href="https://metacpan.org/module/Dancer">Dancer</a> 1), serializers were only used when the data is a reference.</p> <p>There were some issues with that:</p> <ul> <li><a name="item_Unclear_behavior"></a><b>Unclear behavior</b> <p>You could have mixed routes that return serialized and non-serialized content, which is a source for confusion and inconsistency.</p> <p>Now you simply handle this by providing a package that has a serializer and a package that renders content. You can then separate them to different mounting points using <a href="https://metacpan.org/module/Plack::Builder">Plack::Builder</a> as explained in a previous article and showed below.</p> </li> <li><a name="item_What_if_the_data_is_a_string_"></a><b>What if the data is a string?</b> <p>Some serializers actually handle strings. <a href="https://metacpan.org/module/Dancer2::Serializer::CBOR">Dancer2::Serializer::CBOR</a>, for example, can serialize strings. This previous ref-only behavior would render those serializers broken - not good.</p> </li> </ul> <p>Instead, now everything is sent to serializers. Bad requests receive warnings and errors.</p> <h2><a name="hooks"></a>Hooks</h2> <p>While we're still working on adding an error hook, you can already hook into the serializer with a <i>before</i> and <i>after</i>:</p> <pre class="prettyprint">hook before_serializer =&gt; sub {...}; hook after_serializer =&gt; sub {...};</pre> <h2><a name="app_specific_feature"></a>App-specific feature</h2> <p>Remember that serializers are engines. They affect a Dancer Application, which means that once you've set a serializer, <b>all</b> routes within that package will be serialized and deserialized. This is how the feature works.</p> <p>As suggested above, if you would like to have both, you need to create another application which will not be serialized.</p> <p>A common usage for this is an API providing serialized endpoints (and receiving serialized requests) and providing rendered pages.</p> <pre class="prettyprint"># MyApp.pm package MyApp; use Dancer2; # another useful feature: set auto_page =&gt; 1; get '/' =&gt; sub { template 'index' =&gt; {...} }; # MyApp/API.pm package MyApp::API; use Dancer2; set serializer =&gt; 'JSON'; # or any other serializer get '/' =&gt; sub { +{ resources =&gt; \%resources, ... } }; # user-specific routes, for example prefix =&gt; '/users' =&gt; sub { get '/view' =&gt; sub {...}; get '/view/:id' =&gt; sub {...}; put '/add' =&gt; sub {...}; # automatically deserialized params }; ...</pre> <p>Then those will be mounted together for a single app:</p> <pre class="prettyprint"># handler: app.pl: use MyApp; use MyApp::API; use Plack::Builder; builder { mount '/' =&gt; MyApp-&gt;to_app; mount '/api' =&gt; MyApp::API-&gt;to_app; };</pre> <p>There ya go!</p> <h2><a name="conclusion"></a>Conclusion</h2> <p>Serializers make it much easier to write API interfaces. We recommend using them in order to save yourself on typing. However, use caution knowing they will handle all input and all output and affect all routes in a package.</p> <h2><a name="author"></a>Author</h2> <p>This article has been written by Sawyer X for the Perl Dancer Advent Calendar 2014.</p> <h2><a name="copyright"></a>Copyright</h2> <p>No copyright retained. Enjoy.</p> <p>2014 // Sawyer X <code>&lt;xsawyerx@cpan.org&gt;</code></p> </div> What's in an appname? http://advent.perldancer.org/2014/10 perl http://advent.perldancer.org/2014/10 Wed, 10 Dec 2014 00:00:00 -0000 <div class="pod-document"><h1><a name="what_s_in_an_appname"></a>What's in an appname?</h1> <h2><a name="new_feature_in_dancer2__appname"></a>New feature in Dancer2: appname</h2> <p>One change we absolutely love is the <code>appname</code> import option, introduced in <a href="https://metacpan.org/module/Dancer2">Dancer2</a> 0.150000.</p> <h2><a name="what_s_a_dancer_app_again"></a>What's a Dancer App again?</h2> <p>It's worth repeating the explanation of what a Dancer2 application is, since this might confuse a developer with a <a href="https://metacpan.org/module/PSGI">PSGI</a> application.</p> <p>A Dancer2 App is simply a package containing routes and engines which receives a request and returns a response. The engines are not mandatory, but might be a template, a session, a logger, and a serializer.</p> <p>A PSGI application is a code reference which receives a request as a hash of environment variables (from a server using a <a href="https://metacpan.org/module/Plack">Plack</a> handler) and returns a proper PSGI response which could be an array reference or a code reference.</p> <h2><a name="too_many_apps_"></a>Too many apps!</h2> <p>As soon as you import <a href="https://metacpan.org/module/Dancer2">Dancer2</a> (by calling <code>use Dancer2</code>), you create a Dancer2 App. It will use your class name (defined by either the <code>package</code> function in Perl or the default in Perl: <code>main</code>) to define the Dancer2 App name. This is how Dancer2 will recognize your application.</p> <p>This introduces an interesting situation. If you wish to separate your App to multiple files, you're actually creating multiple applications.</p> <h2><a name="so_what"></a>So what?</h2> <p>This means that any engine defined in an application, because the application is a complete separate scope, will not be available to a different application:</p> <pre class="prettyprint">package MyApp::User { use Dancer2; set serializer =&gt; 'JSON'; get '/view' =&gt; sub {...}; } package MyApp::User::Edit { use Dancer2; get '/edit' =&gt; sub {...}; }</pre> <p>These are two different Dancer2 Apps. They have different scopes, contexts, and thus different engines. While <code>MyApp::User</code> has a serializer (the <a href="https://metacpan.org/module/JSON">JSON</a> one) defined, <code>MyApp::User::Edit</code> will not have that configuration.</p> <p>If you want the path <code>/edit</code> to have a serializer also, you will need to define one for <code>MyApp::User::Edit</code>. This is not just tedious, but when you mix this with the <code>to_app</code> method (described in the previous article, you have a problem:</p> <pre class="prettyprint">use MyApp::User; use MyApp::User::Edit; use Plack::Builder; builder { mount '/' =&gt; MyApp::User-&gt;to_app; # what about MyApp::User::Edit ??? };</pre> <p>If <code>/</code> is taken by <code>MyApp::User</code>, where do we put <code>MyApp::User::Edit</code>?</p> <p>We don't actually wish <code>MyApp::User::Edit</code> to be another application, we just want it to be a comfortable extension to the regular app, providing additional routes that are part of the same already-existing application.</p> <p>While you might think loading <code>MyApp::User::Edit</code> within <code>MyApp::User</code> will help to just extend it, that is not the case. It will still fail.</p> <p><code>appname</code> to the rescue!</p> <h2><a name="appname_saves_the_day"></a>appname saves the day</h2> <p>By using the import option <code>appname</code>, we can ask Dancer2 to extend an App without creating a new one:</p> <pre class="prettyprint">package MyApp::User { use Dancer2; set serializer =&gt; 'JSON'; get '/view' =&gt; sub {...}; } package MyApp::User::Edit { use Dancer2 appname =&gt; 'MyApp::User'; # extending MyApp::User get '/edit' =&gt; sub {...}; }</pre> <p>Now, by using <code>appname</code> when importing, we can ask this App to simply extend an existing one (or one will be created if it does not exist yet) and add the routing there.</p> <p>The serializer will be available, it will have the same configuration, and it will even represent all of the routes with the same internal application object.</p> <pre class="prettyprint"># app.pl use MyApp::User; use MyApp::User::Edit; # single application composed of routes provided in multiple files MyApp::User-&gt;to_app;</pre> <p>Usually we would load classes that contain additional routes inside the original class they extend:</p> <pre class="prettyprint">package MyApp::User { use Dancer2; use MyApp::User::Edit; set serializer =&gt; 'JSON'; ... }</pre> <p>This way we only need to load one when we create an app:</p> <pre class="prettyprint"># app.pl: use MyApp::User; MyApp::User-&gt;to_app;</pre> <h2><a name="conclusion"></a>Conclusion</h2> <p>The import option <code>appname</code> allows you to seamlessly extend Dancer2 Apps without creating unnecessary additional applications or repeat any definitions.</p> <p>This allows you to spread your application routes across multiple files and allow ease of mind when developing it, and accommodate multiple developers working on the same codebase.</p> <h2><a name="author"></a>Author</h2> <p>This article has been written by Sawyer X for the Perl Dancer Advent Calendar 2014.</p> <h2><a name="copyright"></a>Copyright</h2> <p>No copyright retained. Enjoy.</p> <p>2014 // Sawyer X <code>&lt;xsawyerx@cpan.org&gt;</code></p> </div> New feature in Dancer2: to_app http://advent.perldancer.org/2014/9 perl http://advent.perldancer.org/2014/9 Tue, 9 Dec 2014 00:00:00 -0000 <div class="pod-document"><h1><a name="new_feature_in_dancer2__to_app"></a>New feature in Dancer2: to_app</h1> <p><a href="https://metacpan.org/module/Dancer2">Dancer2</a> 0.151000 has made a major change to the dispatching mechanism and provided a new method: <code>to_app</code>. What was the change, why was this keyword introduced, and why should we use it now?</p> <h2><a name="the_way_things_were"></a>The way things were</h2> <p>The original dispatching mechanism in Dancer2 would take all of your Dancer2 applications and wrap them with a loop that tries to match their routes. Once you know that a <i>Dancer App</i> is basically a unit of routes with its own set of engines (such as a template, a session storage, a logger, and a serializer - not all required), you might begin to see a problem here.</p> <p>If you have two applications (meaning two packages that have <code>use Dancer2</code> in them) called <code>MyApp::A</code> and <code>MyApp::B</code>, and you call the <code>dance</code> keyword to create a full fledged PSGI application from them, Dancer will try to match a request against each one. It will start with <code>MyApp::A</code> and then <code>MyApp::B</code>.</p> <p><i>"Is it always in this order?"</i>, you might ask. Actually, it isn't. Since it is internally stored in an array (which is at least deterministic, right?), it is actually checked in the order in which you loaded them into memory.</p> <p>If your handler is:</p> <pre class="prettyprint">use MyApp::B; use MyApp::A; use Dancer2; dance;</pre> <p>It will now check <code>MyApp::B</code> first and <code>MyApp::A</code> last.</p> <p>In fact, it will check <code>MyApp::B</code> first, <code>MyApp::A</code> second, and the last will be whatever package this snippet of code you saw is in - in case it has any routes configured in it before <code>dance</code> was called.</p> <h2><a name="why_is_this_bad"></a>Why is this bad?</h2> <p>So you might be wondering, <i>"Okay, there's an order issue here, but why should I care? Eventually it reaches my route and works fine."</i></p> <p>You are absolutely right - in most cases. However, if both applications have the same route defined, you won't necessarily know which route was actually hit.</p> <p>If you're preloading applications into memory (which is a good idea in large infrastructures), your resulting application might hit someone else's route instead.</p> <p>If you're using the <b>AutoPage</b> feature, you might snag on a different app's template. If one app has a <b>Serializer</b> defined, you might return serialized output. If different apps have a different <b>Session</b> engine, that's even worse. That's tantamount to a security risk - although we try to minimize that risk internally by moving session objects around so you don't hit a mistaken session.</p> <h2><a name="what_can_we_do"></a>What can we do?</h2> <p>The first change we made, back in Dancer2 0.150000, was to call the <code>psgi_app</code> keyword with specific application names, either by class name or by a regular expression. This allowed you to create PSGI applications from specific Dancer Apps:</p> <pre class="prettyprint"># preload everything use MyApp::A; use MyApp::B; use MyApp::C; use MyApp::D; use MyApp::E; # an app for A, B, C my $abc_app = Dancer2-&gt;psgi_app([ qr{^MyApp::[ABC]$} ]); # an app for D, E my $d_app = Dancer2-&gt;psgi_app([ 'MyApp::D', 'MyApp::E' ]);</pre> <p>This allows us to load into memory all the applications we have and then create a PSGI application from only some of them.</p> <p>Here is another example which also joins multiple apps into a single, bigger PSGI app with <a href="https://metacpan.org/module/Plack::Builder">Plack::Builder</a>:</p> <pre class="prettyprint">use MyApp::A; use MyApp::B; use MyApp::C; use Plack::Builder; builder { mount '/' =&gt; Dancer2-&gt;psgi_app(['MyApp::A']); mount '/special' =&gt; Dancer2-&gt;psgi_app([ qr{^MyApp::[BC]$} ]); };</pre> <p>This was a major improvement, but it still didn't address the core problem.</p> <h2><a name="fine__i_ll_bite__what_was_the_core_problem"></a>Fine. I'll bite. What was the core problem?</h2> <p>I'm glad you asked!</p> <p>The code problem was that the dispatching was the duty of the core dispatcher object (an instance of <a href="https://metacpan.org/module/Dancer2::Core::Dispatcher">Dancer2::Core::Dispatcher</a>) instead of the app object itself (<a href="https://metacpan.org/module/Dancer2::Core::App">Dancer2::Core::App</a>). Since the routing should have been done in the app object (the lowest context for engines and routes), it made sense to move it there instead of the dispatcher object.</p> <p>We've done so in Dancer2 0.151000, a version later.</p> <p>While retaining the old behavior of the <code>psgi_app</code> keyword, we introduced one major addition: the <code>to_app</code> class method.</p> <h2><a name="to_app_or_not_to_app"></a>to_app or not to_app</h2> <p>While perhaps not the same question Shakespeare asked, it is a noble one just the same.</p> <p>The <code>to_app</code> method creates a PSGI app from a single application - not from all of your applications or a PSGI app that is restricted to specific ones.</p> <p>This means you can now treat a Dancer2 App as its own unit that can be composed into any path you like.</p> <p>The following:</p> <pre class="prettyprint">MyApp-&gt;to_app;</pre> <p>gives the same behavior to the user as:</p> <pre class="prettyprint">Dancer2-&gt;psgi_app(['MyApp']);</pre> <p>except it does it using quite a few workarounds.</p> <p>Instead of using the awkward <code>Dancer2-&gt;psgi_app()</code>, which provides the same behavior as <code>dance()</code>, you could use <code>to_app</code>. This won't require calling <code>use Dancer2</code> in your handler, since it's a method on your Dancer2 application class.</p> <p>When you have multiple Dancer2 applications, you can compose them together using either <a href="https://metacpan.org/module/Plack::App::URLMap">Plack::App::URLMap</a> or the wrapper syntax for it available in <a href="https://metacpan.org/module/Plack::Builder">Plack::Builder</a>:</p> <pre class="prettyprint">use MyApp::Main; use MyApp::Admin; builder { mount '/' =&gt; MyApp::Main-&gt;to_app; mount '/admin' =&gt; MyApp::Admin-&gt;to_app; };</pre> <p>The effect of the mounting is that these applications will be completely separate and <a href="https://metacpan.org/module/Plack::Builder">Plack::Builder</a> will assure only the appropriate application handles a given request.</p> <p>Instead of creating a loop around all of them, you provide each app with its own dispatching mechanism, in charge only for the routes defined inside it.</p> <p>Another effect of mounting is that the mounting point (<code>/admin</code>, for example) is stripped from the path the application needs to match. This means that <code>MyApp::Admin</code> doesn't need to define <code>/admin/view</code>, but just <code>/view</code>.</p> <p>This has become such a useful and important feature that if you try to call <code>psgi_app</code> on an application (instead of on <code>Dancer2</code> or <code>Dancer2-&gt;runner</code>, it will effectively call <code>to_app</code> underneath.</p> <h2><a name="conclusion"></a>Conclusion</h2> <p>In short, yes. We <b>do</b> want <code>to_app</code>. :)</p> <h2><a name="author"></a>Author</h2> <p>This article has been written by Sawyer X for the Perl Dancer Advent Calendar 2014.</p> <h2><a name="copyright"></a>Copyright</h2> <p>No copyright retained. Enjoy.</p> <p>2014 // Sawyer X <code>&lt;xsawyerx@cpan.org&gt;</code></p> </div> Sweetening the test suite http://advent.perldancer.org/2014/8 perl http://advent.perldancer.org/2014/8 Mon, 8 Dec 2014 00:00:00 -0000 <div class="pod-document"><h1><a name="sweetening_the_test_suite"></a>Sweetening the test suite</h1> <p>The testing suite of a project is an important component, allowing users and developers to maintain trust in the code. Having an organized testing suite makes it easier for developers to add new tests, improve existing tests, and make sure tests are evenly covering the variety of code from all of its angles, as well as making it easier for contributors to help out.</p> <h2><a name="the_sweet_suite"></a>The sweet suite</h2> <p>While mayhem ruled the testing suite of Dancer (both version 1 and 2), we've recently started rearranging it in order to handle the various situations our code works under.</p> <p>Here's the new structure:</p> <h3><a name="t_classes_"></a>t/classes/</h3> <p>The main component of the testing suite are the classes. In <a href="https://metacpan.org/module/Dancer2">Dancer2</a> all the DSL implementation is built on top of core classes. This allows us to decouple the keywords the user uses and their implementation.</p> <p>Under the <i>t/classes/</i> we run tests for classes only. This should not run web requests, understand the web environment, or anything of the sort. Some exceptions may apply, but we try to minimize those.</p> <p>Each class has a directory for itself, allowing you to quick find it, and add tests to it. Each method gets its own test file. We test roles as well, of course. In each directory we can provide static files fo test various scenarios.</p> <h3><a name="t_dsl_"></a>t/dsl/</h3> <p>The user-visible interface of the Dancer web framework is the DSL, which are those keywords we use to define routing.</p> <p>The DSL is tested under the <i>t/dsl/</i> directory. Inside it each DSL keyword has its own file. Keywords requiring more than a single test, or requiring static files (such as sample configuration files), receive their own directory.</p> <p>We're still porting the old DSL keywords into clean tests inside the <i>t/dsl/</i> directory, which means this directory is still relatively small and most of the DSL tests are strewn across the general <i>t/</i> directory.</p> <p>We wouldn't say no to any help offered. :)</p> <h3><a name="t_issues_"></a>t/issues/</h3> <p>Regression tests offer a test which isn't covered by the above described categories. We use regression tests to check specific situations, rather than code paths.</p> <p>Since these situations arise in tickets (and tickets can always be opened for them if not), we created a directory holding all of these tests, sorted by the tracker and the ticket ID in that tracker.</p> <p>Often times a good way to handle an issue is to provide a test, which can then allow verifying it was fixed.</p> <p>For example, we have <i>t/issues/gh-723.t</i> to make sure that scenario doesn't pop up again as a bug.</p> <h2><a name="conclusion"></a>Conclusion</h2> <p>Nowadays when we want to play with tests, we already know where they go and how to write them. Now you do too, which makes it possible for you to write up some tests when providing a fix or a feature, or when you just want to improve the testing coverage.</p> <p>Consistency in the test suite is absolutely vital in order to continually improve the testing coverage and make sense of the testing code.</p> <h2><a name="author"></a>Author</h2> <p>This article has been written by Sawyer X for the Perl Dancer Advent Calendar 2014.</p> <h2><a name="copyright"></a>Copyright</h2> <p>No copyright retained. Enjoy.</p> <p>2014 // Sawyer X <code>&lt;xsawyerx@cpan.org&gt;</code></p> </div> Doing an API Mashup with Dancer http://advent.perldancer.org/2014/7 perl http://advent.perldancer.org/2014/7 Sun, 7 Dec 2014 00:00:00 -0000 <div class="pod-document"><h1><a name="doing_an_api_mashup_with_dancer"></a>Doing an API Mashup with Dancer</h1> <p>I was delighted to receive a Twitter message from Su-Shee on an article about mashing up an API call with <a href="http://www.sinatrarb.com/">Sinatra</a>:</p> <blockquote class="twitter-tweet" lang="en"><p>.<a href="https://twitter.com/PerlSawyer">@PerlSawyer</a> tiny total beginner&#39;s <a href="https://twitter.com/hashtag/sinatra?src=hash">#sinatra</a> example, should be blatantly copied for <a href="https://twitter.com/hashtag/dancer?src=hash">#dancer</a>... <a href="https://t.co/SlSia0f92a">https://t.co/SlSia0f92a</a> &quot;learn how to API&quot; :)</p>&mdash; Su-Shee (@sheeshee) <a href="https://twitter.com/sheeshee/status/541175744358268928">December 6, 2014</a></blockquote> <script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script> <p>You might wonder how a version of it would look like in Dancer. Shouldn't be a problem. Let's have a go at it!</p> <h2><a name="prior_work"></a>Prior work</h2> <p>If you haven't had the time or inclination to read the aforementioned article (which we actually recommend), here is a brief description of our task.</p> <p>We want to create an app that makes a request to a weather API and then displays it dynamically in a web page.</p> <h2><a name="to_everything_a_start"></a>To everything a start</h2> <p>Setting up the application was relatively quick. Open up your favorite editor on a new file. Let's call it <i>mashup.pl</i>:</p> <p>Other than <a href="https://metacpan.org/module/Dancer2">Dancer2</a> for defining routes, we will use <a href="https://metacpan.org/module/HTTP::Tiny">HTTP::Tiny</a> to make the weather API request, <a href="https://metacpan.org/module/JSON">JSON</a> to decode it from JSON format, and finally <a href="https://metacpan.org/module/File::Spec">File::Spec</a> to provide a fully-qualified path to our template engine. That last bit will be explained later on.</p> <pre class="prettyprint">use JSON; use Dancer2; use HTTP::Tiny; use File::Spec;</pre> <h2><a name="configuration"></a>Configuration</h2> <p>Now we set up some variables for our web application. We will use the excellent <a href="https://metacpan.org/module/Template">Template::Toolkit</a> template system. It is simple and easy to work with.</p> <p>Dancer searches for our templates in our views directory, which defaults to <i>views</i> directory in our current directory. Since we want to put our template in our current directory, we will configure that. However, <i>Template::Toolkit</i> does not want us to provide a relative path without configuring it to allow it. This is a security issue. So, we're using <a href="https://metacpan.org/module/File::Spec">File::Spec</a> to create a full path to where we are.</p> <p>We also unset the default layout, so Dancer won't try to wrap our template with another one. This is a feature in Dancer to allow you to wrap your templates with a layout when your templating system doesn't support it. Since we're not using a layout here, we don't need it.</p> <pre class="prettyprint">set template =&gt; 'template_toolkit'; # set template engine set layout =&gt; undef; # disable layout set views =&gt; File::Spec-&gt;rel2abs('.'); # full path to views</pre> <p>A lot of explanation and only three lines of code. :)</p> <p>Now, we define our URL:</p> <pre class="prettyprint">my $url = 'http://api.openweathermap.org/data/2.5/weather?id=5110629&amp;units=imperial';</pre> <h2><a name="route___the_gist_of_it"></a>Route - the gist of it</h2> <p>The main component is our web route. We will define a main route which, upon a request, will fetch the information from the weather API, decode it, and then display it to the user.</p> <p>Route definition:</p> <pre class="prettyprint">get '/' =&gt; sub { ... };</pre> <p>Editing the stub of route dispatching code, we start by making the request and decoding it:</p> <pre class="prettyprint"># fetch data my $res = HTTP::Tiny-&gt;new-&gt;get($url); # decode request my $data = decode_json $res-&gt;{'content'};</pre> <p>The data is not just a flat hash. It's a deep structure. To make this post simpler, we will filter it for only the simple keys in the retrieved data:</p> <pre class="prettyprint">my $metrics = { map +( ref $data-&gt;{$_} ? () : ( $_ =&gt; $data-&gt;{$_} ) ), keys %{$data} };</pre> <p>All that is left now is to render it:</p> <pre class="prettyprint">template index =&gt; { metrics =&gt; $metrics };</pre> <p>Oh, and to make this into a runnable-application, we add the magic word:</p> <pre class="prettyprint">dance;</pre> <h2><a name="and_the_template"></a>And the template</h2> <p>We can't forget about the HTML code of course. The following is our <i>index.tt</i> template file:</p> <pre class="prettyprint">&lt;table&gt; &lt;th&gt;The Weather in Buffalo, NY, USA&lt;/th&gt; &lt;tr&gt; &lt;td&gt; [% FOREACH metric IN metrics.keys %] &lt;tr&gt;&lt;td&gt;[% metric %]&lt;/td&gt;&lt;td&gt;[% metrics.$metric %]&lt;/td&gt;&lt;/tr&gt; [% END %] &lt;/td&gt; &lt;/tr&gt; &lt;/table&gt; &lt;hr noshade&gt; Powered by the &lt;a href = 'http://openweathermap.org/' target = _new&gt;Open W eather Map API&lt;/a&gt;</pre> <p>Et Voila!</p> <h2><a name="all_together_now"></a>All together now</h2> <p>Here is our complete app:</p> <pre class="prettyprint">use JSON; use Dancer2; use HTTP::Tiny; use File::Spec; set template =&gt; 'template_toolkit'; set layout =&gt; undef; set views =&gt; File::Spec-&gt;rel2abs('.'); my $url = 'http://api.openweathermap.org/data/2.5/weather?id=5110629&amp;units=imperial'; get '/' =&gt; sub { my $res = HTTP::Tiny-&gt;new-&gt;get($url); my $data = decode_json $res-&gt;{'content'}; my $metrics = { map +( ref $data-&gt;{$_} ? () : ( $_ =&gt; $data-&gt;{$_} ) ), keys %{$data} }; template index =&gt; { metrics =&gt; $metrics }; }; dance;</pre> <p>And the result we have at the end:</p> <table> <th>The Weather in Buffalo, NY, USA</th> <tr> <td> <tr><td>id</td><td>5110629</td></tr> <tr><td>cod</td><td>200</td></tr> <tr><td>name</td><td>Buffalo</td></tr> <tr><td>base</td><td>cmc stations</td></tr> <tr><td>dt</td><td>1417885200</td></tr> </td> </tr> </table> <hr noshade> Powered by the <a href = 'http://openweathermap.org/' target = _new>Open Weather Map API</a> <h2><a name="conclusion"></a>Conclusion</h2> <p>Many of the odder configuration options were actually due to writing an application outside the defaults of a normal production-ready application.</p> <p>If we had a <i>views</i> directory, we wouldn't need <a href="https://metacpan.org/module/File::Spec">File::Spec</a> and to configure the <code>views</code>. If we had used a layout, which we would normally use, we wouldn't need to disable the layout using the <code>layout</code> option. If we tried to account for all data returned, we would also write a template that supports a deeper structure, or dumped it to HTML from its hash representation, which would probably had been easier.</p> <p>At the end, the production code would share all of these comments and end up both smaller and simpler. Of course, our production code would check for errors on fetching the data and decoding it, which we have conveniently ignored. :)</p> <p>One clear difference between our implementation and the <i>Sinatra</i> one is we don't actually stick any HTML in the code itself. There is no need. We simply throw it to the templating engine.</p> <p>With light web frameworks writing your application is usually as straight-forward and simple as it seems in our head.</p> <h2><a name="author"></a>Author</h2> <p>This article has been written by Sawyer X for the Perl Dancer Advent Calendar 2014.</p> <h2><a name="copyright"></a>Copyright</h2> <p>No copyright retained. Enjoy.</p> <p>2014 // Sawyer X <code>&lt;xsawyerx@cpan.org&gt;</code></p> </div> Static noise - Static file serving in Dancer2 http://advent.perldancer.org/2014/6 perl http://advent.perldancer.org/2014/6 Sat, 6 Dec 2014 00:00:00 -0000 <div class="pod-document"><h1><a name="static_noise___static_file_serving_in_dancer2"></a>Static noise - Static file serving in Dancer2</h1> <p>All too often beginners would stumble over the behavior of static file serving in Dancer2. The idea made sense on paper but somehow, when you put it in practical terms, it wasn't just a hurdle but a real pain to constantly headbutt without realizing, <i>"damn it, that again!"</i></p> <p>The good news is we fixed it. The bad news is you will have to read this article to understand what we're talking about. The treat is we will explain how it was fixed after we explain what was wrong.</p> <h2><a name="ex_static"></a>Ex-static</h2> <p>The logic for request serving in Dancer 1 is simple. It consists of the following steps run in order:</p> <ul> <li><a name="item_Try_to_render_a_static_file_from__code_public___code_"></a><b>Try to render a static file from <code>public/</code></b> </li> <li><a name="item_Try_to_render_an_action___a_user_s_route"></a><b>Try to render an action - a user's route</b> </li> <li><a name="item_Try_to_render_an_AutoPage___a_user_s_template"></a><b>Try to render an AutoPage - a user's template</b> </li> <li><a name="item_Give_up_and_render_a_404_page"></a><b>Give up and render a 404 page</b> </li> </ul> <p>In <a href="https://metacpan.org/module/Dancer2">Dancer2</a> these items were broken down into composable units known as handlers. <a href="https://metacpan.org/module/Dancer2::Handler::File">Dancer2::Handler::File</a> serves static files (which the DSL keyword <code>send_file</code> uses internally) and <a href="https://metacpan.org/module/Dancer2::Handler::AutoPage">Dancer2::Handler::AutoPage</a> renders template files.</p> <p>These handlers were, when configured to be used (or according to the defaults), merged into an application as regular routes. To make sure they don't cause any confusion, they were merged at the very end. Oops. Strike one!</p> <p>The following order was created:</p> <ul> <li><a name="item_Try_to_match_a_user_route"></a><b>Try to match a user route</b> </li> <li><a name="item_Try_to_match_a_static_file_route__Handler__File_"></a><b>Try to match a static file route (Handler::File)</b> </li> <li><a name="item_Try_to_match_a_rendered_template__Handler__AutoPage_"></a><b>Try to match a rendered template (Handler::AutoPage)</b> </li> <li><a name="item_Give_up_and_render_a_404_page"></a><b>Give up and render a 404 page</b> </li> </ul> <p>While it seems reasonable for user-defined routes to trump static resources and templates, people were not expecting it to happen, which led to a few peculiar situations.</p> <h2><a name="problem_1__greed_is_not_good"></a>Problem 1: Greed is NOT good</h2> <p>In order for these routes to accept <i>any</i> input, they use a greedy <b>megasplat</b> route, which captures everything:</p> <pre class="prettyprint">get '/**' =&gt; sub { # I SEE ALL ROUTES # (as long as they are a GET request) };</pre> <p>(Users can define these routes as well, of course.)</p> <p>The first manifestation of the reshuffling in order of execution occurred when users defined greedy <b>megasplat</b> routes which accidentally captured all static requests as well:</p> <pre class="prettyprint">get '/**' =&gt; sub { # handle what I think is a user request # but can also be a static file request };</pre> <p>Now users had to account for static files being asked of them. Ouch. This is actually the small problem.</p> <h2><a name="problem_2__a_hook_to_kill"></a>Problem 2: A hook to kill</h2> <p>Remember hooks? Sure you do. Every route can have hooks. Amongst available hooks there are the <b>before</b> and <b>after</b> hooks which control the execution sequence of a matched route, allowing you to call code before and after it is executed, respectively.</p> <p>How does that come into play? Since the <b>File</b> and <b>AutoPage</b> handlers create regular routes (just like a user might), the <b>before</b> and <b>after</b> hooks actually apply to them.</p> <p>What?</p> <p>Yes! This meant that, for example, your <b>before</b> route hooks were called for static files. If they contained a security check (for which many users use them), you might accidentally prevent a file from being rendered. Strike two!</p> <p><i>"You can't see the lacking access picture because you lack access!"</i></p> <h2><a name="plack_strikes_back"></a>Plack strikes back</h2> <p>Before we hit a <i>strike three</i> we decided to fix this. Since we're depending on <a href="https://metacpan.org/module/Plack">Plack</a> and the associated technology to help resolve so many issues, we looked there.</p> <p>One wonderful part of Plack is the middlewares. One specific middleware that came to our rescue was <a href="https://metacpan.org/module/Plack::Middleware::Static">Plack::Middleware::Static</a>. It allow us to render static files from the <code>public/</code> directory before it actually reaches our application and Dancer2 dispatching code at all. Wait, what?</p> <p>The Plack middleware wraps the Dancer2 code and checks for static files on each request before it sends it off to Dancer2. If it can find a file that matches the request, it will serve it directly instead of passing it onwards.</p> <p>This means we're back to a proper static file serving behavior. They are now served properly before the app and the hooks do not apply to them.</p> <p>We still kept the <b>File</b> handler to provide <code>send_file</code>, but it is no longer in charge of automatically serving static files.</p> <p>The <b>AutoPage</b> handler is kept as is because hooks make sense in rendering templates. You might want to use the <b>before_template</b> hook in order to provide default variables that will be available in every template rendering (including automatic ones served by <b>AutoPage</b>) - which is something you will not have with static content.</p> <h2><a name="conclusion"></a>Conclusion</h2> <p>Wonderful work by <a href="https://metacpan.org/author/RUSSELLJ">Russell @veryrusty Jenkins</a> solving this thorn in Dancer2 and providing consistent behavior that makes sense.</p> <p>If you meet him, offer him a drink. He's Australian so he'll take it. :)</p> <h2><a name="author"></a>Author</h2> <p>This article has been written by Sawyer X for the Perl Dancer Advent Calendar 2014.</p> <h2><a name="copyright"></a>Copyright</h2> <p>No copyright retained. Enjoy.</p> <p>2014 // Sawyer X <code>&lt;xsawyerx@cpan.org&gt;</code></p> </div> Packing the Fat http://advent.perldancer.org/2014/5 perl http://advent.perldancer.org/2014/5 Fri, 5 Dec 2014 00:00:00 -0000 <div class="pod-document"><h1><a name="packing_the_fat"></a>Packing the Fat</h1> <p>After speaking of one way to handle dependencies, it's time to talk about another.</p> <p>One promise we've made with <a href="https://metacpan.org/module/Dancer2">Dancer2</a> is it will always be <i>fatpackable</i>, but only a few people actually know what this means and why it's important.</p> <p>If you keep on reading, you're going to join that group of people.</p> <h2><a name="fatpacker"></a>FatPacker</h2> <p>One of the reasons people worry about dependencies is not being able to install them. Of course you could use <a href="https://metacpan.org/module/local::lib">local::lib</a> or <a href="https://metacpan.org/module/carton">carton</a> to install them locally, but another mechanism available is <a href="https://metacpan.org/module/App::FatPacker">App::FatPacker</a>.</p> <p><a href="https://metacpan.org/module/App::FatPacker">App::FatPacker</a> (using its command line interface, <a href="https://metacpan.org/module/fatpack">fatpack</a>) packs dependencies into a single file (hence the name), allowing you to carry a single file instead of a directory tree.</p> <p>If you're interested in understanding <a href="https://metacpan.org/module/App::FatPacker">App::FatPacker</a>, I have written <a href="http://www.perladvent.org/2012/2012-12-14.html">an article</a> describing it, how it works, and how to use it.</p> <h2><a name="fatpacking_dancer2_applications"></a>FatPacking Dancer2 applications</h2> <p>By saying <a href="https://metacpan.org/module/Dancer2">Dancer2</a> is fatpackable, we mean that we make sure the Dancer2 can be fatpacked. We do this by requiring by default only pure-Perl modules. We allow you to optionally install XS modules to improve speed, but Dancer2 will work just fine without them.</p> <p>This means that as long as your application is also pure-Perl, you could create a single file with your application and all of Dancer2 in it.</p> <p>Let's take a look at an example.</p> <p>Assuming we have an application in <i>lib/MyApp.pm</i>:</p> <pre class="prettyprint">package MyApp; use Dancer2; get '/' =&gt; sub {'OK'}; 1;</pre> <p>And we have a handler in <i>bin/app.pl</i>:</p> <pre class="prettyprint">use strict; use warnings; use FindBin; use lib "$FindBin::Bin/../lib"; use MyApp; MyApp-&gt;to_app;</pre> <p>To fatpack it, we will begin by tracing the script:</p> <pre class="prettyprint">$ fatpack trace bin/app.pl</pre> <p>This creates a <i>fatpacker.trace</i> file. From this we create the packlists:</p> <pre class="prettyprint">$ fatpack packlists-for `cat fatpacker.trace` &gt; packlists</pre> <p>The packlists are stored in a file called, surprisingly, <i>packlists</i>.</p> <p>Now we create the tree using the following command:</p> <pre class="prettyprint">$ fatpack tree `cat packlists`</pre> <p>The tree is created under the directory <i>fatlib</i>.</p> <p>Now that we have the tree, we simply need to pack it all together. While this will create a file containing the dependency tree, we also want to add our script to it, so we'll do it all in one command:</p> <pre class="prettyprint">$ (fatpack file; cat bin/app.pl) &gt; myapp.pl</pre> <p>This creates a file called <i>myapp.pl</i> with everything in it. But before we can run it, we need to account for one small detail. Dancer2 is using <a href="https://metacpan.org/module/MIME::Types">MIME::Types</a> which has a database of all MIME types and helps translate those. The small database file containing all of these types is a binary and therefore cannot be fatpacked. We need to copy it to the current directory so our script can find it.</p> <pre class="prettyprint">$ cp fatlib/MIME/types.db .</pre> <p>Now we can use the file just like any other <a href="https://metacpan.org/module/PSGI">PSGI</a> application file:</p> <pre class="prettyprint">$ plackup myapp.pl</pre> <p>While we're using <code>plackup</code> here, it's just an example of a server that will read this. You would usually configure this in your web server as a PSGI application script.</p> <h2><a name="conclusion"></a>Conclusion</h2> <p><a href="https://metacpan.org/module/Dancer2">Dancer2</a> aims to allow you to package your apps in any number of ways and <a href="https://metacpan.org/module/App::FatPacker">App::FatPacker</a> is a very useful packaging mechanism we aim to continually support.</p> <p>You can now easily pack everyting and send your co-worker/colleague/enemy a single file that has everything in it, all dependencies bundled in.</p> <p>Next time someone says <i>"But I can't install anything"</i>, throw your packed Dancer web application at them!</p> <h2><a name="author"></a>Author</h2> <p>This article has been written by Sawyer X for the Perl Dancer Advent Calendar 2014.</p> <h2><a name="copyright"></a>Copyright</h2> <p>No copyright retained. Enjoy.</p> <p>2014 // Sawyer X <code>&lt;xsawyerx@cpan.org&gt;</code></p> </div> Your website in a carton box http://advent.perldancer.org/2014/4 perl http://advent.perldancer.org/2014/4 Thu, 4 Dec 2014 00:00:00 -0000 <div class="pod-document"><h1><a name="your_website_in_a_carton_box"></a>Your website in a carton box</h1> <p>My new favorite way to package <a href="https://metacpan.org/module/Dancer2">Dancer2</a> applications is <a href="https://metacpan.org/module/Carton">Carton</a>. You setup a single file, type a command or two, and you're done. Here's how it works and how you set it up yourself.</p> <h2><a name="what_carton_does"></a>What Carton does?</h2> <p><a href="https://metacpan.org/module/Carton">Carton</a> sets up a local copy of your project prerequisites. You only need to define them in a file and ask Carton to download all of them and set them up.</p> <p>When you want to deploy your app, you just carry the git clone and ask Carton to set up the environment again and you will then be able to run it.</p> <p>The benefit is multi-fold:</p> <ul> <li><a name="item_Local_directory_copy"></a><b>Local directory copy</b> <p>By putting all the dependencies in a local directory, you can make sure they aren't updated by someone else by accident and their versions locked to the version you picked.</p> </li> <li><a name="item_Sync_versions"></a><b>Sync versions</b> <p>Deciding which versions of the dependent modules your project needs allows you to sync this with other developers as well. Now you're all using the same version and they don't change unless you want update the versions you want. When updated everyone again uses the same new version of everything.</p> </li> <li><a name="item_Carry_only_the_requirement__not_bundled_modules"></a><b>Carry only the requirement, not bundled modules</b> <p>Instead of bundling the modules, you only actually bundle the requirements. Carton builds them for you when you need it.</p> </li> </ul> <h2><a name="setting_it_up"></a>Setting it up</h2> <p>First thing we do is set up a new app:</p> <pre class="prettyprint">$ dancer2 -a MyApp ...</pre> <p>Then we delete the files we don't care about:</p> <pre class="prettyprint">$ rm -f Makefile.PL MANIFEST MANIFEST.SKIP</pre> <p>Now let's create a Git repo:</p> <pre class="prettyprint">$ git init &amp;&amp; git add . &amp;&amp; git commit -m "initial commit"</pre> <p>Let's add a requirement using the <a href="https://metacpan.org/module/cpanfile">cpanfile</a> format:</p> <pre class="prettyprint">$ cat &gt; cpanfile requires 'Dancer2' =&gt; 0.155000; requires 'Template' =&gt; 0; recommends 'URL::Encode::XS' =&gt; 0; recommends 'CGI::Deurl::XS' =&gt; 0; recommends 'HTTP::Parser::XS' =&gt; 0;</pre> <p>We can now ask Carton to set it up:</p> <pre class="prettyprint">$ carton install Installing modules using [...] Successfully installed [...] ... Complete! Modules were install into [...]/local</pre> <p>Now we have two files: <i>cpanfile</i> and <i>cpanfile.snapshot</i>. We add both of them to our Git repository and we make sure we don't accidentally add the <i>local/</i> directory Carton created which holds the modules it installed:</p> <pre class="prettyprint">$ echo local/ &gt;&gt; .gitignore $ git add .gitignore cpanfile cpanfile.snapshot $ git commit -m "Start using carton"</pre> <p>When we want to update the versions on the production machine, we simply call:</p> <pre class="prettyprint">$ carton install --deployment</pre> <p>By using <code>--deployment</code> we make sure we only install the modules we have in our <i>cpanfile.snapshot</i> file and do not fallback to querying the CPAN.</p> <h2><a name="conclusion"></a>Conclusion</h2> <p>Setting up <a href="https://metacpan.org/module/Carton">Carton</a> takes two minutes and allows us to provide specific requirements for our applications and a mechanism to install them on a production machine while ensuring it will create a local copy of everything.</p> <p>We no longer care about the system module versions and we can maintain multiple versions of each module used in each separate application. If a certain application doesn't need to update a module, it just doesn't have to, and at the same time doesn't prevent another application from updating its own modules.</p> <p>Try it out, you'll love it!</p> <h2><a name="author"></a>Author</h2> <p>This article has been written by Sawyer X for the Perl Dancer Advent Calendar 2014.</p> <h2><a name="copyright"></a>Copyright</h2> <p>No copyright retained. Enjoy.</p> <p>2014 // Sawyer X <code>&lt;xsawyerx@cpan.org&gt;</code></p> </div> Migrating to Dancer2 http://advent.perldancer.org/2014/3 perl http://advent.perldancer.org/2014/3 Wed, 3 Dec 2014 00:00:00 -0000 <div class="pod-document"><h1><a name="migrating_to_dancer2"></a>Migrating to Dancer2</h1> <p>A question we often get asked when we promote <a href="https://metacpan.org/module/Dancer2">Dancer2</a> is <i>"How do I migrate my code to Dancer2?"</i></p> <p>There had been some changes between the versions - big enough to require an entirely new namespace. What were they? How do we migrate?</p> <h2><a name="changing_the_namespace"></a>Changing the namespace</h2> <p>The reason we changed the namespace wasn't really due much to the change a user will necessarily see, but more due to the incredible difference in core architecture, and CPAN's inability to maintain two running versions in the same namespace, as mentioned in the <a href="http://advent.perldancer.org/2014/2">previous article</a>.</p> <p><a href="https://metacpan.org/module/Dancer2">Dancer2</a> is actually a complete rewrite. It had small portions of the code moved and some of the documentation was copied over, but mainly it is completely restructured.</p> <p>It no longer relies on reinventing the wheel as much. Users simply didn't care about installing another module or two or three or even more. At the same time, enough tools we written to still allow you to get away with not being able to install dependencies, so the entire problem became moot.</p> <p>For example, Having <a href="https://metacpan.org/module/local::lib">local::lib</a> allows you to install an entire module tree in a local user's directory (not requiring administrative privileges). Having <a href="https://metacpan.org/module/fatpacker">fatpacker</a> allows you to fatpack your entire Dancer2 application in a single file. Having <a href="https://metacpan.org/module/Carton">Carton</a> allows you to package it all nicely. Having <a href="https://metacpan.org/module/Pinto">Pinto</a> allows you to set up an entire personal CPAN for your company. Things are much easier.</p> <p>(Watch for additional articles that cover <a href="https://metacpan.org/module/fatpacker">fatpacker</a> and <a href="https://metacpan.org/module/Carton">Carton</a> in this advent calendar.)</p> <p>Additionally, we wanted the ability to make core changes without breaking a lot of old applications. This doesn't mean a migration is difficult though. Having two different namespaces allows you to keep your current Dancer 1 applications running alongside your new Dancer2 applications and make it simple to migrate when <b>you</b> are ready.</p> <p>Following are a few tips for migrating your applications to Dancer2, finishing with one great resource for it at the end.</p> <h2><a name="it_s_all_about_the_plack"></a>It's all about the Plack</h2> <p>Dancer originally wasn't built for <a href="https://metacpan.org/module/Plack">Plack</a>. When Plack came out, Dancer has made the necessary changes to accommodate it. However, it wasn't the leading spec for Dancer, as it was simply a port of another framework from Ruby.</p> <p>Dancer2 took a different approach: Plack leads the way. This led to quite a few changes in removing unnecessary code, producing much more correct behavior, and providing more deterministic results.</p> <p>A few examples:</p> <ul> <li><a name="item_Each_class_is_an_entire_app"></a><b>Each class is an entire app</b> <p>A Dancer App is now every class which consumes <a href="https://metacpan.org/module/Dancer2">Dancer2</a>. This means they can each have their own configuration, allowing different engines:</p> <pre class="prettyprint">package Admin { use Dancer2; ... } package Public { use Dancer2; ... }</pre> <p>Now <code>Admin</code> and <code>Public</code> are fully independent applications. They will not share any resources and will be able to have different engines (template, session, serializer, logger) which will not be shared. No more worrying about globals.</p> </li> <li><a name="item_Removing___script__import_key_for_plackup"></a><b>Removing ':script' import key for plackup</b> <p>Dancer 1 had the <code>:script</code> import key which would read your command line arguments to change how the Dancer server would run.</p> <p>Since <a href="https://metacpan.org/module/Plack">Plack</a> has the <a href="https://metacpan.org/module/plackup">plackup</a> command line tool, it already reads your command line arguments. Why make a duplicate effort?</p> </li> <li><a name="item_Fully_object_oriented"></a><b>Fully object-oriented</b> <p>Dancer2 has changed its core substantially to be much more object oriented. Now the core is implemented in objects. The DSL layer simply provides an interface to those objects.</p> <p>This makes everything much easier to compose and test.</p> </li> <li><a name="item_HTTP__Server__Simple_replaced_with_HTTP__Server__PSGI"></a><b>HTTP::Server::Simple replaced with HTTP::Server::PSGI</b> <p>Originally Dancer would use <a href="https://metacpan.org/module/HTTP::Server::Simple">HTTP::Server::Simple</a> which supported PSGI, but it was a pain to use, since it had issues we needed to patch and provided a dependency we weren't happy about.</p> <p>As it happens, <a href="https://metacpan.org/module/Plack">Plack</a> comes with a great development server called <a href="https://metacpan.org/module/HTTP::Server::PSGI">HTTP::Server::PSGI</a>. Since we're building on Plack, we might as well make use of it. This is why Dancer2 uses it instead.</p> </li> </ul> <h2><a name="migration_in_a_nutshell"></a>Migration in a nutshell</h2> <p>Okay, but putting all of that aside, how do I migrate?</p> <p>Well, it really depends on what you do with your application, but here are our main migration tips:</p> <ul> <li><a name="item_Clean_importing"></a><b>Clean importing</b> <p>All of the importing keywords are unnecessary now, except for <code>appname</code>, explained below.</p> </li> <li><a name="item_Separate_serialized_routes"></a><b>Separate serialized routes</b> <p>Routes that require serializers should be separated to their own Dancer2 app, since serializers will try to deserialize all input and serialize all output in every route in their app scope.</p> </li> <li><a name="item_DSL_keyword_changes"></a><b>DSL keyword changes</b> <p>We tried to change very little of the DSL. <code>load</code> and <code>param_array</code> no longer exist, and <code>session</code> can also provide the session object, not just retrieve and set values for keys.</p> </li> <li><a name="item_Applications_are_self_dispatching_units"></a><b>Applications are self-dispatching units</b> <p>As explained above, any module that uses <code>Dancer2</code> becomes a Dancer Application, which creates a separated dispatcher only for the routes created under that module namespace.</p> <p>The application's engines will not be shared with others - an issue that pained experienced developers of Dancer 1.</p> <p>If you want to compose multiple Dancer Applications to create a single web application, you can use <a href="https://metacpan.org/module/Plack::Builder">Plack::Builder</a> and <code>to_app</code>. Stay tuned for an article explaining this exact situation.</p> </li> <li><a name="item_Multiple_packages_for_a_single_app"></a><b>Multiple packages for a single app</b> <p>Allowing multiple packages to create a single Dancer Application is also possible using the <code>appname</code> feature. This will also appear in an upcoming article.</p> </li> </ul> <h2><a name="you_said_something_about_a_great_resource"></a>You said something about a great resource?</h2> <p>Oh yes!</p> <p>Writing down all the migration changes between Dancer 1 and Dancer2 would be too much. Plus, who would check this article after a while again to see if it was updated? No one, that's who!</p> <p>Instead, we've compiled a list (with the kind help of Snigdha Dagar) of all of these changes under <a href="https://metacpan.org/module/Dancer2::Manual::Migration">Dancer2::Manual::Migration</a>.</p> <p>If you're interested in migrating your applications to Dancer2, or would like to write a new application and care to know what the differences are, you should consult it.</p> <p>Of course we welcome any changes and improvements to this document as it is a living breathing document (which we hope will not attack us during Halloween), so feel free to submit pull requests, send comments on the mailing list, or stop by the IRC channel.</p> <h2><a name="conclusion"></a>Conclusion</h2> <p>Dancer2 has a few changes that promote much more consistent and deterministic web application development. It reduces the considerations we have to take into account while providing much more correct implementations for various pieces.</p> <p>Our new Migration Document helps new-comers and seasoned developers keep up-to-date with the changes we've done and how it might affect their future code.</p> <h2><a name="author"></a>Author</h2> <p>This article has been written by Sawyer X and Mickey Nasriachi for the Perl Dancer Advent Calendar 2014.</p> <h2><a name="copyright"></a>Copyright</h2> <p>No copyright retained. Enjoy.</p> <p>2014 // Sawyer X <code>&lt;xsawyerx@cpan.org&gt;</code></p> </div> Dancer2 - starting anew http://advent.perldancer.org/2014/2 perl http://advent.perldancer.org/2014/2 Tue, 2 Dec 2014 00:00:00 -0000 <div class="pod-document"><h1><a name="dancer2___starting_anew"></a>Dancer2 - starting anew</h1> <p>It has a different namespace, a different release manager, and a different repo - <a href="https://metacpan.org/module/Dancer2">Dancer2</a> sounds like a completely new thing, which it is. But it also isn't.</p> <h2><a name="the_portsmith_s_history"></a>The portsmith's history</h2> <p>Dancer started as a Perl port of Sinatra - a successful light web framework in Ruby. The author of Dancer, Alexis Sukrieh (AKA, sukria), who is also a Ruby programmer, had enjoyed it so much, he wanted something similar in Perl. He then began the task of porting Sinatra to Perl under the name <b>Dancer</b>.</p> <p><a href="https://metacpan.org/module/Dancer">Dancer</a> had become very successful. In fact it had been so successful a wonderful warm community grew around it. Users and developers alike sharing their use cases, giving talks, trainings, writing articles, and even making it part of their job.</p> <p>When Dancer became a production framework in various companies, a major flaw in the design had creeped into sight: the global state. (Chime in with horror music.)</p> <p>Many components in Dancer were globals and this shared state made it impossible to have multiple applications without side-effects. Sukria had gone underground and returned with <b>Dancer 2</b>. A completely rewritten framework, based on the same principle as Dancer, sharing the same DSL and overall design, but lacking the global state which had crippled Dancer so.</p> <p>This version promised to be the noble successor.</p> <h2><a name="the_version_that_never_was"></a>The version that never was</h2> <p>Unfortunately the code was still incompatible in some ways. Plugins, mainly, did not work, since the architecture was vastly different. We wanted to release both a <i>2.0</i> branch and a <i>1.0</i> branch, but CPAN does not allow that. We then decided to split the namespace to allow both versions to exist at the same time while we iron out the missing bits. Considering <b>Mongrel2</b> and even Perl's <a href="https://metacpan.org/module/Amon2">Amon2</a>, why not <b>Dancer2</b>?</p> <p>After a few releases, Sukria had to attend to more pressing issues, and Dancer2 received little attention. Sawyer, who had become the project leader for production version of Dancer, took Dancer2, and Yanick Champoux, the amazing French Canadian, had taken the production version of Dancer under his wing - one of many wings, in fact.</p> <h2><a name="the_prodigal_daughter"></a>The prodigal daughter</h2> <p>Following multiple big releases, Dancer2 had become ready for mass usage. It has a few rough edges, but in most ways, it's in fact much more reliable.</p> <p>Dancer2 has the following advantages over Dancer 1, amongst others:</p> <ul> <li><a name="item_Composable_Dancer_Applications"></a><b>Composable Dancer Applications</b> <p>Dancer2 Apps are composable units that take care of their own dispatching. While we have the original <code>dance</code> behavior to dispatch over all registered applications, we now have much better mechanisms to handle separate applications without forcing the user to have all or nothing.</p> <p>This Advent Calendar will feature an article showcasing this functionality with plenty of explanations on the matter.</p> </li> <li><a name="item_Decoupled_DSL_implementation"></a><b>Decoupled DSL implementation</b> <p>The DSL implementation in Dancer2 is decoupled in a way that allows us to improve it without changing it for the users. In fact, Dancer2 shares the majority of the DSL with Dancer 1 and we can keep that working as expected.</p> </li> <li><a name="item_Successful_object_system"></a><b>Successful object system</b> <p>Instead of rolling our own objects, Dancer2 uses <a href="https://metacpan.org/module/Moo">Moo</a>, which provides the same behavior as <a href="https://metacpan.org/module/Moose">Moose</a> for all the objects we have. It allows us to have much smarter objects than we did before with lazy attributes, attribute builders, role composition, and more.</p> </li> <li><a name="item_Better_development_server"></a><b>Better development server</b> <p>Dancer2 uses the <a href="https://metacpan.org/module/Plack">Plack</a> core development server, <a href="https://metacpan.org/module/HTTP::Server::PSGI">HTTP::Server::PSGI</a>, which provides a more reliable experience. In the past, for Dancer 1, we had to work around a lot of problems with the development server.</p> </li> <li><a name="item_Less_specialized_code"></a><b>Less specialized code</b> <p>Dancer 1 contained a lot of unnecessary code which was removed in favor of a proper implementation around Plack: this includes the command line parsing when importing the DSL, static file serving, testing code, and more.</p> </li> <li><a name="item_Robust_CLI_capabilities"></a><b>Robust CLI capabilities</b> <p>The command-line interface in Dancer2 is written in <a href="https://metacpan.org/module/App::Cmd">App::Cmd</a>, which allows us to extend it fully, providing interesting command-line features.</p> <p>We haven't yet gone nuts with it, but now we'll be able to do so, and we have a few interesting ideas.</p> </li> <li><a name="item_Devoted_set_of_developers"></a><b>Devoted set of developers</b> <p>While Dancer version 1 has been placed into freeze mode, Dancer2 has a group of developers devoted to it. More and more developers have joined the core team as well. This includes the aforementioned Yanick, Russell Jenkins, Mickey Nasriachi, Stefan Hornburg (Racke), Steven Humphrey, Alberto Sim&#xf5;es, and David Precious. Somewhere in there Sawyer X is probably there, but we can't attest to that - at least not legally.</p> </li> </ul> <p>At the end of the day, though, there is one major consideration we've yet to mention.</p> <h2><a name="the_version_that_is"></a>The version that is</h2> <p>While many users are still on Dancer 1, Dancer2 is ready and waiting, and we're pooling all of our efforts to improving it. Dancer 1 is on freeze mode, meaning no new features.</p> <p>Dancer2 is <b>NOT</b> a new framework, it is simply the next version. When asked in the past, we explained that this isn't Perl 5 and Perl 6.</p> <p>Dancer2 might have a few rough edges, but it's much more reliable, correct, featureful, and a much safer bet than Dancer 1.</p> <h2><a name="conclusion"></a>Conclusion</h2> <p>Please consider writing your new code in <a href="https://metacpan.org/module/Dancer2">Dancer2</a> and also porting any major applications you want to continue to develop. If you find difficulties in the process, please let us know, so we could fix them.</p> <p>Be careful though, that's the first step to becoming a contributor! :)</p> <h2><a name="author"></a>Author</h2> <p>This article has been written by Sawyer X for the Perl Dancer Advent Calendar 2014.</p> <h2><a name="copyright"></a>Copyright</h2> <p>No copyright retained. Enjoy.</p> <p>2014 // Sawyer X <code>&lt;xsawyerx@cpan.org&gt;</code></p> </div> Another year of Dancing... http://advent.perldancer.org/2014/1 perl http://advent.perldancer.org/2014/1 Mon, 1 Dec 2014 00:00:00 -0000 <div class="pod-document"><h1><a name="another_year_of_dancing___"></a>Another year of Dancing...</h1> <p>Welcome to the Dancer advent calendar!</p> <p>We skipped last year's advent calendar, but we're hoping the articles we gathered this year will help you learn more about Dancer and specifically Dancer2, which is the target version of all new applications.</p> <p>We will show changes Dancer2 has made, features it recently added, a few tricks, and even survey the code - as well as mention some of our numerous community contributors, and take a look at the project as a whole.</p> <h2><a name="more_and_more_dancers___"></a>More and more dancers...</h2> <p>Usage of Dancer continues to grow, with more new users added to the <a href="http://dancer.pm/dancefloor">dancefloor</a>.</p> <p>If you're using Dancer in your company and would like to appear on the dancefloor page, please contact us.</p> <p>Dancer has been spotted as a required/desired skill in several job adverts, showing the increased uptake of Dancer in corporate web apps. Try <a href="http://jobs.perl.org/search?q=dancer">searching for Dancer on jobs.perl.org</a>.</p> <h2><a name="dancer2___a_reality"></a>Dancer2 - a reality</h2> <p>Far more progress has been made with <a href="https://metacpan.org/module/Dancer2">Dancer2</a>. It is now a fully usable, robust replacement for Dancer 1. That said, Dancer 1 will continue to be supported for some time yet and continues to receive bugfixes, support, and minor improvements.</p> <p>This article will focus mainly on Dancer2.</p> <h2><a name="dancer_at_lpw2013"></a>Dancer at LPW2013</h2> <p>Andrew Solomon ran a free two-hour Dancer 2 training course at last year's London Perl Workshop. Andrew's course was a hands-on training session to develop a website with dynamic content using Dancer, during which the attendees would:</p> <ul> <li><a name="item_Learn_about_Dancer2_as_a_framework_and_as_a_language"></a><b>Learn about Dancer2 as a framework and as a language</b> </li> <li><a name="item_Implement_route_handlers_using_sessions_and_hooks"></a><b>Implement route handlers using sessions and hooks</b> </li> <li><a name="item_Implement_views__templates__and_layouts_using_Template_Toolkit_and_Bootstrap"></a><b>Implement views, templates, and layouts using Template Toolkit and Bootstrap</b> </li> <li><a name="item_Understand_the_concept_of_Model_View_Controller"></a><b>Understand the concept of Model-View-Controller</b> </li> <li><a name="item_Experience_structuring_code_for_maintainability"></a><b>Experience structuring code for maintainability</b> </li> <li><a name="item_Experience_using_object_oriented_Perl_modules"></a><b>Experience using object oriented Perl modules</b> </li> <li><a name="item_Understand_all_the_crazy_jargon_above_"></a><b>Understand all the crazy jargon above!</b> </li> </ul> <p>See also Andrew's <a href="http://geekuni.com/perl-web-d2">Perl Web Development</a> course on geekuni.com.</p> <h2><a name="dancerconf"></a>DancerConf</h2> <p>This year in Hancock, New York, the first Dancer conference was held. It had trainings on <a href="https://metacpan.org/module/Dancer">Dancer</a> (and <a href="https://metacpan.org/module/Dancer2">Dancer2</a>), <a href="https://metacpan.org/module/DBIx::Class">DBIx::Class</a>, and other related technologies.</p> <p>We plan on having another conference in 2015 as well.</p> <h2><a name="dancer_irc_channel_community_grows"></a>Dancer IRC channel community grows</h2> <p>The community of helpful users on the Dancer IRC channel continues to grow! You can find us on <code>irc.perl.org</code> in <code>#dancer</code> or <a href="irc://irc.perl.org/dancer">irc://irc.perl.org/dancer</a> if your system is configured to support <code>irc://</code> links.</p> <p>If you do not regularly use IRC but wish to join us, there is also a web IRC client available at <a href="http://dancer.pm/irc">http://dancer.pm/irc</a> for ease of use.</p> <h2><a name="authors"></a>AUTHORS</h2> <p>David Precious (BIGPRESH)</p> <p>Sawyer X (XSAWYERX)</p> </div>