<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
    <title>Catalyzed.org</title>
    <link rel="alternate" type="text/html" href="http://www.catalyzed.org/" />
    <link rel="self" type="application/atom+xml" href="http://www.catalyzed.org/atom.xml" />
    <id>tag:www.catalyzed.org,2009-04-13://1</id>
    <updated>2009-12-03T19:40:11Z</updated>
    <subtitle>A Catalyst and Perl Blog</subtitle>
    <generator uri="http://www.sixapart.com/movabletype/">Movable Type Pro 4.25</generator>

<entry>
    <title>Look at Padre!</title>
    <link rel="alternate" type="text/html" href="http://www.catalyzed.org/2009/12/look-at-padre.html" />
    <id>tag:www.catalyzed.org,2009://1.77</id>

    <published>2009-12-03T16:37:17Z</published>
    <updated>2009-12-03T19:40:11Z</updated>

    <summary>For many years the favored editor for Perl developers fell under the same umbrella as the favored editor in *nix. A major fight between Vi and Emacs, and all the other options trailing behind somewhere. Over the past year, a...</summary>
    <author>
        <name>Jay Kuri</name>
        <uri>http://www.catalyzed.org/mt/mt-cp.cgi?__mode=view&amp;blog_id=1&amp;id=1</uri>
    </author>
    
        <category term="Perl" scheme="http://www.sixapart.com/ns/types#category" />
    
    <category term="cpan" label="cpan" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="padre" label="padre" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="perl" label="perl" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en" xml:base="http://www.catalyzed.org/">
        <![CDATA[<p>For many years the favored editor for Perl developers fell under the same umbrella as the favored editor in *nix.  A major fight between Vi and Emacs, and all the other options trailing behind somewhere.  </p>

<p>Over the past year, a team of developers has been working to change that.  The result is the Padre editor, or the <strong>P</strong>erl <strong>A</strong>pplication <strong>D</strong>evelopment and <strong>R</strong>efactoring <strong>E</strong>nvironment.  The Padre team recently released their 0.5 revision and let me tell you, <strong><em>it is fantastic.</em></strong> </p>

<p>With the 0.5 release there are two particularly interesting developments.  They are a <a href="http://ali.as/Padre.dmg">Mac standalone package</a> and a self-contained <a href="http://padre.perlide.org/download.html">Windows package</a>. This makes Padre extremely easy to install on the two most common desktop systems and puts it on level ground with all your other editing options.  If you don't read another word, grab a copy and try it.
* (... screenshot after the break)*</p>
]]>
        <![CDATA[<p>Being a long time vi user (And more recently a Textmate convert) I was not really in the market for a new editor.  That said, the new release is a vast improvement over the Padre of even just a few months ago.  In my opinion Padre is 100% ready for daily use, and the Padre team are committed to improving it even further. </p>

<p>Kudos to the Padre team.  Padre 0.5 has done what I thought was unthinkable, it has threatened to topple Textmate as my primary editor.  My prediction the 1.0 release of Padre will be the gold standard editor for Perl developers.  It's already well on it's way.  </p>

<p>If you haven't tried it, grab the <a href="http://ali.as/Padre.dmg">package</a> for your <a href="http://padre.perlide.org/download.html">system</a> (or do the install via CPAN) and take it for a spin.  You won't be disappointed.</p>

<p>Oh, and as promised:</p>

<p><span class="mt-enclosure mt-enclosure-image" style="display: inline;"><a href="http://www.catalyzed.org/assets_c/2009/12/padre-45.html" onclick="window.open('http://www.catalyzed.org/assets_c/2009/12/padre-45.html','popup','width=964,height=640,scrollbars=no,resizable=no,toolbar=no,directories=no,location=no,menubar=no,status=no,left=0,top=0'); return false"><img src="http://www.catalyzed.org/assets_c/2009/12/padre-thumb-450x298-45.png" width="450" height="298" alt="padre.png" class="mt-image-center" style="text-align: center; display: block; margin: 0 auto 20px;" /></a></span></p>
]]>
    </content>
</entry>

<entry>
    <title>Fnargh::Form::Auto (Soon to be HTML::FormHandler::Reflector::DBIC)</title>
    <link rel="alternate" type="text/html" href="http://www.catalyzed.org/2009/11/fnarghformauto-soon-to-be-htmlformhandlerreflectordbic.html" />
    <id>tag:www.catalyzed.org,2009://1.75</id>

    <published>2009-11-13T16:49:48Z</published>
    <updated>2009-11-13T22:31:33Z</updated>

    <summary>I&apos;ve never really liked dealing with creating forms. You have to write a butt load of tedious HTML, validate it, and then return error messages as needed. If you want it to be fancy and pretty, you have to write...</summary>
    <author>
        <name>Devin Austin</name>
        <uri>http://www.catalyzed.org/mt/mt-cp.cgi?__mode=view&amp;blog_id=1&amp;id=2</uri>
    </author>
    
        <category term="Catalyst" scheme="http://www.sixapart.com/ns/types#category" />
    
        <category term="Perl" scheme="http://www.sixapart.com/ns/types#category" />
    
    <category term="catalyst" label="catalyst" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="dbixclass" label="dbix::class" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="formhandler" label="formhandler" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="forms" label="forms" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="html" label="html" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="htmlformhandler" label="html::formhandler" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="moose" label="Moose" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en" xml:base="http://www.catalyzed.org/">
        <![CDATA[<p>I've never really liked dealing with creating forms.  You have to write a butt load of tedious HTML, validate it, and then return error messages as needed.  If you want it to be fancy and pretty, you have to write a bunch of CSS to put your error messages where you want and make them shiny.  Luckily, there are <a href="http://search.cpan.org/~cfranks/HTML-FormFu-0.05001/lib/HTML/FormFu.pm">things</a> <a href="http://search.cpan.org/~markstos/Data-FormValidator-4.63/lib/Data/FormValidator.pm">to</a> <a href="http://search.cpan.org/~gshank/HTML-FormHandler-0.28001/lib/HTML/FormHandler.pm">handle</a> <a href="http://search.cpan.org/~hank/Form-Processor-0.19/lib/Form/Processor.pm">this</a>.</p>

<p>Being a Moose fanatic, I am most partial to the latter, <a href="http://search.cpan.org/~gshank/HTML-FormHandler-0.28001/lib/HTML/FormHandler.pm">HTML::FormHandler</a>.  It's extremely easy to use, and requires zero configuration file crap.  You get validation as Moose types/constraints, it's very cool.</p>

<p>So, back to me hating having to build forms.  This includes building a form for something that already has enough information to build a form <em>from</em>, say, a database schema.  My dream has been to be able to read a database schema (preferably <a href="http://search.cpan.org/~ribasushi/DBIx-Class-0.08112/lib/DBIx/Class.pm">DBIx::Class</a>), and generate a form based on the data types specified in said schema.  This is completely doable! Heck, even <em>I</em> drafted up some code to get some preliminary form fields from a database.  The following is from the CMS I'm working on, using HTML::FormHandler and DBIx::Class to get things done.  This is extremely proof of concept code, and doesn't actually have any logic to determine what <em>kind</em> of form element a given schema entity should be.  That, however, should be fairly trivial and I will undoubtedly be writing a follow up to that effect.  Go here to check out the source: <a href="http://gist.github.com/230652">http://gist.github.com/230652</a>. Enjoy.</p>
]]>
        

    </content>
</entry>

<entry>
    <title>Fun With JSON Config Files!</title>
    <link rel="alternate" type="text/html" href="http://www.catalyzed.org/2009/11/fun-with-json-config-files.html" />
    <id>tag:www.catalyzed.org,2009://1.73</id>

    <published>2009-11-09T07:24:32Z</published>
    <updated>2009-11-09T07:34:20Z</updated>

    <summary>So I recently decided to convert the config file for a new app I&apos;m working on to JSON. Why? Well for one, it&apos;s a lot easier to express perl data structures in, and it&apos;s also extremely easy to read. Check...</summary>
    <author>
        <name>Devin Austin</name>
        <uri>http://www.catalyzed.org/mt/mt-cp.cgi?__mode=view&amp;blog_id=1&amp;id=2</uri>
    </author>
    
    <category term="catalyst" label="catalyst" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="config" label="config" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="json" label="json" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en" xml:base="http://www.catalyzed.org/">
        <![CDATA[<p>So I recently decided to convert the config file for a new <a href="http://github.com/dhoss/fnargh">app</a> I'm working on to JSON.  Why?  Well for one, it's a lot easier to express perl data structures in, and it's also extremely easy to read.  Check it out!</p>

<pre><code>{
    "name": "Fnargh",
    "Model::Database": {
        "connect_info": [
            "dbi:SQLite:fnargh.db",
            "",
            "" 
        ] 
    } ,
    "session": {
        "flash_to_stash": "1" 
    }
}
</code></pre>

<p>Started off a bit rocky, but thanks to <a href="http://www.jsonlint.com">http://www.jsonlint.com</a> I was able to pick at my config file until it was valid.  It formats it nicely for you as well!</p>

<p>The best part? You can take the perl data that you use in your Catalyst app, and do something like this: </p>

<pre>
squishface:~ dhoss$ perl -e "use JSON; print to_json({ my_data => [ 'thing1', 'thing2', 'thing3' ] });"
{"my_data":["thing1","thing2","thing3"]}
</pre>

<p>JSON formatted for your config! </p>
]]>
        

    </content>
</entry>

<entry>
    <title>System Call Debugging with (s|k|d(trace|truss)) (that&apos;s strace, ktrace, dtrace or dtruss)</title>
    <link rel="alternate" type="text/html" href="http://www.catalyzed.org/2009/11/system-call-debugging-with-skdtracetruss-thats-strace-ktrace-dtrace-or-dtruss.html" />
    <id>tag:www.catalyzed.org,2009://1.70</id>

    <published>2009-11-06T19:17:00Z</published>
    <updated>2009-11-06T19:07:57Z</updated>

    <summary>Recently while working on getting tests done for Catalyst::Devel so it could be shipped, and I absolutely could not figure out how to get the test for the development server to work. So, I queried #catalyst-dev about it, and my...</summary>
    <author>
        <name>Devin Austin</name>
        <uri>http://www.catalyzed.org/mt/mt-cp.cgi?__mode=view&amp;blog_id=1&amp;id=2</uri>
    </author>
    
        <category term="Catalyst" scheme="http://www.sixapart.com/ns/types#category" />
    
        <category term="Perl" scheme="http://www.sixapart.com/ns/types#category" />
    
    <category term="calls" label="calls" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="catalyst" label="catalyst" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="debugging" label="debugging" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="devel" label="devel" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="dtruss" label="dtruss" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="ipc" label="ipc" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="strace" label="strace" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="system" label="system" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en" xml:base="http://www.catalyzed.org/">
        <![CDATA[<p>Recently while working on getting tests done for Catalyst::Devel so it could be shipped, and I absolutely could not figure out how to get the test for the development server to work.  So, I queried #catalyst-dev about it, and my good friend <a href="http://www.shadowcat.co.uk/blog/matt-s-trout/">mst</a> told me to use strace to figure out what was going on behind the scenes.  In this case, I used dtruss since I'm a Mac user and for some reason the usual *nix tool doesn't work on the Mac platform.</p>

<p>Basically, what went down was this: </p>

<ol>
<li>sudo dtruss -f prove -l t/author/optional_http-server.t</li>
<li>a whole load of rather cryptic output (see below for a snippet)</li>
<li>analysis and correction</li>
</ol>

<p>What I found was that since the Catalyst development server is chock full of system calls that are chock full of information on what's going on (and going wrong) behind the scenes, dtruss was the perfect tool for grabbing messages being relayed between processes and not necessarily being spewed out to my terminal.  Here's a small snippet of the problem area I (well, mst actually) discovered:</p>

<p><code>
46665/0x117e04:  stat64("/opt/local/lib/perl5/vendor<em>perl/Catalyst/ScriptRunner.pm\0", 0x7FFF5FBFEE90, 0xFFFFFFFFFFFFFFFF)       = -1 Err#2
46665/0x117e04:  stat64("/opt/local/lib/perl5/5.8.9/darwin-2level/Catalyst/ScriptRunner.pmc\0", 0x7FFF5FBFEF20, 0x0)         = -1 Err#2
46665/0x117e04:  stat64("/opt/local/lib/perl5/5.8.9/darwin-2level/Catalyst/ScriptRunner.pm\0", 0x7FFF5FBFEE90, 0xFFFFFFFFFFFFFFFF)       = -1 Err#2
46665/0x117e04:  stat64("/opt/local/lib/perl5/5.8.9/Catalyst/ScriptRunner.pmc\0", 0x7FFF5FBFEF20, 0x0)       = -1 Err#2
46665/0x117e04:  stat64("/opt/local/lib/perl5/5.8.9/Catalyst/ScriptRunner.pm\0", 0x7FFF5FBFEE90, 0xFFFFFFFFFFFFFFFF)         = -1 Err#2
46665/0x117e04:  stat64("./Catalyst/ScriptRunner.pmc\0", 0x7FFF5FBFEF20, 0x0)    = -1 Err#2
46665/0x117e04:  stat64("./Catalyst/ScriptRunner.pm\0", 0x7FFF5FBFEE90, 0xFFFFFFFFFFFFFFFF)      = -1 Err#2
46665/0x117e04:  write</em>nocancel(0x2, "Can't locate Catalyst/ScriptRunner.pm in @INC (@INC contains: /Users/dhoss/web-devel/Cat-Runtime-5.8/t/author/../../lib /Users/dhoss/web-devel/Cat-Runtime-5.8/lib /opt/local/lib/perl5/site<em>perl/5.8.9/darwin-2level /opt/local/lib/perl5/site</em>perl/5.8.9 /opt/", 0x2D0)
</code></p>

<p>That's just a snippet.  Somewhat cryptic, but it's <em>all</em> right there. Check out this line: <code>46665/0x117e04:  write<em>nocancel(0x2, <strong>"Can't locate Catalyst/ScriptRunner.pm in @INC (@INC contains: /Users/dhoss/web-devel/Cat-Runtime-5.8/t/author/../../lib /Users/dhoss/web-devel/Cat-Runtime-5.8/lib /opt/local/lib/perl5/site</em>perl/5.8.9/darwin-2level /opt/local/lib/perl5/site_perl/5.8.9 /opt/"</strong>, 0x2D0)</code>.  Derp!  I was running this test in Catalyst::Runtime trunk/ that doesn't have my ScriptRunner classes merged yet.  So, I reran this test (using dtruss -f again) under my branch, found out that the options being passed to the development server were incorrect, corrected, svn committed, and can now take another step (finally) toward shipping Catalyst::Devel!</p>
]]>
        

    </content>
</entry>

<entry>
    <title>MT+Plack on nginx = love</title>
    <link rel="alternate" type="text/html" href="http://www.catalyzed.org/2009/11/mtplack-on-nginx-love.html" />
    <id>tag:www.catalyzed.org,2009://1.71</id>

    <published>2009-11-06T18:45:00Z</published>
    <updated>2009-11-06T22:02:50Z</updated>

    <summary>There&apos;s a new kid on the block for web application development, and it&apos;s called Plack. I&apos;m not going to go into depth on explaining it here, as the website listed previously does a stellar job of that, but I&apos;m going...</summary>
    <author>
        <name>Devin Austin</name>
        <uri>http://www.catalyzed.org/mt/mt-cp.cgi?__mode=view&amp;blog_id=1&amp;id=2</uri>
    </author>
    
        <category term="Catalyst" scheme="http://www.sixapart.com/ns/types#category" />
    
        <category term="Perl" scheme="http://www.sixapart.com/ns/types#category" />
    
    <category term="catalyst" label="catalyst" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="movable" label="movable" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="plack" label="plack" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="psgi" label="psgi" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="type" label="type" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en" xml:base="http://www.catalyzed.org/">
        <![CDATA[<p>There's a new kid on the block for web application development, and it's called <a href="http://www.plackperl.org">Plack</a>.  I'm not going to go into depth on explaining it here, as the website listed previously does a stellar job of that, but I'm going to explain and talk about what got me started on it, and what made me love it.</p>

<p>I've been a pretty avid <a href="http://www.movabletype.org">MovableType</a> fan since I first got it running.  It Just Works(tm).  I've always ran it under Apache, however, so when I made the big and permanent transition to nginx, I was befuddled as to how to get it to run under my new toy. A kind sir by the name of <a href="http://www.coldhardcode.com">Jay Shirley</a> recommended I use Plack to get my old love running under nginx.  I talked to the creator of this mystical new being, <a href="http://bulknews.vox.com/">Tatsuhiko Miyagawa</a> on its IRC channel, #plack.  We went back and forth for a few iterations until w(h)e got his mt.psgi script (listed <a href="http://gist.github.com/227584">here</a>) working so that MT would be okay with new installs. </p>

<p>The result: A mostly working MovableType installation!  The only problem is, I have a MT database dump from MySQL that I either A) need to convert the data portion of the dump to something PostgreSQL (what I've converted to for life) will like, or B) suck it up and set up a MySQL instance for this one app. MT itself runs just fine, it's completely my fault that anything on the database side doesn't work.  Miyagawa reports that previous installations work just fine with this, so, as I said, I will need to investigate which route I want to take to get this data into a database for MT.</p>

<p>Either way, my experience was fantastic.  Plack is really easy to set up.  All the work is done for you, and you can still run things under FastCGI (if you're so inclined).  It's a great bridge between server software and a web application, so we're not stranded somewhere in between holding on to the connecting ends of a bridge screaming "HOLY FUCK THIS HURTS AND GOD I HOPE IT HOLDS TOGETHER IF WE HAVE TO CHANGE ANYTHING".</p>

<p>Kudos to you miyagawa, I'm pretty sold on using this from here on out for web apps I write in the future (mostly Catalyst based, for which we have <a href="http://search.cpan.org/~miyagawa/Catalyst-Engine-PSGI-0.05/lib/Catalyst/Engine/PSGI.pm">Catalyst::Engine::PSGI</a>!)</p>

<p><strong>UPDATE:</strong> Here's the configuration I'm using for nginx: <a href="http://wiki.catalyzed.org/codesamples/dhoss/plack_nginx_conf">http://wiki.catalyzed.org/codesamples/dhoss/plack<em>nginx</em>conf</a></p>
]]>
        

    </content>
</entry>

<entry>
    <title>Rendering TT on command with Catalyst</title>
    <link rel="alternate" type="text/html" href="http://www.catalyzed.org/2009/11/rendering-tt-on-command-with-catalyst.html" />
    <id>tag:www.catalyzed.org,2009://1.72</id>

    <published>2009-11-04T22:19:59Z</published>
    <updated>2009-11-05T07:05:14Z</updated>

    <summary>Scenario You&apos;re trying to send an email (via Catalyst::Plugin::Email, MIME::Lite, Email::Sender::Simple, your choice) and you would like to be able to stuff your canned email messages into their respective Template::Toolkit templates. One way to do this is use Catalyst::View::Email::Template, which...</summary>
    <author>
        <name>Devin Austin</name>
        <uri>http://www.catalyzed.org/mt/mt-cp.cgi?__mode=view&amp;blog_id=1&amp;id=2</uri>
    </author>
    
        <category term="Catalyst" scheme="http://www.sixapart.com/ns/types#category" />
    
        <category term="Perl" scheme="http://www.sixapart.com/ns/types#category" />
    
    <category term="catalyst" label="catalyst" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="email" label="email" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="render" label="render" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="template" label="template" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="toolkit" label="toolkit" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en" xml:base="http://www.catalyzed.org/">
        <![CDATA[<h1>Scenario</h1>

<p>You're trying to send an email (via Catalyst::Plugin::Email, MIME::Lite, Email::Sender::Simple, your choice) and you would like to be able to stuff your canned email messages into their respective Template::Toolkit templates. One way to do this is use Catalyst::View::Email::Template, which is pretty cool, but forces you to use Catalyst::View::Email, which some people aren't too keen on. So, you can do something like this:</p>

<pre><code>sub email_stuff : Local {
    my ($self, $c, $review_id) = @_;

    $c-&gt;stash(
        review_url    =&gt; $c-&gt;uri_for("/thingy/${review_id}"),
        status_msg =&gt; "Thank you for your feedback!",
        template      =&gt; 'view_all.tt2',
    );

    $c-&gt;email(
        header =&gt; [
            From    =&gt; $c-&gt;config-&gt;{'from'},
            To      =&gt; $c-&gt;config-&gt;{'to'},
            Subject =&gt; "Emaily stuff!",
        ],
        body =&gt; $c-&gt;view('TT')-&gt;render($c, 'review.tt2'),
    );

    return; 
}
</code></pre>

<p>The line <code>$c->view('TT')->render($c, 'review.tt2')</code> allows you to have your view render your template for you using all the things you put into <code>$c->stash</code>. Pretty cool eh?</p>
]]>
        

    </content>
</entry>

<entry>
    <title>Coming soon: DBIx::Class::Tree::Recursive</title>
    <link rel="alternate" type="text/html" href="http://www.catalyzed.org/2009/10/coming-soon-dbixclasstreerecursive.html" />
    <id>tag:www.catalyzed.org,2009://1.69</id>

    <published>2009-10-13T17:10:08Z</published>
    <updated>2009-10-13T17:58:14Z</updated>

    <summary>I&apos;ve had a need for some time now to have an ability to make recursive calls to an SQL database with out completely melting down my database server using literal recursion for SQL calls (namely, a for loop that does...</summary>
    <author>
        <name>Devin Austin</name>
        <uri>http://www.catalyzed.org/mt/mt-cp.cgi?__mode=view&amp;blog_id=1&amp;id=2</uri>
    </author>
    
        <category term="Perl" scheme="http://www.sixapart.com/ns/types#category" />
    
    <category term="adjacency" label="adjacency" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="databases" label="databases" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="dbixclass" label="DBIx::Class" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="list" label="list" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="materialized" label="materialized" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="nested" label="nested" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="path" label="path" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="rdbms" label="rdbms" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="recursive" label="recursive" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="sets" label="sets" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="tree" label="tree" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="trees" label="trees" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en" xml:base="http://www.catalyzed.org/">
        <![CDATA[<p>I've had a need for some time now to have an ability to make recursive calls to an SQL database with out completely melting down my database server using literal recursion for SQL calls (namely, a for loop that does a select for EACH record I need to retrieve, easy to see how things would go up in flames.), and have played around with a few ideas.</p>

<p>There are nested sets, which are kind of cool, because they make a nice bridge between programming's want for trees/graphs, and SQLs stickler for their organized sets.  It's a neat concept, having the immediate knowledge of what is to the left and right of a given "node", but this makes it KILLER to make inserts into.  You have a whole ton of knowledge to gather before you even insert any data for a new record.</p>

<p>Adjacency lists are a bit like nested sets, but they pretty much keep track of the parent id as opposed to what's on each side of the node.  They're fast, but once again, munging must be done before you can get correct/normalized results and good inserts.</p>

<p>Materialized paths are currently my favorite, but by no means are they the be all end all solution.  Especially since different RDBMSes are better optimized for other such methods (Oracle's CONNECT BY, for instance).  Materialized paths are pretty much just a path up to the node you are selecting of its parents.  For instance: </p>

<p>1.2.1.1.3.5 </p>

<p>would be the 5th child of the 3rd child of the 1st child of the 1st child of the 2nd child of the parent whose primary key is 1.  It's pretty simple.  Selecting from and inserting into with this is pretty easy as well.</p>

<p>DBIC::T::Recursive is probably going to, in one way or another, make use of each of these (maybe more, given there is likely going to be a -handle => $method<em>goes</em>here where $method<em>goes</em>here could be matpath, adjacency list, nested set, connect by, etc.), and will eventually be optimized per DBMS to suit the best type of recursion.</p>

<p>The best part, it will all be abstracted away and will Just Work.  It's going to be a mighty project, but I'm looking forward to making more progress on it.</p>
]]>
        

    </content>
</entry>

<entry>
    <title>GSOC: Post Mortem</title>
    <link rel="alternate" type="text/html" href="http://www.catalyzed.org/2009/10/gsoc-post-mortem.html" />
    <id>tag:www.catalyzed.org,2009://1.68</id>

    <published>2009-10-05T18:35:25Z</published>
    <updated>2009-10-09T02:09:48Z</updated>

    <summary>So, I recently finished (for certain values of &quot;finished&quot;) my Google Summer of Code grant. It was very fun, stressful, and eye opening. I learned a LOT. A lot more than I could possibly encompass in a single (or infinite,...</summary>
    <author>
        <name>Devin Austin</name>
        <uri>http://www.catalyzed.org/mt/mt-cp.cgi?__mode=view&amp;blog_id=1&amp;id=2</uri>
    </author>
    
        <category term="Catalyst" scheme="http://www.sixapart.com/ns/types#category" />
    
        <category term="Perl" scheme="http://www.sixapart.com/ns/types#category" />
    
    <category term="catalyst" label="catalyst" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="catalysthelper" label="catalyst::helper" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="code" label="code" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="google" label="google" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="lifestyle" label="lifestyle" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="perl" label="perl" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="summer" label="summer" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en" xml:base="http://www.catalyzed.org/">
        <![CDATA[<p>So, I recently finished (for certain values of "finished") my <a href="http://socghop.appspot.com/student_project/show/google/gsoc2009/dukeleto/t124022226631">Google Summer of Code</a> grant.  It was very fun, stressful, and eye opening.  I learned a LOT.  A lot more than I could possibly encompass in a single (or infinite, really) blog post, and way more than the realm of computer hackery involves.</p>

<p>I remember starting the project, getting my SVN commit bit, svn co'ing the code, and going "Holy shit. I am in WAY over my head."  But I kept at it. I was stubborn, and MOST important, asked incessant questions, probably much to the chagrin of my mentor and the very kind souls that held my hand through all of this.  </p>

<p>I finally got my head wrapped around most of the code, and went, "hey! I kick ass! I'm contributing, I'm smart, I'm getting things done, I'm good enough, and gosh darn it people like me!."  Then we got into stage two.  The process preeeetty much started all over again.  I had no idea where I was, I was writings tests for things I didn't quite understand, and did a great deal of staring at my computer screen.  I wasn't, however, committing to the wrong places or fucking up the repo (as much) anymore!  Progress was being made.  Slow, but there.</p>
]]>
        <![CDATA[<p>This really opened up a lot of doors for me.  It got my name out, it got people in touch with me I've never heard of before, opened doors I'd never <em>thought</em> of before, and one of the most incredible bits was it got me a job with the most kind Mr. Jay Kuri, the overlord of this here site.  It put me on track to having a career in this field, to be quite frank.</p>

<p>Things continued to progress, up and down, good things happened, bad things happened, I got stressed, I conquered things.  Not NEARLY enough was done in my opinion, and I take complete blame for this.  I can't blame it on yak shaving, because, how much money is made off of yak shaving alone in people's careers on a daily basis? Contracts are often based solely on this concept alone.  It's a necessary skill, just like learning how to milk Google and say "no" to that final beer.  </p>

<p>What DID happen was we got the API cleaned up, got the community aware, involved, and a lacking part of the Helper API some love, and energy.  A lot is left to do, but I've given myself (and many others who have and in the future will contribute) a great platform to go off of.  It's not quite the claim to fame I wanted it to end up to be, but hey, like I said, I learned things here I may never have learned otherwise.</p>

<p>The moral of the story is, software is good/bad.  It takes a long time to get things to a point where the public can use it.  Even then, things break, and horribly.  This is where a true programmer's skills shine, in the trenches, tired, without all his (or her) tools, and some bubble gum and duct tape.  People come and go, and programming is merely a means to an end.  </p>

<p>I've learned that computers and their problems are dealt with using your brain, and if you're lucky, perl.  Even then, it's up to YOU to give perl the right directions and avenues to go down.  Google Summer of Code gave me an insight into this, and in the end, taught me more about the lifestyle of a successful programming community than the programming involved in itself.</p>
]]>
    </content>
</entry>

<entry>
    <title>Software Quality and Value - A mathematical examination</title>
    <link rel="alternate" type="text/html" href="http://www.catalyzed.org/2009/09/software-quality-and-value---a-mathematical-examination.html" />
    <id>tag:www.catalyzed.org,2009://1.66</id>

    <published>2009-09-08T06:17:08Z</published>
    <updated>2009-09-08T18:54:47Z</updated>

    <summary>Software developers often like to think of themselves as artists. We like being unquantifiable and somewhat mysterious. This behavior has roots in the fact that humans generally like to be thought of as unique and special. It also has roots...</summary>
    <author>
        <name>Jay Kuri</name>
        <uri>http://www.catalyzed.org/mt/mt-cp.cgi?__mode=view&amp;blog_id=1&amp;id=1</uri>
    </author>
    
        <category term="Perl" scheme="http://www.sixapart.com/ns/types#category" />
    
    <category term="analysis" label="analysis" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="development" label="development" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="perl" label="perl" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="quality" label="quality" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="value" label="value" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en" xml:base="http://www.catalyzed.org/">
        <![CDATA[<p>Software developers often like to think of themselves as artists. We like
being unquantifiable and somewhat mysterious. This behavior has roots in the
fact that humans generally like to be thought of as unique and special. It
also has roots in the all-too-common 'Now I got you you SOB' that many
development managers / executives like to play with technical staff (which
usually plays out as 'I know I changed the requirements 5 times since then,
but you said it'd be done by Tuesday!! You bastard!') The natural result of
which is a desire not to give hard estimates so you can avoid being slapped with them later.</p>

<p>The fact of the matter, though, is that applying numbers or at least equations
to the process of software development is not that hard. There are a number of
concepts that are already out there and are fairly commonly accepted that can
be applied toward that goal. Today I want to introduce some of them. I want to
take some of these equations and break them down so that we can understand how
they operate, and how we operate through them.</p>
]]>
        <![CDATA[<p><strong>Authors Note:</strong> <em>Before I begin, I want to point out that a lot of the
components of these equations are very difficult to objectively define. That
is because quality and value are very subjective topics. These equations are
meant more as a thinking tool than a way to determine an exact value. That
said, if you take the time to push this out to its logical conclusion, you
can actually apply numbers to these formulas and come up with some pretty
interesting figures that relate to your project.</em></p>

<p>Let's begin with Value. Value is a concept we are all familiar with. The
things we build or buy have value; our car or bicycle, our meal or beer. We
also value things and people based on our judgements about them. Ask someone
to explain why something has value to them, though, and you are likely to get
a vague answer somewhere between 'I just like it' and a set of personal
judgements about the quality of said item.</p>

<p>There will be a thread, though. Value is practically always defined as a
relationship between Quality and Cost. This relationship can be
<em>(over)</em>simplified to the following equation:</p>

<p><span class="mt-enclosure mt-enclosure-image" style="display: inline;"><img alt="Value.png" src="http://www.catalyzed.org/softwarequality/Value.png" width="300" height="111" class="mt-image-center" style="text-align: center; display: block; margin: 0 auto 20px;" /></span></p>

<p>In order for that to have any meaning, though, we need to be able to quantify
it. This is not exactly easy to do. There are no units of measurement for
Value or Quality. They exist only as perception, and even then are only
meaningful when related to something else.</p>

<h2>Quality</h2>

<p>There is no unit of measurement for Quality. Quality is a
vague thing. It is often hard to describe and can be difficult to nail down. I
have, however, come up with a definition of quality which I find works in
nearly every application of the term. My definition of Quality is "suitability
for its purpose." A thing is generally said to be of excellent quality when
it performs its purpose flawlessly. When a thing is said to be of low
quality, it generally performs its purpose sub-optimally, or not at all. This
definition clearly defines Quality as a range and for the range to be useful, an upper
and lower numeric bound must be defined.</p>

<p>To keep our concept of Quality grounded, we will use a range of 0 to 1. When
judging software using this definition and range of Quality, we will say that
a piece of software that performs every aspect of its purpose exactly the way
it is intended has a Quality of one (1). A Quality of zero (0), by contrast,
does not perform its intended task at all. Obviously, when developing
software, the ideal target is always a Quality of 1. Keep this in mind, we
will use it later.</p>

<h2>Value</h2>

<p>Now let's explore the next element of the equation, value. Value is another
hard to define concept. There is no unit of measurement that is
generally defined for value. It is again a range and is somewhat arbitrary.
In order for our results to be meaningful we need to define a range. When we
speak of the value of a thing, we may say it has no value, or that it has high
value. So, we will use a range that is in keeping with the way we usually use
the word. We will say that if a thing has no value, its value is 0. Let us
say, for the purposes of this subject that a value of 1 is a 'neutral value'
that is neither exceedingly good, nor exceedingly bad. Anything that has a
value that is higher than one (1) is of 'high value.'</p>

<h2>Cost</h2>

<p>Now that we have workable definitions and ranges for Quality and Value, we
only have one component of our initial equation left to define: cost.
Generally speaking, cost can be quantified in terms of money, or time, or a
relation of the two. When developing software, cost is most often quantified
using money. The time element of cost can usually be converted to money by
multiplying the total hours required by the hourly rate of the developer or
developers. Every working developer knows this equation all too well.</p>

<p>So now we have a working definition of cost as well. We have to apply it to
our original equation. In order for it to work, however, we have to remember
that value has a perceptual element as well. Remember that value is judged
based on our concept of what something's cost <em>should</em> be according to some
ideal.</p>

<h2>Ideal cost</h2>

<p>So what is ideal cost? You already know the answer to this. If the actual cost
is what it really takes to get a set of features done, then the ideal cost
would be the minimum required to get those features working. Let's use a web
application as an example. We know that each application has business logic
that is unique and specific to that application, it also has presentation code
that will be specific to that application. In an ideal world, we would only
have to write the code to define that behavior. So our ideal cost is what it
would take to write just the business logic and presentation portion of our
application.</p>

<p>All of this translates to an equation that looks like this:</p>

<p><span class="mt-enclosure mt-enclosure-image" style="display: inline;"><img alt="Value-ideal.png" src="http://www.catalyzed.org/softwarequality/Value-ideal.png" width="583" height="114" class="mt-image-center" style="text-align: center; display: block; margin: 0 auto 20px;" /></span></p>

<p>With this equation, you have a working model for determining value. With our
target Quality as 1, as actual cost approaches ideal cost, our value
approaches 1, or 'good value.' If actual cost is less than ideal cost, value
increases, and likewise if actual cost is more than ideal cost, your value
goes down.</p>

<p>The problem with this equation right now is that it only works if we always use our target of quality level of 1, or highest quality.  As any working developer knows, this
highest level of quality is rarely attained. Unfortunately, this returns us to
the question, how do you define quality with regard to software? We've given
it a range, but it currently has no meaning. In order for our overall equation
to mean anything, quality must be more clearly defined.</p>

<h2>Software Quality Revisited</h2>

<p>There are many ways you can judge a code's quality, but many of them are
subjective. Here we want to focus on as objective measures as possible.
Different people have different preferences, but ultimately there are some
objective areas that can be used nearly universally. For our purposes there
are two areas that define the quality of a chunk of code.</p>

<h3>Functionality</h3>

<p>First and most simply is <em>functionality</em>. Functionality simply answers the
question 'does this code actually provide the feature required in its
entirety?' Functionality is easily determined if you have a complete
specification. You can think of functionality as a percentage. Take the
implemented number of components of a given feature and divide it by the
total components of that same feature according to the spec.</p>

<p>Any professional developer with even a few projects under his belt would agree
that overall code quality tends to suffer when there is an incomplete (or
worse, nonexistent) spec. It is mathematically impossible to solve the value
equation if required functionality remains an unknown.</p>

<p>Note that often people define many other areas to consider when evaluating software quality, for example: reliability, scalability, portability, usability, etc. When it comes
down to it, though, each application will have different requirements for each
of these areas. In this respect, it is clearer to think of these
requirements as feature requirements and thus they fall under the <em>functionality</em> heading in terms of analysis.</p>

<h3>Maintainability</h3>

<p>The second part of software quality is <em>maintainability</em>. Software rarely is
written and never modified, so for any real code quality judgement you have
to look at how easy it will be for the code to be maintained and modified down
the road. In my experience code's maintainability can be defined as a
combination of three elements: <em>documentation</em>, <em>clarity of code</em> and
<em>verifiability of functionality</em>.</p>

<p><strong>Documentation</strong> we are all familiar with. It is the easiest element of code
quality to control, as the author of the code can easily write what the code
does in plain language. Sadly, it is all too often neglected. The level of
documentation required can be somewhat subjective depending on the reader, but
for our purposes we are talking about documentation required for the software
to be well maintained. This includes documentation of the <em>intended function</em>,
as well as the details of how the code functions. Note that this includes both
formal documentation and code comments. We can quantify documentation quality
by comparing the information required to maintain the code with the
information actually present in the form of documentation. This will vary from
developer to developer, but in practice it comes down to something akin to
code coverage testing. In my opinion, if the general purpose of the code is defined, and every function or method is documented in terms of what it expects as arguments, what state (if any) it affects while running, and what it produces as a return value, the
documentation requirement has been met. This, like functionality, can be taken
as a percentage.</p>

<p><strong>Clarity of code</strong> is an assessment of the code itself. Code clarity answers
the question 'How easy is it to determine what the code is doing?' Are
variables well named? Are clever but hard to understand solutions eschewed for
clearer, if more verbose, solutions? When hard to understand solutions are
unavoidable, are there enough code comments to decipher the associated code?
All of this boils down to the question, 'When a change is required to the
code, can you easily determine where and how to make that change?' This is a
difficult one to quantify, but it is not unreasonable to treat it as a 0/1,
yes or no proposition. If another reasonably competent developer (who is unfamiliar with the code) can read it and understand it without requiring additional
explanation or a long code spelunking process, then clarity of code is
achieved, otherwise it is not.</p>

<p><strong>Verifiability of functionality</strong> is the ability to objectively verify that a piece of 
code does what it is supposed to do. Generally speaking, there is one way to
verify functionality: unit tests. In order to achieve maintainable software,
you have to be able to tell whether the maintenance change you just did
damaged the code. In order to do that, you need to have set inputs and expected outputs and you need to have automated tests that verify that the code produces the expected outputs (and side effects) when a given set of inputs are provided.  </p>

<p>If you can not easily verify this for each piece of code your maintenance will be significantly more troublesome. The clearest (and quite significantly discussed) method of evaluating this is 'code coverage' analysis of your tests. Taking your code coverage as a percentage is sufficient for this element.</p>

<h3>Complete definition of Quality</h3>

<p>So, the quality of a given set of code or feature can be said to be the
average of these four elements: <em>functionality, documentation, code clarity</em>
and <em>tests</em>. If you think of each of these elements as a percentage, or a
fraction of 1, then our quality equation becomes:</p>

<p><span class="mt-enclosure mt-enclosure-image" style="display: inline;"><img alt="quality.png" src="http://www.catalyzed.org/softwarequality/quality.png" width="600"  class="mt-image-center" style="text-align: center; display: block; margin: 0 auto 20px;" /></span></p>

<p>Which makes our Value equation:</p>

<p><span class="mt-enclosure mt-enclosure-image" style="display: inline;"><img alt="Complete-Value.png" src="http://www.catalyzed.org/softwarequality/Complete-Value.png" width="471" height="113" class="mt-image-center" style="text-align: center; display: block; margin: 0 auto 20px;" /></span></p>

<h2>Boiling it down</h2>

<p>We now have equations that give us a way to gauge both the quality of software
and its value, but what do we do with them? Well, to begin, anyone in charge
of the completion of a software project now has a way to evaluate the
completeness of a piece of software. We also have a way to compare competing
software packages more objectively. There are likely always to be factors to
consider outside of those we have covered. That said, however, at minimum,
<strong>the quality equation gives us a baseline to evaluate all packages</strong>. If the
values are significantly skewed at the quality level to start, evaluation of
additional factors may be irrelevant.</p>

<p>As developers it is easy to at first be put off by these figures and equations.  It can seem like a recipe for more slapping around by managers who don't understand what development really entails.  I think, however, that this can have the opposite effect.  It provides an unbiased and clear set of criteria for evaluating code quality.  It allows you to base your code creation process on factors that do not change, and it provides a clear business reason for defining specifications ahead of time.  </p>

<p>These formulas provide a way to explain a target for software development that makes our jobs easier.  It also provides a way to explain why the all too common practice of 'We need it now, I don't care how ugly it is' ultimately leads to low quality software and an unmanageable disaster of maintenance.</p>

<p>Obviously, these can only be useful if you can apply them. Next time, I will be covering some of the more interesting implications of these equations.  In the meantime,  I'd love to hear your experiences with development process, selecting software and modules,  and what you've found useful for improving software quality.  Got a thought to share?  Sound off in the comments.</p>
]]>
    </content>
</entry>

<entry>
    <title>Spiderin&apos; - Scraping Information with Web::Scraper</title>
    <link rel="alternate" type="text/html" href="http://www.catalyzed.org/2009/09/spiderin---scraping-information-with-webscraper.html" />
    <id>tag:www.catalyzed.org,2009://1.65</id>

    <published>2009-09-02T11:32:31Z</published>
    <updated>2009-09-06T02:45:23Z</updated>

    <summary>I&apos;m a jerk. I failed to give credit to Kieren Diment who helped me with some of the finer points of this script. Thanks Kieren! Web spiders are not a new idea. A well written spider can gather a whole...</summary>
    <author>
        <name>Devin Austin</name>
        <uri>http://www.catalyzed.org/mt/mt-cp.cgi?__mode=view&amp;blog_id=1&amp;id=2</uri>
    </author>
    
        <category term="Perl" scheme="http://www.sixapart.com/ns/types#category" />
    
    <category term="perl" label="perl" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="scraper" label="scraper" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="spider" label="spider" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="web" label="web" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="webscraper" label="web::scraper" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en" xml:base="http://www.catalyzed.org/">
        <![CDATA[<p><strong>I'm a jerk.  I failed to give credit to Kieren Diment who helped me with some of the finer points of this script.  Thanks Kieren!</strong></p>

<p>Web spiders are not a new idea.</p>

<p>A well written spider can gather a whole lot of data without any labor beyond actually writing it, and in a speedy manner.</p>

<p>I've put together a spider for a recent project I've been working on, using <a href="http://search.cpan.org/~miyagawa/Web-Scraper-0.31/lib/Web/Scraper.pm">Web::Scraper</a>.</p>

<p>So here we go!</p>
]]>
        <![CDATA[<p>Let's walk through the listing.</p>

<p>We're using Smart::Comments so we don't have to add a bunch of print statements around.  </p>

<pre>
#!/usr/bin/env perl
use Smart::Comments;
use warnings;
use strict;
use Web::Scraper;
use URI;
use YAML qw/ Dump /;
use WWW::Mechanize;
use WWW::Mechanize::Link;
use URI::Query;
use URI::Escape;
use IO::File;
</pre>

<p>For starters, we grab the URL we want to hit and scrape using WWW::Mechanize.</p>

<pre>
### On your marks
my $yaml;
my $start_url =  WWW::Mechanize::Link->new( { url =>'your_url_to_scrape'});

### Get Set
my $mech = WWW::Mechanize->new;
</pre>

<p>Here, we loop through our page, and the subsequent pages if there is pagination.</p>

<pre>

### GO!
foreach my $l (@letters) {
    my $base_url = $start_url->url;
    $base_url =~ s/__HERE__/currentLetter=$l/;
    my $page = 1;
    ### Letter: $l

    while ($base_url) {
        ### Page: $page
        $mech->get($base_url);
        my $next = $mech->find_link( text_regex => qr/^Next$/i);

        # Bailout
        $base_url = $next ? $next : undef;

        $page++;

        my @gold        = scrape_some('gold', $mech);

        # bailout condition
        undef $base_url  if (!@gold && !@free && !@nearly_free); # nothing on this or subsequent pages for this loop.
        my @information = (@gold, @free, @nearly_free);
        open my $OUT, ">>", "full.yml";
        print $OUT Dump(@information);
        close $OUT;
    }
}
</pre>

<p>This is the actual Web::Scraper code.  Wonderfully, all we have to do is specify some DOM attributes and Web::Scraper will grab the data as we specify.  TEXT is the text data in the element being searched for and scraped.  @href is the actual link URL.</p>

<pre> 
### All done!

sub scrape_some {
    my ( $list_type, $mech ) = @_;
    my @contractors; # return value
    my $want = scraper {
        process "li.$list_type" , "contractors[]" => scraper { 
            process ".listing_link",   name    => 'TEXT';
            process ".address", address => 'TEXT'; # need to split this up into address, state, postcode,
            process ".phone",               phone   => 'TEXT';
            process ".links",                     website => '@href';
        };
    };
    my $ua = $want->user_agent;
    my $names = $want->scrape( $mech->content, $mech->uri);
    my @ppl = ();
    @ppl = @{$names->{data}} if $names->{data};

    foreach my $p (@ppl) {
        if (exists $p->{website}) {
            my $site = $p->{website};
            my $true_url      = URI->new($site);
            my $query = URI::Query->new($true_url->query);
            my $site_from_query = uri_unescape($query->hash_arrayref->{webSite}->[0]);
            $p->{website} = $site_from_query;
        }
        $p->{type} = $list_type;
        push @contractors, @ppl;
    }
    return @contractors;
}
</pre>

<p>This could definitely be refined, however having not done very many web crawlers in the past, Web::Scraper saved the day for me.</p>
]]>
    </content>
</entry>

<entry>
    <title>Open Flash Chart from Catalyst</title>
    <link rel="alternate" type="text/html" href="http://www.catalyzed.org/2009/08/post.html" />
    <id>tag:www.catalyzed.org,2009://1.63</id>

    <published>2009-08-18T06:30:00Z</published>
    <updated>2009-08-18T12:02:10Z</updated>

    <summary>Recently I was looking for a way to make some snazzy bar charts from a Catalyst application. I have successfully used GD and GD::Graph before, but wanted to try something different this time around. After exploring several possibilities I decided...</summary>
    <author>
        <name>mateu</name>
        <uri>http://www.catalyzed.org/mt/mt-cp.cgi?__mode=view&amp;blog_id=1&amp;id=9</uri>
    </author>
    
        <category term="Catalyst" scheme="http://www.sixapart.com/ns/types#category" />
    
        <category term="Perl" scheme="http://www.sixapart.com/ns/types#category" />
    
    <category term="catalyst" label="Catalyst" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="chart" label="chart" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="openflashchart" label="Open Flash Chart" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="perl" label="Perl" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en" xml:base="http://www.catalyzed.org/">
        <![CDATA[<p>Recently I was looking for a way to make some snazzy bar charts from a Catalyst application.  I have successfully used GD and GD::Graph before, but wanted to try something different this time around.  After exploring several possibilities I decided to have a crack at using <a href="http://teethgrinder.co.uk/open-flash-chart-2/">Open Flash Chart</a> version 2 (OFC2). In this article, I discuss how I integrate Open Flash Chart into a Catalyst application.</p>]]>
        <![CDATA[<h2>Chart Data Source - The Model</h2>

<p>A chart is only useful when it displays some useful data.  Most of the time, this data will be coming from a database somehow, perhaps with some adjustment on the way out.  In my case, the data source is a set of student test scores stored in a database.  I use a <span class="caps">DBI</span>x::Class custom ResultSet classes to get at the data, and then munge it a bit to suit my needs.  As an example, here is how I get at the averages for each of the five sections of the test for an arbitrary school and grade<sup class="footnote"><a href="http://www.catalyzed.org/2009/08/post.html#fn1">1</a></sup>.</p>



<pre>
sub school_section_averages {
    my $self      = shift;
    my $admin_id  = shift;
    my $school_id = shift;

    my $school_section_scores = $self-&gt;search_rs(
        {
            'me.admin_id'             =&gt; $admin_id,
            'student2class.school_id' =&gt; $school_id,
        },
        {
            'select' =&gt; [
                { avg =&gt; 'me.percentage_score' }, 'me.section_id',
                'section.name', 'section.position',
            ],
            'as' =&gt; [
                'average_score', 'section_id',
                'section_name',  'section_position',
            ],
            'join' =&gt; [ 'student2class', 'section' ],
            'group_by' =&gt;
              [ 'me.section_id', 
               'section.name', 
               'section.position', ],
            'order_by' =&gt; ['section.position'],
        }
    );

    my @school_section_averages;
    while ( my $section_average = $school_section_scores-&gt;next ) {
        push @school_section_averages,
          sprintf( &quot;%.0f&quot;, 
                    $section_average-&gt;get_column('average_score') );
    }
    return \@school_section_averages;
}
</pre>

<p>  </p>

<p>I do something similar to get at section averages by classroom teacher which we'll chart later.</p>

<h2>Mediating the Data - The Controller</h2>

<p>In a standard Catalyst controller I acquire the underlying data and ship it to a Private action for further processing<sup class="footnote"><a href="http://www.catalyzed.org/2009/08/post.html#fn2">2</a></sup>.  This processing is where I create a Perl data structure that defines all the attributes of the chart.  This data structure is then transformed into <span class="caps">JSON </span>which is the data format required by Open Flash Chart 2<sup class="footnote"><a href="http://www.catalyzed.org/2009/08/post.html#fn3">3</a></sup>.  Let's see what the structure looks like:</p>



<pre>
    my $chart_data = {
        'bg_colour' =&gt; '#ffffff',
        'y_axis'    =&gt; {
            'tick_length' =&gt; 3,
            'colour'      =&gt; '#d000d0',
            'stroke'      =&gt; 1,
            'max'         =&gt; 100,
            'grid_colour' =&gt; '#00ff00',
            'offset'      =&gt; 0,
            'steps'       =&gt; 10,
        },
        'x_axis' =&gt; {
            'colour' =&gt; '#d000d0',
            'stroke' =&gt; 1,
            'labels' =&gt; {
                'labels' =&gt; $labels,
                'size'   =&gt; 12,
            },
            'grid_colour' =&gt; '#00ff00',
            'tick_height' =&gt; 10
        },
        'elements' =&gt; $elements,
        'title'    =&gt; {
            'text' =&gt; $title,
            'style' =&gt; '{
                             font-size: 20px; 
                             color:black; 
                             font-family: Verdana sans; 
                             text-align: center;
                         }'
        },
        'y_legend' =&gt; {
            'text'  =&gt; 'Percent Correct',
            'style' =&gt; '{color: #736AFF; font-size: 14px;}'
        },
        'tooltip' =&gt; {
            'mouse'      =&gt; 2,
            'stroke'     =&gt; 1,
            'colour'     =&gt; '#000000',
            'background' =&gt; '#ffffff'
        },
    };
</pre>



<p>The three variables <code>$labels</code>, <code>$elements</code> and <code>$title</code> have to be constructed as well, but I've left them out for the sake of clarity.  Suffice it to say that $elements is the most interesting as it defines the actuall chart values and chart styles.  The $elements variable is actually an ArrayRef[HashRef] where the HashRef values could be a scalar or another ArrayRef.  To help ease your head from spinning here is example of one element<sup class="footnote"><a href="http://www.catalyzed.org/2009/08/post.html#fn4">4</a></sup>:</p>



<pre>
{&quot;alpha&quot;:&quot;0.5&quot;,&quot;colour&quot;:&quot;#9933CC&quot;,&quot;text&quot;:&quot;Fergie Liscious&quot;,
&quot;values&quot;:[93,84,92,89,88],&quot;type&quot;:&quot;bar&quot;,&quot;font-size&quot;:12}
</pre>



<p>Once I've packaged up the data into a Perl data structure, I can turn it into <span class="caps">JSON </span>with the help of the <a href="http://search.cpan.org/perldoc?JSON"><span class="caps">JSON </span>module</a> like so:</p>



<pre>
use JSON;
my $json   = new JSON;
my $json_chart_data = $json-&gt;encode($chart_data);
</pre>



<h2>Turning Data into a Chart - The View</h2>

<p>At this point we have put the data into the format needed by <span class="caps">OFC2. </span> Now let's focus on building the view.  The approach I take is to construct a web page via Template Toolkit (TT) that has the necessary Flash and Javascript library links along with the <span class="caps">JSON </span>data embedded in the page.  Here's what the TT template for the page head looks like:</p>


<div style="font-family:Arial, Verdana, sans-serif; font-size: 1.1em; background:#ffffd0; border: 1px solid black; padding:2em; color:black;">
&lt;script type="text/javascript" src="<span>c.uri_for('/static/chart/json2.js') </span>"&gt;&lt;/script&gt;<br />
&lt;script type="text/javascript" src="<span>c.uri_for('/static/chart/swfobject.js') </span>"&gt;&lt;/script&gt;<br />
&lt;script type="text/javascript"&gt;<br />
swfobject.embedSWF("<span>c.uri_for('/static/chart/open-flash-chart-custom.swf') </span>", "ofc_averages_chart", "800", "400",<br />
 "9.0.0", "<span>c.uri_for('/static/chart/expressInstall.swf') </span>");<br />
&lt;/script&gt;

<p>&lt;script type="text/javascript"&gt;</p>

<p>function open_flash_chart_data()<br />
{<br />
&nbsp;&nbsp;    // read data<br />
&nbsp;&nbsp;    return <span class="caps">JSON.</span>stringify(data);<br />
}</p>

<p>function findSWF(movieName) {<br />
&nbsp;&nbsp;  if (navigator.appName.indexOf("Microsoft")!= -1) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;    return window[movieName];<br />
&nbsp;&nbsp;  } else {<br />
&nbsp;&nbsp; &nbsp;&nbsp;   return document[movieName];<br />
 &nbsp;&nbsp; }<br />
}<br />
    <br />
var data = <span>json_chart_data </span>;</p>

&lt;/script&gt;<br />
</div>


<p>Let's go through this template in parts:</p>

<h3>json2.js</h3>

<p>This is the Javascript <span class="caps">JSON </span>library used to stringify the <span class="caps">JSON </span>for <span class="caps">OFC2. </span> It uses <code>var data</code> which comes from the <span class="caps">JSON </span>data we encoded earlier in the Controller.</p>

<h3>swfobject.js</h3>

<p>Optional helper Javascript library used to reduce the amount of Javascript code needed in this template.</p>

<h3>open-flash-chart-custom.swf</h3>

<p>This Flash application is the center-piece of the charting process.  It is a custom version of <span class="caps">OFC2</span><sup class="footnote"><a href="http://www.catalyzed.org/2009/08/post.html#fn5">5</a></sup> It uses the <code>open_flash_chart_data()</code> function to consume the chart data and render the chart.  The <code>ofc_averages_chart</code> parameter is the id of an <span class="caps">HTML </span>div where the chart will be placed in the web page.</p>

<h2>Final View</h2>

<p>If you'd like to see an example of the final output, you can go <a target="_blank" href="https://satya.huntana.com/ofc2-barchart-example.html"><span class="caps">HERE.</span></a></p>

<p>As you can see, after this relatively small amount of work, we have a dynamic, flexible and shiny chart tracking the data we are interested in.  <a target="_blank" href="http://teethgrinder.co.uk/open-flash-chart-2/">Open Flash Chart</a> is a nice and simple way to add a bit of 'wow' factor to a set of statistical data, and including it in your Catalyst app is a breeze.</p>




<h2>Footnotes</h2>

<p class="footnote" id="fn1"><sup>1</sup> The $admin_id represent a test given to a certain grade level at a certain time.  e.g First Grade Spring 20009.</p>

<p class="footnote" id="fn2"><sup>2</sup> Yes, I would be wise to put my controller on a diet and move more of the data processing into the model.</p>

<p class="footnote" id="fn3"><sup>3</sup> There are some Perl modules that can assist this process but the mature one is for the older (non-JSON) format, while the newer one is not stable.</p>

<p class="footnote" id="fn4"><sup>4</sup> I'm actually showing the element in it's <span class="caps">JSON </span>form, but the Perl form is very close, just substitute ':' with ' =&gt; '.</p>

<p class="footnote" id="fn5"><sup>5</sup> I'm using a slightly modified version of <span class="caps">OFC2. </span> It includes a patch that provides keys to shapes.  The patch came from <span class="caps">DZ. </span> This custom library was compiled with Flex <span class="caps">SDK</span> 3.3 on Linux.  Bug me for another article if that interests you.</p>]]>
    </content>
</entry>

<entry>
    <title>jQuery and Catalyst: Easier than you thought</title>
    <link rel="alternate" type="text/html" href="http://www.catalyzed.org/2009/08/jquery-and-catalyst-easier-than-you-thought.html" />
    <id>tag:www.catalyzed.org,2009://1.62</id>

    <published>2009-08-15T01:21:10Z</published>
    <updated>2009-08-15T15:28:49Z</updated>

    <summary><![CDATA[So recently, I've been hacking on some jquery for some UI stuff for a small site I've been working on.&nbsp; The site is backed by Catalyst, of course, and given I'm not big on design stuff, I figured I'd give...]]></summary>
    <author>
        <name>Devin Austin</name>
        <uri>http://www.catalyzed.org/mt/mt-cp.cgi?__mode=view&amp;blog_id=1&amp;id=2</uri>
    </author>
    
        <category term="Catalyst" scheme="http://www.sixapart.com/ns/types#category" />
    
        <category term="Perl" scheme="http://www.sixapart.com/ns/types#category" />
    
    <category term="catalyst" label="catalyst" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="jquery" label="jQuery" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="perl" label="perl" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en" xml:base="http://www.catalyzed.org/">
        <![CDATA[<p>So recently, I've been hacking on some <a href="http://www.jquery.com">jquery</a> for some <a href="http://www.jqueryui.com">UI</a> stuff for a small site I've been working on.&nbsp; The site is backed by Catalyst, of course, and given I'm not big on design stuff, I figured I'd give jQuery UI a go.&nbsp; It turned out great, however, my findings were that when using the jQuery AJAX (or for the pedantic, AHAH) method for generating <a href="http://jqueryui.com/demos/tabs/">tabs</a>, one has to do some tinkering from the standard <a href="http://www.template-toolkit.org">Template::Toolkit</a> WRAPPER practices.&nbsp; ]]>
        <![CDATA[
Typically, one writes a wrapper as such:<br /><br /><span style="font-family: courier new,courier;">[% IF template.name.match('\.(css|js|txt)') || no_wrapper;<br />&nbsp;&nbsp; debug("Passing page through as text: $template.name");<br />&nbsp;&nbsp;&nbsp;&nbsp; content;<br />&nbsp;&nbsp; ELSE %]<br />&lt;?xml version="1.0" encoding="UTF-8"?&gt;<br />&lt;!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"&gt;<br />&lt;html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"&gt;<br />&lt;head&gt;<br />&lt;title&gt;[% template.title or "myapp.com" %]&lt;/title&gt;<br />&lt;link rel="stylesheet" href="[% c.uri_for('/static/styles/main.css') %]" /&gt;<br />&lt;link rel="shortcut icon"&nbsp; href="[% c.uri_for('/static/images/favicon.ico') %]" /&gt;<br />&lt;style&gt;<br />.titlec {<br />&nbsp; font-size: small;<br />}<br />ul.videos li {<br />&nbsp; float: left;<br />&nbsp; width: 10em;<br />&nbsp; margin-bottom: 1em;<br />}<br />ul.videos<br />{<br />&nbsp; margin-bottom: 1em;<br />&nbsp; padding-left : 0em;<br />&nbsp; margin-left: 0em;<br />&nbsp; list-style: none;<br />}<br />&lt;/style&gt;<br /><br />&lt;/head&gt;<br />&lt;body&gt;<br />&lt;div id="header" align="center"&gt;<br />&lt;img src="[% c.uri_for('/static/images/logo.png') %]" /&gt;<br />&lt;/div&gt;<br /><br />&lt;div id="topnav"&gt;<br /><br />&lt;div id="dividermenu"&gt;<br />&lt;ul&gt;<br />&lt;li&gt;&lt;a href="[% c.uri_for('/') %]"&gt;home&lt;/a&gt;&lt;/li&gt;<br />[%- UNLESS c.user_exists %]<br />&lt;li&gt;&lt;a href="[% c.uri_for('/login') %]"&gt;login&lt;/a&gt;&lt;/li&gt; <br />&lt;li&gt;&lt;a href="[% c.uri_for('/signup') %]"&gt;sign up&lt;/a&gt;&lt;/li&gt;<br />[%- ELSE -%]<br />&lt;li&gt;&lt;a href="[% c.uri_for('/logout') %]"&gt;logout&lt;/a&gt;&lt;/li&gt; <br />&lt;li&gt;&lt;a href="[% c.uri_for('/photo/add') %]"&gt;upload photos&lt;/a&gt;&lt;/li&gt;<br />[%- END %]<br />&lt;li&gt;&lt;a href="[% c.uri_for('/photos') %]"&gt;view pictures&lt;/a&gt;&lt;/li&gt;<br />&lt;li&gt;&lt;a href="[% c.uri_for('/search') %]"&gt;search pictures&lt;/a&gt;&lt;/li&gt;<br />&lt;/ul&gt;<br />&lt;/div&gt;<br />&lt;/div&gt;<br /><br />&lt;div id="bodyblock" align="right"&gt;<br />&lt;div id="left-col"&gt;<br />&lt;div id="menu"&gt;<br />&lt;ul&gt;&lt;h2&gt;Products&lt;/h2&gt;<br />&lt;ul&gt;<br />&lt;li&gt;&lt;a href="[% c.uri_for('/') %]"&gt;Home&lt;/a&gt;&lt;/li&gt;<br />&lt;li&gt;&lt;a href="[% c.uri_for('/contact') %]" title="Contact Us"&gt;Contact Us&lt;/a&gt;&lt;/li&gt;<br />&lt;li&gt;&lt;a href="[% c.uri_for('/about') %]" title="About Us"&gt;About&lt;/a&gt;&lt;/li&gt;<br />[% UNLESS c.user_exists %]<br />&lt;li&gt;&lt;a href="[% c.uri_for('/signup') %]"&gt;sign up and upload your pictures&lt;/a&gt;&lt;/li&gt;<br />[% END %]<br /><br />&lt;/ul&gt;<br /><br />&lt;/div&gt;<br />&lt;/div&gt;<br />&lt;div class="error"&gt;[% error_msg %]&lt;/div&gt;<br />&lt;div class="status"&gt;[% status_msg %]&lt;/div&gt;<br />&lt;div id="content"&gt;<br />&lt;p&gt;<br />[% content %]<br />&lt;/p&gt;<br /><br />&lt;/div&gt;<br />&lt;/div&gt;<br />&lt;div id="footer" align="center"&gt;Copyright (c) myapp.com&lt;/div&gt;<br /><br />&lt;/div&gt;<br /><br />&lt;/body&gt;<br />&lt;/html&gt;<br />[% END %]</span></p>
<p><br />However, jQuery sets things up so that your main page acts as your wrapper.&nbsp; Essentially, you have to include the tab set up in your index/main page template as opposed to your wrapper.&nbsp; Otherwise, you end up with nested content that looks horrid.&nbsp;</p>
<p>Long story short:&nbsp; It's easiest to lose the wrapper in this case.&nbsp; Don't include one for your Template::Toolkit view, and just do your page layout in your main template.&nbsp; Here's what I came up with:&nbsp;</p>
<p>"index.tt"</p>
<p><span style="font-family: courier new,courier;">[% IF template.name.match('\.(css|js|txt)') || no_wrapper;<br />&nbsp;&nbsp; debug("Passing page through as text: $template.name");<br />&nbsp;&nbsp;&nbsp;&nbsp; content;<br />&nbsp;&nbsp; ELSE %]<br />&lt;?xml version="1.0" encoding="UTF-8"?&gt;<br />&lt;!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"&gt;<br />&lt;html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"&gt;<br />&lt;head&gt;<br />&lt;title&gt;[% template.title or "My App's Website - Now With More jQuery!" %]&lt;/title&gt;<br />&lt;link type="text/css" href="[% c.uri_for('/', 'static', 'css', 'custom-theme', 'jquery-ui-1.7.2.custom.css') %]" rel="stylesheet" /&gt;<br />&lt;script type="text/javascript" src="[% c.uri_for('/', 'static', 'js', 'jquery-1.3.2.min.js' ) %]"&gt;&lt;/script&gt;<br />&lt;script type="text/javascript" src="[% c.uri_for('/', 'static', 'js', 'jquery-ui-1.7.2.custom.min.js' ) %]"&gt;&lt;/script&gt;<br />&lt;link rel="shortcut icon"&nbsp; href="[% c.uri_for('/', 'static','images','favicon.ico') %]" /&gt;<br />&lt;script type="text/javascript"&gt;<br />$(function(){<br /><br />&nbsp;&nbsp;&nbsp; // Accordion<br />&nbsp;&nbsp;&nbsp; $("#accordion").accordion({ header: "h3" });<br /><br />&nbsp;&nbsp;&nbsp; // Tabs<br />&nbsp;&nbsp;&nbsp; $('#tabs').tabs({ <br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; ajaxOptions: { async: false }, <br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; spinner: 'Retrieving data...',&nbsp; <br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; collapsible: true <br />&nbsp;&nbsp;&nbsp; });<br /><br /><br />&nbsp;&nbsp;&nbsp; // Dialog&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; $('#dialog').dialog({<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; autoOpen: false,<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; width: 600,<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; buttons: {<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; "Ok": function() { <br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; $(this).dialog("close"); <br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }, <br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; "Cancel": function() { <br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; $(this).dialog("close"); <br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; } <br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp; });<br />&nbsp;&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; // Dialog Link<br />&nbsp;&nbsp;&nbsp; $('#dialog_link').click(function(){<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; $('#dialog').dialog('open');<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; return false;<br />&nbsp;&nbsp;&nbsp; });<br /><br />&nbsp;&nbsp;&nbsp; // Datepicker<br />&nbsp;&nbsp;&nbsp; $('#datepicker').datepicker({<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; inline: true<br />&nbsp;&nbsp;&nbsp; });<br />&nbsp;&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; // Progressbar<br />&nbsp;&nbsp;&nbsp; $("#progressbar").progressbar({<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; value: 20 <br />&nbsp;&nbsp;&nbsp; });<br />&nbsp;&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; //hover states on the static widgets<br />&nbsp;&nbsp;&nbsp; $('#dialog_link, ul#icons li').hover(<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; function() { $(this).addClass('ui-state-hover'); }, <br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; function() { $(this).removeClass('ui-state-hover'); }<br />&nbsp;&nbsp;&nbsp; );<br />&nbsp;&nbsp;&nbsp; <br />});<br />&lt;/script&gt;<br /><br />&lt;/head&gt;<br />&lt;body&gt;<br /><br />&lt;div id="header" align="left"&gt;<br />&lt;img src="[% c.uri_for('/', 'static','images','logo.gif') %]" /&gt;<br />&lt;/div&gt;<br /><br />[% IF status_msg %]<br />&lt;div class="ui-widget"&gt;<br />&nbsp;&nbsp;&nbsp; &lt;div class="ui-state-highlight ui-corner-all" style="padding: 0pt 0.7em; margin-top: 20px;"&gt; <br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &lt;p&gt;&lt;span class="ui-icon ui-icon-info" style="float: left; margin-right: 0.3em;"&gt;&lt;/span&gt;<br /><br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &lt;strong&gt;Success&lt;/strong&gt; [% status_msg %].&lt;/p&gt;<br />&nbsp;&nbsp;&nbsp; &lt;/div&gt;<br />&lt;/div&gt;<br />[% END %]<br /><br />[% IF error_msg %]<br />&lt;div class="ui-widget"&gt;<br />&lt;div class="ui-state-error ui-corner-all" style="padding: 0pt 0.7em;"&gt; <br />&nbsp;&nbsp;&nbsp; &lt;p&gt;&lt;span class="ui-icon ui-icon-alert" style="float: left; margin-right: 0.3em;"&gt;&lt;/span&gt; <br />&nbsp;&nbsp;&nbsp; &lt;strong&gt;Alert:&lt;/strong&gt; [% error_msg %].&lt;/p&gt;<br />&lt;/div&gt;<br />[% END %]<br />[% content %]<br />&lt;/body&gt;<br />&lt;/html&gt;<br />[% END %]</span><br /><br />"contact.tt"<br /><span style="font-family: courier new,courier;">&lt;pre&gt;&lt;h2&gt;Contacting Us&lt;/h2&gt;<br /><br />&lt;div&gt;[% form.render %]&lt;/div&gt;</span><br /><br />I hope this helps future jQuery-ui users to lessen their confusion if they happen to run into this.&nbsp; jQuery is a *great* thing and I have really enjoyed its ease of use on top of Catalyst.</p>]]>
    </content>
</entry>

<entry>
    <title>MojoMojo Lightning Install</title>
    <link rel="alternate" type="text/html" href="http://www.catalyzed.org/2009/08/mojomojo-lightning-install.html" />
    <id>tag:www.catalyzed.org,2009://1.61</id>

    <published>2009-08-05T06:30:00Z</published>
    <updated>2009-08-05T15:51:29Z</updated>

    <summary>MojoMojo uses a boatload of CPAN module to do its things. If you already have Catalyst and DBIC installed you&apos;re more than half way there, but what if you&apos;re starting from scratch and you want to quickly find out if...</summary>
    <author>
        <name>mateu</name>
        <uri>http://www.catalyzed.org/mt/mt-cp.cgi?__mode=view&amp;blog_id=1&amp;id=9</uri>
    </author>
    
        <category term="Catalyst" scheme="http://www.sixapart.com/ns/types#category" />
    
        <category term="Perl" scheme="http://www.sixapart.com/ns/types#category" />
    
    <category term="catalyst" label="Catalyst" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="dbixclass" label="DBIx::Class" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="install" label="Install" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="mojomojo" label="MojoMojo" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="perl" label="Perl" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en" xml:base="http://www.catalyzed.org/">
        <![CDATA[<p>MojoMojo uses a boatload of <span class="caps">CPAN </span>module to do its things.  If you already have Catalyst and <span class="caps">DBIC </span>installed you're more than half way there, but what if you're starting from scratch and you want to quickly find out if MojoMojo is something you're interested in.</p>

<h2>Install it Quick and Dirty</h2>

<p>Ok maybe not dirty but in seven steps we will install this database backed, version controlled tree full of searchable and navigable page mania.  </p>]]>
        <![CDATA[<h2>Overview</h2>

<p>How to install MojoMojo in the fewest steps.  This example assumes I'm installing MojoMojo to <em>/home/user/MojoMojo</em><sup class="footnote"><a href="http://www.catalyzed.org/2009/08/mojomojo-lightning-install.html#fn1">1</a></sup> on a Debian or Ubuntu machine. </p>

<h2>1. Install supporting Debian packages<sup class="footnote"><a href="http://www.catalyzed.org/2009/08/mojomojo-lightning-install.html#fn2">2</a></sup></h2>



<pre lang="Bash">
apt-get install libpng12-dev libjpeg62-dev libxslt1-dev \
libgdbm-dev libgcrypt11-dev docbook-xsl docbook-xsl-doc-html \
libfreetype6-dev
</pre>




<h2> 2. <a href="https://satya.huntana.com/download/MojoMojo.tar.gz">Download MojoMojo</a></h2>

<h2>3. Extract the tar file and cd into MojoMojo/</h2>



<pre lang="Bash">
tar xvfz MojoMojo.tar.gz
cd MojoMojo/
</pre>



<h2>4. Set <span class="caps">PATH</span><sup class="footnote"><a href="http://www.catalyzed.org/2009/08/mojomojo-lightning-install.html#fn3">3</a></sup></h2>



<pre lang="Bash">
source tools/shipwright-source-bash /home/user/MojoMojo
</pre>



<h2> 5. Start MojoMojo</h2>



<pre lang="Bash">
mojomojo_server.pl
</pre>



<h2>6. Browse to MojoMojo root page</h2>

<p>For localhost<sup class="footnote"><a href="http://www.catalyzed.org/2009/08/mojomojo-lightning-install.html#fn4">4</a></sup>:  <a href="http://localhost:3000/">http://localhost:3000/</a></p>


<h2> 7. Log in</h2>



<pre>
username: admin
password: admin
</pre>



<h2> Notes</h2>


<ul>
<li>This distribution of MojoMojo uses the pre-initialized <span class="caps">SQL</span>ite database <em>mojomojo.db</em></li>
</ul>



<h2> Credits</h2>

<p>Thanks to <a href="http://search.cpan.org/perldoc?Shipwright">Shipwright</a> which was used to create the MojoMojo.tar.gz vessel that contains MojoMojo and all its <a href="http://deps.cpantesters.org/?module=MojoMojo;perl=latest">wonderful dependencies.</a></p>

<p class="footnote" id="fn1"><sup>1</sup> Use a path to suit your needs.</p>

<p class="footnote" id="fn2"><sup>2</sup>  For Imager and DocBook support.</p>

<p class="footnote" id="fn3"><sup>3</sup> Inform the environment where MojoMojo is located.</p>

<p class="footnote" id="fn4"><sup>4</sup>  Please adjust hostname according to your needs.  In addition, default port for MojoMojo is 3000.  It can be set with -p $port on startup, where $port is a port number. </p>]]>
    </content>
</entry>

<entry>
    <title>Creating a Simple Server - Part 2</title>
    <link rel="alternate" type="text/html" href="http://www.catalyzed.org/2009/08/creating-a-simple-server---part-2.html" />
    <id>tag:www.catalyzed.org,2009://1.60</id>

    <published>2009-08-03T17:16:16Z</published>
    <updated>2009-08-04T05:40:17Z</updated>

    <summary>Hi all, I&apos;ve returned, with the full source listing of Creating a Simple Server - No HTTPD Required. So here it is......</summary>
    <author>
        <name>Devin Austin</name>
        <uri>http://www.catalyzed.org/mt/mt-cp.cgi?__mode=view&amp;blog_id=1&amp;id=2</uri>
    </author>
    
        <category term="Perl" scheme="http://www.sixapart.com/ns/types#category" />
    
    <category term="application" label="application" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="lite" label="lite" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="perl" label="Perl" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="server" label="server" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="web" label="web" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en" xml:base="http://www.catalyzed.org/">
        <![CDATA[<p>Hi all,</p>

<p>I've returned, with the full source listing of <a href="http://www.catalyzed.org/2009/07/creating-a-simple-server---no-httpd-required.html">Creating a Simple Server - No HTTPD Required</a>.</p>

<p>So here it is...</p>
]]>
        <![CDATA[<p>A few notes:  </p>

<ul>
<li>You'll notice, this is a <em>fully</em> functional web application.  This essentially replaces and obsoletes a, say, CGI version of this application as well as the web server it attaches to.  </li>
<li>You have a dispatch table you can set up, authentication (via HTTP::Server::Simple sublcasses), SSL (via the commented out SSL hook), </li>
<li><em>and</em> a fully embedded server that allows for preforking.</li>
</ul>

<p>And without further adieu: </p>

<p><strong>lite.pl</strong></p>

<pre>
#!/usr/bin/env perl

package Server::Lite::App;
use Moose;
use namespace::autoclean;
use Server::Lite;
use IO::File;
use MooseX::Types::Moose qw/Str Int/;

with 'MooseX::Getopt';

has logfile => (
    is => 'ro',
    isa => Str,
    traits => [qw(Getopt)],
    cmd_aliases => 'l',
    documentation => qq{ specify a log name for syslog },
    required => 1,
);

has task_dir => (
    is => 'ro',
    isa => Str,
    traits => [qw(Getopt)],
    cmd_aliases => 'dir',
    documentation => qq{ the directory where task queues are stored },
    required => 1,
);

has pid_file => (
    is => 'ro',
    isa => Str,
    traits => [qw(Getopt)],
    cmd_aliases => 'pid',
    documentation => qq{ name of the pidfile to be written to },
    required => 1,
);

has port => (
    is => 'ro',
    isa => Int,
    traits => [qw(Getopt)],
    cmd_aliases => 'p',
    documentation => qq{ specify a port to listen to },
    required => 1,
);


sub recorder_prefix { # set the log file for recorder
    my $self = shift;
    DateTime->now . $self->port;
}

sub net_server {
    "Net::Server::PreForkSimple";
}

sub bad_request {
    print "HTTP/1.0 404 Bad request\r\n";
}

sub write_pid {
    my ($self, $pid) = @_;
    my $fh = IO::File->new;
    my $pid_file = $self->pid_file;

    if ($fh->open("> $pid_file") ) {
        print $fh "$pid\n";
        undef $fh;
    } else {
        warn("Cannot open: $pid_file: $!");
    }
}

sub graceful_shutdown {
    my ($self, $server) = @_;
    my $pid = $self->pid;

    print "Shutting down...\n";
    $server->logger->log(
        level => "notice",
        message => "TERM received. Shutting down..."
    );
    `rm $pid`;

}

sub init {
    my ($self) = shift;
    ## start the server
    unless (@ARGV) {
        print "usage: perl bin/lite.pl [options]\n";
        exit;
    }

    my $server = Server::Lite->new($self->port);
    my $logger = Log::Dispatch::Syslog->new(
     name => $self->logfile,
     min_level => 'info', );
    $logger->log( level => 'error', message => "data logging initiated");
    $server->logger($logger);
    $server->dir($self->task_dir);
    my $pid = $server->background();
    $self->write_pid($pid);
}

my $server = __PACKAGE__->new_with_options;
$server->init;
$SIG{'TERM'} = sub { __PACKAGE__->graceful_shutdown($server) };

1;
</pre>

<p>Server.pm</p>

<pre>
package Server::Lite;

use Moose;
use HTTP::Server::Simple;
use IO::Socket::SSL;
use IO::File;
use Regexp::Common qw /URI/;
use DateTime;
use File::Spec;
use Log::Dispatch::Syslog;
use MooseX::Types::Moose qw/Str Int/;
use namespace::autoclean;

extends qw/HTTP::Server::Simple::CGI/ ;

has logger => (
    is => 'rw',
    isa => 'Log::Dispatch::Output',
    required => 1,
);

has dir => (
    is => 'rw',
    isa => Str,
    required => 1,
);

sub get_dispatch {
     my ($self, $path) = @_;
     my %dispatch = (
        '/do' => \&handle_it,
     );

     return $dispatch{$path};

}

sub handle_request {
    my ($self, $cgi) = @_;

    my $path = $cgi->path_info();
    my $handler = $self->get_dispatch($path);

    if (ref($handler) eq "CODE") {
         print "HTTP/1.0 200 OK\r\n";
         $handler->($self, $cgi);

     } else {
         print "HTTP/1.0 404 Not found\r\n";
         print $cgi->header,
               $cgi->start_html('Not found'),
               $cgi->h1('Not found'),
               $cgi->end_html;

     }

}

#sub accept_hook {
# my $self = shift;
# my $fh = $self->stdio_handle;

# $self->SUPER::accept_hook(@_);

# my $newfh =
# IO::Socket::SSL->start_SSL( $fh,
# SSL_server => 1,
# SSL_use_cert => 1,
# SSL_cert_file => 'myserver.crt',
# SSL_key_file => 'myserver.key',
# )
# or warn "problem setting up SSL socket: " . IO::Socket::SSL::errstr();

# $self->stdio_handle($newfh) if $newfh;
#}

sub handle_it {
    my ($self, $cgi) = @_;

    return if !ref $cgi;

    my $dir = $self->dir;
    my $prefix = $cgi->param('prefix');
    my $goes_in_queue = $cgi->param('to_queue');
    my $to_url = $cgi->param('url');
    my $now = DateTime->now;
    my $activity = File::Spec->catdir($dir, "$goes_in_queue$now");

    print $cgi->header;

    unless ( !$prefix or !$goes_in_queue or $to_url !~ /$RE{URI}{HTTP}/ ) {

        my $fh = new IO::File;
        if ( $fh->open(">$activity") ){

            print $fh "$goes_in_queue" or print $cgi->h1("File IO Error:$!");
            $fh->close;

            $self->logger->log( level => "error", message =>$cgi->remote_addr . "\t" . "URL: $to_url\t" .
                          "Prefix: $prefix \t Command: $goes_in_queue \t Status: Success\n" ); # or die "Error: $!";

        }

        print $cgi->start_html('Success!'),
              $cgi->h1("Successfully handled request"),
              $cgi->p("Dir: " . $self->dir),
              $cgi->end_html;

    } else {

        print $cgi->start_html('Fail!'),
              $cgi->h1("Missing required parameters!"),
              $cgi->end_html;

        $self->logger->log( level => "error", message => $cgi->remote_addr . "\t" . "URL: $to_url\t" .
                      "Prefix: $prefix \t Command: $goes_in_queue \t Status: Failed\n" ) or die "Error: $!";

    }

}

# ABSTRACT: A really simple server + web application implementation with SSL, HTTP authentication *and* preforking options

=head1 NAME

Server::Simple

=cut

=head1 DESCRIPTION

A really simple server + web application implementation with SSL, HTTP authentication *and* preforking options

=cut 

=head1 SYNOPSIS

    perl  bin/lite.pl --pid /tmp/server-lite.pid --logfile local1 --dir tasks/ --port 3001

=cut

=head1 OPTIONS

pid: specify a pidfile for the server

logfile: a valid syslog service to connect to

dir: the dir to which command queue files will be written to

port: a port to listen to 

=cut

=head1 SEE ALSO

Moose, HTTP::Server::Simple, Log::Dispatch::Syslog

=cut

=head1 AUTHOR

Devin Austin <dhoss@cpan.org>, Jay Kuri <jayk@cpan.org>

=cut

1;
</pre>

<p>You can download the source here: <a href="http://github.com/dhoss/server-lite/tarball/1.02">tar.gz</a>, <a href="http://github.com/dhoss/server-lite/zipball/1.02">zip</a></p>
]]>
    </content>
</entry>

<entry>
    <title>The lie of independence - or - how I learned to stop worrying and love the dependency chain.</title>
    <link rel="alternate" type="text/html" href="http://www.catalyzed.org/2009/07/the-lie-of-independence.html" />
    <id>tag:www.catalyzed.org,2009://1.59</id>

    <published>2009-07-29T06:30:00Z</published>
    <updated>2009-08-05T03:58:06Z</updated>

    <summary>Every so often I see a blog post or a comment that is along the lines of &quot;Don&apos;t use X, it has too many dependencies, use Y instead, it doesn&apos;t depend on anything.&quot; I&apos;ve touched on this subject before, but...</summary>
    <author>
        <name>Jay Kuri</name>
        <uri>http://www.catalyzed.org/mt/mt-cp.cgi?__mode=view&amp;blog_id=1&amp;id=1</uri>
    </author>
    
        <category term="Perl" scheme="http://www.sixapart.com/ns/types#category" />
    
    <category term="catalyst" label="catalyst" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="cpan" label="cpan" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="dependencies" label="dependencies" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="development" label="development" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="perl" label="Perl" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en" xml:base="http://www.catalyzed.org/">
        <![CDATA[<p>Every so often I see a blog post or a comment that is along the lines of "Don't use X, it has too many dependencies, use Y instead, it doesn't depend on anything."  I've <a href="http://www.catalyzed.org/2009/05/the-holy-grail-of-software-development.html">touched on this subject</a> before, but in different ways. I've seen this subject crop up again recently and think it warrants another look.  </p>

<p><a href="http://stackoverflow.com/questions/1146238/whats-wrong-with-using-a-framework-that-has-a-lot-of-dependencies">This time</a> it was oriented towards Rails and Catalyst, but I've seen it on other projects as well.  The question behind the above statement is somewhat deceiving.  It seems to be: '<strong>Do I choose a system that has lots of dependencies, or one that has only a few (or none)</strong>?'  Well, when you put it like that, it seems like a no brainer... but <strong>it is, in reality, a trick question</strong>.</p>
]]>
        <![CDATA[<p>The truth is that <strong>no modern software stands on its own</strong>.  There are literally hundreds of small tasks that need to be accomplished for every web request in a modern application.  Decoding headers, parsing values, communicating with the web server, etc.  All of these things need to be done. The question, really, is not whether you have lots of dependencies.  <strong>The question is, are those dependencies internal or external.</strong> </p>

<p>So what's the difference between something with 'internal dependencies' and something with 'external dependencies'?  The difference is that the 'internal dependency' projects try to do all those small tasks themselves, where the 'external dependency' projects delegate those small tasks to external modules specifically built for those particular tasks. </p>

<p>The practical differences between these two are subtle, but important.  It's a difference in viewpoint for one.  Those in the 'external dependency' camp tend to prefer to focus on the problem they are trying to solve, and use tools to solve the little tasks that are built for solving those little tasks.  The 'internal dependency' camp tends to have a more 'do it myself so I can get exactly what I want' type view.  Both of these views have merit in certain situations, but ultimately I think the 'external dependency' camp wins for all practical purposes and I'll explain why.</p>

<p>One of the biggest wins for the 'external dependency' camp is that they are focused on their own particular problem and spend less time Yak Shaving, writing Yet Another Templating Language, etc.</p>

<p>Another important fact is that <strong>when a module is published on its own, it has to stand up on its own</strong>.  This generally means more documentation and clearly defined interface.  Interfaces are important because they are the contract between the code being used and the application which is using it.  A clearly defined API makes the code that uses a module MORE solid, as it is clear what the expectations are on both sides.  </p>

<p>Documentation solidifies APIs.  <strong>When an API is documented, it becomes public and it adds weight to the code, making it harder to modify</strong>. When it's documented and published, it gets even more solid.  It's like a sign that says 'don't pull this rug, someone might be standing on it'.</p>

<p>When the same small task is accomplished by some chunk of code in some sub-module within the main application, it is often without a clearly defined API and documentation.  This doesn't seem like a big deal until you realize that it usually means that the application author feels like he can adjust the calling semantics or return values to work better in the newest release of ApplicationFramework vWhizBang.42.  When that happens, any code that you wrote that used that functionality suddenly breaks.  If you are lucky the change is documented somewhere so you can find out why your application doesn't work anymore.  Most of the time you are not lucky.  </p>

<p>Which brings us to the next point; the author of the 'small task' module has incentive to fix the problem without disrupting the API.  As I mentioned, once documented and published, a module becomes solid.  <strong>As soon as it's out there, people start depending on it</strong>, and not just the people who wrote it.  <strong>This forces the author to think hard about making a change to the API</strong>.  This is not motivated by some fuzzy 'goodness' feeling toward other people, it's simply the background knowledge that 'boy, if I change this, I am going to get swamped with emails and complaints'.  All of this means that the author has a reason to fix whatever problem it is without disrupting the API... even if it's a little harder to do.</p>

<p>Another aspect of this is that when a module is published, it gets used by more than one application.  It almost always starts getting used for things that the original author didn't intend or didn't think of.  Any seasoned developer knows, the vast majority of bugs relate to the code being used in ways the author didn't plan for. </p>

<p>What this means is that those bugs are exposed more quickly.  When your code is deployed by many different people in many different ways, you have a much larger group of people stress testing and reporting bugs.  <strong>This means that published modules tend to have their issues identified and corrected more quickly</strong> than an unpublished piece of code within another distribution. </p>

<p>A module that is used in many different applications also has the benefit of expanding its feature-set more quickly.  Different applications and frameworks grow and develop at different rates and in different areas.  <strong>When new requirements come up, the self-contained module will likely be updated to better support it</strong>.  This will happen, often, without a disruption in the API.  </p>

<p>The benefit of this, in its simplest terms, is that when you realize that your application requires some additional functionality, often you will find that the module has already gained that functionality.  In the 'internal dependency' camp, in the same situation you instead get to have a nice Yak Shaving Holiday, away from working on your core feature set.  </p>

<p>In short, <strong>having dependencies allows you to focus on your core functionality</strong>... the features that are most important to you.  All the while those who wrote your dependency modules are focused on their own core functionality, that which is most important to them.  It means that each small component has someone focused on making it as good and as solid as it can be.</p>

<p>There is another aspect to all of this that must be discussed. When your application doesn't include all its small tasks within itself, you are actually <strong>MORE</strong> able to respond to security and other problems.  Most of the time, a security or bug-fix type issue can be isolated to a particular module.  Because the API is defined and documented, usually that module can be updated independent of the rest of the application.  The bug can usually be fixed without disrupting the rest of the code.</p>

<p>There is another subtle effect here.  Because each small-task module is versioned independently, they only need to be updated when they have a problem that needs fixing or when your application requires functionality that is new to that module.  This means that you can update your Cookie handling module without needing to update your form handling module. </p>

<p>In the 'internal dependency' camp, all the small-task code is part of the larger package.  Now, if you need to update, you have a much bigger problem.  Instead of just isolating and adjusting the points where the Cookie module is used, you have to look at every change made to the larger package across the board between the version you have deployed and the version that contains your Cookie bugfix.  You then have to go through your code and adjust every other interaction with code that has changed whether it's related to your Cookie bugfix or not.  This means every update requires much more work. </p>

<p>It also means that with internal dependencies, when your application is left unmodified for a while, you have a much bigger task when it comes time to bring it up to date... and you have to do so all at once, rather than working with one package update at a time.</p>

<p>All of these things demonstrate that ultimately, external dependencies are the way to go.  It lets you focus on your core features and gives you a much more solid base to stand on as you build your own functionality.</p>

<p>All of this said, there are still places where internal dependency options are better.  Examples of these might be embedded devices or areas where you have little or no control over your deployment environment such as shared virtual hosts, etc.  </p>

<p>Fortunately the world of application deployment has progressed beyond shared virtual-hosts.  We now have options such as cloud servers and other virtual environments that give us flexible machines where we get to decide what is deployed and how.  For most of us, using external modules is a no-brainer.</p>

<p>Waiting for many modules to install can be annoying.  Ultimately, when you realize the real benefits of using external dependencies, you realize that the more you stand on the shoulders of others, the better off you will be.</p>
]]>
    </content>
</entry>

</feed>
