Please build this for me, yesterday, also!

use Port::Authority;

Port::Authority would be a module which assigns and tracks ports for use with multiple application servers running on the same box. It would need an algorithm, capable of generating reproducible results, to generate port numbers in which are available, maybe it could be based on a namespace or random string + current user (etc), or maybe you could be able to specify the type of algorithm (e.g. UUID).

I need this yesterday for a variety of reason, what do you guys think?

Please build this for me, yesterday!

#!/usr/bin/env perl

=head1 NAME

App-sourcery

=head1 USAGE

# loads all @assets within $path and reports any not referenced in at-least one of the @sources
./sourcery --path=/var/www --asset=*.css --asset=*.js --asset=*.png --source=*.html

=head1 DESCRIPTION

Often times I'll find myself mucking around with an old webapp codebase that has had assets (css, js, images, etc) added to it over and over throughout its life, and being the neat-freak that I am I like to keep my codebase clean.

This (potentially) is a program that f…

The Power of the Sun, in the Palm of your Hand

Over the weekend I worked on a new Perl library, MongoDB::QueryBuilder, a tool which is designed to simplify composing complex and dynamic queries for MongoDB in a chainable and object-oriented fashion.

Seldomly do we see examples of querying a MongoDB datastore of significant size and complexity, however, as your application grows and your data evolves, the questions you’ll want to ask your datastore will become more intricate.

For example. Let’s suppose we have an inventory management application that tracks equipment used in our business. Over time the business grows as does the database and (for whatever reason) we want to ask the database to “give us the (serial number, asset type, and the location manager’s name and phone number) closest to one-of-the-three latitude/longitude coordinates we will provide where the asset has been inspected and placed in a bin-location”. Oh, and limit that result-set by 100 documents.

Using MongoDB::QueryBuilder, the abstraction might resemble the following:

use MongoDB::QueryBuilder;

my $query = MongoDB::QueryBuilder->new(
    only => [
        'serial_number',
        'asset.type.name',
        'asset.location.phone',
        'asset.location.manager.name'
    ],
    and_where => [
        'asset.location.bin$ne' => undef,
        '$or' => [ # this condition will short-circuit
            {'asset.location.latlng$near' => [$a, $b]},
            {'asset.location.latlng$near' => [$c, $d]},
            {'asset.location.latlng$near' => [$e, $f]}
        ]
    ],
    limit => 100
);

Needless to say, manually producing the code to query the database would be a bit more involved. Another noteworthy feature is that the query-builder object is chainable which allows you to create classes that will return a result-set.

For example. Considering the aforementioned scenario.

package MyApp::Inventory::Assets;

use MongoDB::QueryBuilder;

has 'query';
sub _build_query { MongoDB::QueryBuilder->new }

sub has_been_inspected {
    my $self = shift;
    $self->query->and_where('asset.location.bin$ne' => undef);
    return $self;
}

sub is_located_near {
    my $self = shift;
    $self->query->and_where('asset.location.latlng$near' => [@_]);
    return $self;
}

sub limit {
    my $self = shift;
    $self->query->limit($_[0] || 100);
    return $self;
}

package main;

my $assets = MyApp::Inventory::Assets->new;

my $cursor = $assets->limit(25)->has_been_inspected;

while (my $asset = $cursor->next) {
    say $asset->{serial_number};
}

.. I rushed through the demonstration, sorry. I’m extremely busy these days. I hope this module will be of as-much use to others as it is to me (at-the-moment).

The end.

Form Rendering: Why Do We Even Bother?

Over the holiday I decided to do some development work even-though I had promised myself I wouldn't work on any open-source projects until all my commercial projects were completed.

I was bored, and since the alcohol and party-favors had lost there seductiveness, I thought I might revisit my super-secret-open-source-software-todo-list (we've all got one). I was looking for something complex enough to hold my interest yet simple enough to implement or at-least get a proof-of-concept out.

Since I've been doing a bunch of work on Validation::Class lately, I decided to work on an idea for a form field rendering plugin. First I'd like to exclaim, "I hate all-inclusive-html-form-handling-libraries", maybe not hate them but I strongly disagree with the premise upon which they are built.

Validation::Class::Plugin::FormFields is a plugin for Validation::Class which can leverage your validation class field definitions to render HTML form elements. Currently, the plugin is intentionally lacking in sophistication in an attempt to take as few liberties as possible (taking liberties is what makes most form renders suck).

Validation::Class::Plugin::FormFields is not an HTML form handler, nor is it an HTML form builder, renderer, construction kit, or framework. It merely renders a single HTML element at-a-time with as-little-markup-as-possible using the state of the associated validation class to maintain the state of the HTML form field.

Why render fields individually and not the entire form? HTML form handling is a heavily opinionated subject and the following reflects my opinion. HTML form rendering (done literally) has too many constraints and considerations to ever be ideally implemented. Consider the following; It's been tried many many times before and there are many different libraries as a result; It's never done quite right; There are too many conflicting contexts (e.g. css, js, security and identification, etc), i.e., CSS wants the form configured a certain way for styling purposes, JS wants the form configured a certain way for introspection purposes, the APP (and possibly the form renderer) wants the form configured a certain way for processing purposes, etc.

So why do we continue to try? "HTML forms are like werewolves and developers love silver bullets"(tm), but bullets are actually made out of lead, not silver. So how do you kill werewolves with lead? Protip, not by shooting them, obviously. I'd argue that we never really wanted complete form rendering anyway, what we actually wanted was a simple way to reduce the tedium and repetitiveness that comes with creating HTML form elements and handling submission and validation of the resulting data. We keep getting it wrong because we keep trying to build on top of the same misconceptions.

An HTML form is predominantly a UI by-product, and in large organizations (especially those which have segmented UI/ENG development teams) an HTML form and it's structure, layout, and markup are typically determined by the UI developers. Many HTML form renders are not viable simply because they impose UI decisions or require to much engineering to conform to the UI specifications.

So maybe we should backup a bit and try something different. In my opinion, the generating of HTML elements individually is much less constrained and definitely much easier to implement.

A Killer Feature for Mojolicious

I just thought of a truly killer feature for Mojolicious. You are undoubtedly asking yourself why I don't just share this with the Mojolicious team on IRC or GitHub, etc. Most of you undoubtedly already know the answer to that, but I digress.

Many shops that I've worked with have this concept generally referred to as content-injection or template filtering depending on how you go about it. It is basically a means of hooking into template rendering after the template has been rendered but before it has been output (or otherwise used by the application).

The problem this solves is that some things are best left to be handled by the template, while other things are best done by using regex or a DOM parser.

I believe Mojolicious is at a unique advantage to offer something like this out-of-the-box because it has it's own templating system -and- it's own DOM parser. An example of a mojolicious template using the technique I'm describing could be as follows:

__DATA__

@@ alter_me.html.ep
<!DOCTYPE html>
<html>
  <head>
    <title>Alter me!</title>
  </head>
  <body>You've been altered.</body>
</html>

% filter begin
% my ($c, $dom) = @_; # is passed the DOM parser using rendered template
  $dom->at('title')->replace_content('because I can');
% end

@@ further_convince_me.html.ep
<!DOCTYPE html>
<html>
  <head>
    <title>Convince me!</title>
  </head>
  <body>
    <select id="industry" value="" name="industry">
      <option id="industry" value="" name="industry">Please Select…</option>
      <option id="industry" value="Aerospace &amp; Defense" name="industry">Aerospace &amp; Defense</option>
      <option id="industry" value="Agriculture" name="industry">Agriculture</option>
      <option id="industry" value="Automotive &amp; Transport" name="industry">Automotive &amp; Transport</option>
      <option id="industry" value="Banking" name="industry">Banking</option>
      <option id="industry" value="Beverages" name="industry">Beverages</option>
      <option id="industry" value="Business Services" name="industry">Business Services</option>
      <option id="industry" value="Charitable Organizations" name="industry">Charitable Organizations</option>
      <option id="industry" value="Chemicals" name="industry">Chemicals</option>
      <option id="industry" value="Computer Hardware" name="industry">Computer Hardware</option>
      <option id="industry" value="Computer Services" name="industry">Computer Services</option>
      <option id="industry" value="Computer Software" name="industry">Computer Software</option>
      <option id="industry" value="Construction" name="industry">Construction</option>
      <option id="industry" value="Consumer Products Manufacturers" name="industry">Consumer Products Manufacturers</option>
      <option id="industry" value="Consumer Services" name="industry">Consumer Services</option>
      <option id="industry" value="Cultural Institutions" name="industry">Cultural Institutions</option>
      <option id="industry" value="Education" name="industry">Education</option>
      <option id="industry" value="Electronics" name="industry">Electronics</option>
      <option id="industry" value="Energy &amp; Utilities" name="industry">Energy &amp; Utilities</option>
      <option id="industry" value="Entertainment" name="industry">Entertainment</option>
      <option id="industry" value="Environmental Services &amp; Equipment" name="industry">Environmental Services &amp; Equipment</option>
      <option id="industry" value="Financial Services" name="industry">Financial Services</option>
      <option id="industry" value="Food" name="industry">Food</option>
      <option id="industry" value="Foundations" name="industry">Foundations</option>
      <option id="industry" value="Government" name="industry">Government</option>
      <option id="industry" value="Health Care" name="industry">Health Care</option>
      <option id="industry" value="Industrial Manufacturing" name="industry">Industrial Manufacturing</option>
      <option id="industry" value="Insurance" name="industry">Insurance</option>
      <option id="industry" value="Leisure" name="industry">Leisure</option>
      <option id="industry" value="Media" name="industry">Media</option>
      <option id="industry" value="Membership Organizations" name="industry">Membership Organizations</option>
      <option id="industry" value="Metals &amp; Mining" name="industry">Metals &amp; Mining</option>
      <option id="industry" value="Pharmaceuticals" name="industry">Pharmaceuticals</option>
      <option id="industry" value="Real Estate" name="industry">Real Estate</option>
      <option id="industry" value="Retail" name="industry">Retail</option>
      <option id="industry" value="Security Products &amp; Services" name="industry">Security Products &amp; Services</option>
      <option id="industry" value="Telecommunications Equipment" name="industry">Telecommunications Equipment</option>
      <option id="industry" value="Telecommunications Services" name="industry">Telecommunications Services</option>
      <option id="industry" value="Transportation Services" name="industry">Transportation Services</option>
      <option id="industry" value="Technology" name="industry">Technology</option>
      <option id="industry" value="Other" name="industry">Other</option>
  </select>
  </body>
</html>

% filter begin
% my ($c, $dom) = @_;
  $dom->at('#industry option[value*="'. $c->param('industry') .'"]')->attrs(selected => 'selected');
% end