<?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>2011-04-26T15:37:42Z</updated>
    <subtitle>A Catalyst and Perl Blog</subtitle>
    <generator uri="http://www.sixapart.com/movabletype/">Movable Type Pro 4.25</generator>

<entry>
    <title>Mount Multiple PSGI Applications</title>
    <link rel="alternate" type="text/html" href="http://www.catalyzed.org/2011/04/mount-multiple-psgi-applications.html" />
    <id>tag:www.catalyzed.org,2011://1.101</id>

    <published>2011-04-26T15:32:42Z</published>
    <updated>2011-04-26T15:37:42Z</updated>

    <summary>Plack has the ability to map applications onto URLs. This is facilitated with Plack::App::URLMap. Here I will demonstrate how one can use Plack and URLMap to mount multiple applications. In addition, we examine how to handle static file requests and...</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="cascadenginx" label="Cascade nginx" 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="reverseproxy" label="reverse proxy" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="urlmap" label="URLMap" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en" xml:base="http://www.catalyzed.org/">
        <![CDATA[<p>Plack has the ability to map applications onto URLs. This is facilitated with  Plack::App::URLMap. Here I will demonstrate how one can use Plack and URLMap to mount multiple applications. In addition, we examine how to handle static file requests and requests to "/" using Cascade.</p>

<p><a href="http://suryahunter.com/wiki/hunter/perl_ironman/mount_multiple_apps_with_plack">Full Story</a></p>
]]>
        

    </content>
</entry>

<entry>
    <title>March Madness - Bracket Time</title>
    <link rel="alternate" type="text/html" href="http://www.catalyzed.org/2011/03/march-madness---bracket-time.html" />
    <id>tag:www.catalyzed.org,2011://1.100</id>

    <published>2011-03-14T14:14:24Z</published>
    <updated>2011-03-14T14:25:13Z</updated>

    <summary>It&apos;s that time of the year again when college basketball fans go crazy. If you&apos;re in the minority of computer programmers that care about basketball or you just want to try out some Catalyst, DBIC and FormHandler software then consider...</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="bracketsoftwarecollegebasketballtournament" label="bracket software college basketball tournament" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en" xml:base="http://www.catalyzed.org/">
        <![CDATA[<p>It's that time of the year again when college basketball fans go crazy.  If you're in the minority of computer programmers that care about basketball or you just want to try out some Catalyst, <span class="caps">DBIC </span>and FormHandler software then consider <strong>Bracket</strong>.  It is available both on <a href="https://github.com/mateu/Bracket">github</a> and <span class="caps">CPAN.</span></p>

<p>The <a href="https://github.com/mateu/Bracket/blob/master/INSTALL"><span class="caps">INSTALL </span>document</a> outlines the process of getting it up and running.</p>]]>
        
    </content>
</entry>

<entry>
    <title>Plack Middleware Example</title>
    <link rel="alternate" type="text/html" href="http://www.catalyzed.org/2011/03/plack-middleware-example.html" />
    <id>tag:www.catalyzed.org,2011://1.99</id>

    <published>2011-03-10T16:31:32Z</published>
    <updated>2011-03-10T16:36:50Z</updated>

    <summary>Plack Middleware is easy to use. Let&apos;s see how with a couple of examples; One example shows how to enable a Debug panel Another shows how to enable conditionally (based on PATH_INFO) Digest Authentication. Full article...</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="Perl" scheme="http://www.sixapart.com/ns/types#category" />
    
    <category term="plackmiddlewaredebugconditionaldigestauthentication" label="Plack Middleware Debug Conditional Digest Authentication" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en" xml:base="http://www.catalyzed.org/">
        <![CDATA[<p>Plack Middleware is easy to use.  Let's see how with a couple of examples;</p>


<ul>
<li>One example shows how to enable a <strong>Debug</strong> panel</li>
<li>Another shows how to enable conditionally (based on <span class="caps">PATH</span>_INFO) Digest Authentication.</li>
</ul>



<p><a href="http://suryahunter.com/wiki/hunter/perl_ironman/Plack_Middleware">Full article</a></p>]]>
        
    </content>
</entry>

<entry>
    <title>Plack Advent Distilled - Week 1</title>
    <link rel="alternate" type="text/html" href="http://www.catalyzed.org/2011/02/plack-advent-distilled---week-1.html" />
    <id>tag:www.catalyzed.org,2011://1.98</id>

    <published>2011-02-18T20:20:33Z</published>
    <updated>2011-02-18T20:26:25Z</updated>

    <summary>If you are a web application or framework developer then PSGI and Plack are worth knowing about. Sensei Miyagawa put together a series of high quality articles describing quite a bit about PSGI and Plack. They are worth your time...</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" />
    
    
    <content type="html" xml:lang="en" xml:base="http://www.catalyzed.org/">
        <![CDATA[<p>If you are a web application or framework developer then <span class="caps">PSGI </span>and Plack are worth knowing about.  Sensei Miyagawa put together a series of <a href="http://advent.plackperl.org/">high quality articles</a> describing quite a bit about <span class="caps">PSGI </span>and Plack.  They are worth your time if you have any interest in the topic at all.</p>

<p>In this paper, I present a distillation of week one's five articles for those who want a quick synopsis.</p>

<p><a href="http://suryahunter.com/wiki/hunter/perl_ironman/Plack_Advent_Distilled_-_Week_1">Full article</a></p>]]>
        
    </content>
</entry>

<entry>
    <title>Mongo CRUD</title>
    <link rel="alternate" type="text/html" href="http://www.catalyzed.org/2011/02/mongo-crud.html" />
    <id>tag:www.catalyzed.org,2011://1.97</id>

    <published>2011-02-16T00:15:09Z</published>
    <updated>2011-02-16T00:23:21Z</updated>

    <summary>MongoDB has an appeal to me given its apparent flexibility. I certainly haven&apos;t gotten to the center yet to tell you if the candy deep down under the wrapper is sweet, but my initial impression is that MongoDB is dang...</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="Perl" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="en" xml:base="http://www.catalyzed.org/">
        <![CDATA[<p>MongoDB has an appeal to me given its apparent flexibility.   I certainly haven't gotten to the center yet to tell you if the candy deep down under the wrapper is sweet, but my initial impression is that MongoDB is dang near as fun as shopping.</p>

<p>With that non-sense out of the way let's take a casual tour of MongoDB using the Perl driver <b>MongoDB</b> to express basic <span class="caps">CRUD.</span></p>

<p><a href="http://suryahunter.com/wiki/hunter/perl_ironman/Mongo_CRUD">Full article</a></p>]]>
        
    </content>
</entry>

<entry>
    <title>Baby Benchmark of PSGI Frameworks</title>
    <link rel="alternate" type="text/html" href="http://www.catalyzed.org/2011/02/baby-benchmark-of-psgi-frameworks.html" />
    <id>tag:www.catalyzed.org,2011://1.96</id>

    <published>2011-02-11T23:57:06Z</published>
    <updated>2011-02-12T00:01:04Z</updated>

    <summary>This papers discusses the topic of benchmarks in the context of PSGI application frameworks. It is not meant to incite violence over the results as they are to be taken with a heavy dose of medication. The reason being that...</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="Perl" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="en" xml:base="http://www.catalyzed.org/">
        <![CDATA[<p>This papers discusses the topic of benchmarks in the context of <span class="caps">PSGI </span>application frameworks. It is not meant to incite violence over the results as they are to be taken with a heavy dose of medication. The reason being that even the slowest performing framework can serve up requests in approximately two milliseconds. Generally this amount of time contributes very little to the overall equation of web page response time, because other factors like IO and the network latency play a more dominant role.</p>

<p><a href="http://suryahunter.com/wiki/hunter/perl_ironman/baby_benchmark_of_psgi_frameworks">Full article</a></p>]]>
        
    </content>
</entry>

<entry>
    <title>Comparing Selectors</title>
    <link rel="alternate" type="text/html" href="http://www.catalyzed.org/2011/02/comparing-selectors.html" />
    <id>tag:www.catalyzed.org,2011://1.95</id>

    <published>2011-02-09T22:05:05Z</published>
    <updated>2011-02-09T22:10:37Z</updated>

    <summary>Recently I have been using jQuery to select and manipulate HTML parts. I wanted to do something similar in Perl so I started playing with HTML::Zoom. In addition, I recently came across an article by tempire that introduced me to...</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="Perl" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="en" xml:base="http://www.catalyzed.org/">
        <![CDATA[<p>Recently I have been using jQuery to select and manipulate <span class="caps">HTML </span>parts.  I wanted to do something similar in Perl so I started playing with <span class="caps">HTML</span>::Zoom.  In addition, I recently came across an <a href="http://blogs.perl.org/users/tempire/2011/02/easy-dom-parsing-with-mojodom.html">article by tempire</a> that introduced me to Mojo::DOM.  This article provides a simple comparison of how the two tools do part of their job.</p>

<p><a href="http://suryahunter.com/wiki/hunter/perl_ironman/Comparing_Selectors">Full Article</a></p>]]>
        
    </content>
</entry>

<entry>
    <title>When a Script Becomes a Module</title>
    <link rel="alternate" type="text/html" href="http://www.catalyzed.org/2011/01/when-a-script-becomes-a-module.html" />
    <id>tag:www.catalyzed.org,2011://1.94</id>

    <published>2011-01-09T20:41:11Z</published>
    <updated>2011-01-09T21:03:24Z</updated>

    <summary>Recently I wrote about using Chart::Clicker to create plots of the high and low temperature forecast. The code I demonstrated was in the form a script. The code did its job, but was not structured so well nor was it...</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="Perl" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="en" xml:base="http://www.catalyzed.org/">
        <![CDATA[<p>Recently I wrote about using Chart::Clicker to create plots of the high and low <a href="http://suryahunter.com/wiki/hunter/charts/weather/temperature_forecast">temperature forecast</a>. The <a href="http://suryahunter.com/wiki/hunter/Charts/Weather/Temperature_Forecast.attachment/15">code</a> I demonstrated was in the form a script. 
The code did its job, but was not structured so well nor was it as easy to (re)use as it could be. Let's examine the situation and see if we can't make it better.</p>

<p><a href="http://suryahunter.com/wiki/hunter/perl_ironman/when_a_script_becomes_a_module">Full article</a></p>
]]>
        

    </content>
</entry>

<entry>
    <title>Sexy Charts with Chart::Clicker</title>
    <link rel="alternate" type="text/html" href="http://www.catalyzed.org/2010/12/sexy-charts-with-chartclicker.html" />
    <id>tag:www.catalyzed.org,2010://1.93</id>

    <published>2010-12-15T16:04:57Z</published>
    <updated>2010-12-15T17:13:28Z</updated>

    <summary>Chart::Clicker is a Perl distribution that is capable of producing some decent charts. This article explores the charting of both high and low temperature forecasts using Chart::Clicker. We&apos;ll scrape forecast data from the web and then use it to plot...</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="Perl" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="en" xml:base="http://www.catalyzed.org/">
        <![CDATA[<p>Chart::Clicker is a Perl distribution that is capable of producing some decent charts.  This article explores the charting of both high and low temperature forecasts using Chart::Clicker.   We'll scrape forecast data from the web and then use it to plot a high and low temperature forecast over the next five days.</p>

<p><a href="http://suryahunter.com/wiki/hunter/Charts/Weather/Temperature_Forecast">Full article</a></p>]]>
        
    </content>
</entry>

<entry>
    <title>Re-using Catalyst config</title>
    <link rel="alternate" type="text/html" href="http://www.catalyzed.org/2010/12/re-using-catalyst-config.html" />
    <id>tag:www.catalyzed.org,2010://1.92</id>

    <published>2010-12-14T15:57:12Z</published>
    <updated>2010-12-14T16:35:22Z</updated>

    <summary>You may have some scripts related to your Catalyst application and you would like to re-use pieces of the application&apos;s configuration information. For example, database connection information is something that could be used in a Catalyst application, but also one...</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" />
    
    
    <content type="html" xml:lang="en" xml:base="http://www.catalyzed.org/">
        <![CDATA[<p>You may have some scripts related to your Catalyst application and you would like to re-use pieces of the application's configuration information.  For example, database connection information is something that could be used in a Catalyst application, but also one could use the connection info within command line scripts so they too can get at the underlying data model.  This petit paper examines the use of Config::JFDI and Config::General to get at the Catalyst .conf file.</p>]]>
        <![CDATA[<h2>Example .conf</h2>

<p>Here is an example of a .conf file with file path information that I'd like to have access to from a script.</p>



<pre>
name YoApp

home /home/apps/YoApp
data_dir __path_to(data)__
weather_dir /var/www/weather/images

slashdot_rss                $data_dir/slashdot.rss
freshmeat_xml               $data_dir/freshmeat.xml
perl_blogs_file             $data_dir/perl_blogs.dat
cpan_modules_file           $data_dir/recent_cpan_modules.dat
med_menu_rss                $data_dir/med_menu.rss
snotel_db_file              $data_dir/snotel.db

precip_forecast_file        $weather_dir/precip-forecast.png
temperature_forecast_file   $weather_dir/temperature-forecast.png
</pre>



<p>Note that we set the home directory explicitly.  While Catalyst can find the home directory based on the standard Catalyst application file structure, a script needs a full path if it's to be called from random directories. </p>

<h2>Get the config</h2>

<p>The key to getting at the config from a script will be the use of Config::JFDI.  Let's create a baby module that has a routine to return the config information.  We'll call this routine later from our script.</p>



<pre>
package GetConfig;
use Config::JFDI;
use Dir::Self;

sub get_config {
    my $jfdi = Config::JFDI-&gt;new( 
	 name =&gt; 'YoApp',  
	 path =&gt; __DIR__ . &quot;/..&quot;,
         driver =&gt; {
		 'General' =&gt; { -InterPolateVars =&gt; 1 }
	});
    my $config = $jfdi-&gt;get;
    return $config;
}
1
</pre>



<p><span class="caps">NOTES</span>:<br />
* We must tell Config::JFDI both the name and the location of the conf file.  We give it a path relative to the module's position which is assumed to be in YoApp/lib.<br />
* For Config::General to interpolate variables we pass the 'InterPolateVars' option.  This allows us to have $data_dir variable interpolated to its full path within the .conf file.</p>

<h2>Using it.</h2>

<p>Now that we have the .conf file defined and method to get at its contents, let's use it.</p>



<pre>
use FindBin qw($Bin);
use lib &quot;$Bin/../lib&quot;;
use GetConfig;

my $config = GetConfig::get_config();
my $storage_file = $config-&gt;{perl_blogs_file};
</pre>



<p>Here we make sure the lib/ with GetConfig.pm is in our @INC.  Then we just call the get_config() function which returns the config contents as a hash reference.  If we want the value of a particular configuration variable (key) then we just pass the key as we do for the perl blogs data file above.</p>

<h2>Conclusion</h2>

<p>Config::JFDI combined with Config::General provide a nice way to separate configuration information from a Catalyst application so it can be re-used elsewhere such as a command line script.  </p>]]>
    </content>
</entry>

<entry>
    <title>Getting Scrappy with Modern Perl</title>
    <link rel="alternate" type="text/html" href="http://www.catalyzed.org/2010/09/getting-scrappy-with-modern-perl.html" />
    <id>tag:www.catalyzed.org,2010://1.91</id>

    <published>2010-09-09T02:13:34Z</published>
    <updated>2010-09-09T15:42:44Z</updated>

    <summary>Modern Perl is all the rage these days in case you hadn&apos;t noticed. But why, might you ask. I will demonstrate a scraper program that stores its results in an object database using such juicy bits as Scrappy (a web...</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="Perl" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="en" xml:base="http://www.catalyzed.org/">
        <![CDATA[<p>Modern Perl is all the rage these days in case you hadn't noticed.  But why, might you ask.  I will demonstrate a scraper program that stores its results in an object database using such juicy bits as Scrappy (a web scraper that in turn uses the Web::Scraper toolkit),  KiokuDB (an object store), and of  course Moose.</p>]]>
        <![CDATA[<h1>The Goal</h1>

<p>Search craigslist for homes matching certain criterion.  For example, we'll search  for cabins in Montana for sale by owner that fall within a certain price range.</p>

<h1>  The  CraigHome Class</h1>

<p>The search results give rise to natural objects where one object is a single result (ad) of  the search.  The search we'll study is about finding a home (cabin).  Let's call the class <b>CraigHome</b>.  It is defined like a typical (simple) Moose class:</p>



<pre>
package CraigHome;
use Moose;
use namespace::autoclean;

has id =&gt; (
    is  =&gt; 'ro',
    isa =&gt; 'Int',
);

has text =&gt; (
    is  =&gt; 'ro',
    isa =&gt; 'Str',
);

has 'link' =&gt; (
    is  =&gt; 'ro',
    isa =&gt; 'URI',
);

has amount =&gt; (
    is  =&gt; 'ro',
    isa =&gt; 'Num',
);

has search_URL =&gt; (
    is  =&gt; 'ro',
    isa =&gt; 'Str',
);

has search_keywords =&gt; (
    is  =&gt; 'ro',
    isa =&gt; 'Str',
);

has search_name =&gt; (
    is  =&gt; 'ro',
    isa =&gt; 'Str',
);

__PACKAGE__-&gt;meta-&gt;make_immutable;
1
</pre>



<h1>Search and Store Results</h1>

<p>We'll use a script to scrape the search results and then store them for later analysis.</p>

<h2>Load needed modules</h2>



<pre>
use strict;
use warnings;

use Scrappy qw/:syntax/;
use KiokuDB;
use KiokuDB::Backend::DBI;
use CraigHome;
</pre>



<p>Notice that we use Scrappy, KiokuDB,  the <span class="caps">DBI </span>backend for KiokuDB and our custom class CraigHome.</p>

<h2> Define the Search Parameters</h2>

<p>The search parameters include:</p>


<ul>
<li>a search name</li>
<li>a <span class="caps">URL </span>to search</li>
<li>keywords to search for</li>
<li>max. and min. dollar  amounts</li>
</ul>





<pre>
my %search_definitions = (
    1 =&gt; {
        search_name =&gt; 'montana_cabin_by_owner',
        search_URIs =&gt; [
            'http://montana.craigslist.org/reo/',
            'http://missoula.craigslist.org/reo/', 
            'http://bozeman.craigslist.org/reo/'
        ],
        keywords  =&gt; [qw/ cabin /],
        max_price =&gt; 60000,
        min_price =&gt; 1,
    },
);
</pre>



<h2>  Connect to Kioku Data Store and Designate Columns for Searching</h2>

<p>In this example, we use the <span class="caps">DBI </span>backend and connect to a <span class="caps">SQL</span>ite database where we store stuff.  In addition, we define two attributes of our CraigHome object that we want to search on.  Doing so will index the attributes (so to speak) to provide for more efficient searches.  One could always just grep the object attributes from a list of all objects.</p>



<pre>
my $db = KiokuDB-&gt;connect(
    &quot;dbi:SQLite:dbname=db/craighomes.db&quot;,
    create  =&gt; 1,
    columns =&gt; [
        search_name =&gt; {
            data_type   =&gt; &quot;varchar&quot;,
            is_nullable =&gt; 0, 
        },
        amount =&gt; {
            data_type   =&gt; &quot;int&quot;,
            is_nullable =&gt; 0, 
        },
    ]
);
my $scope_object = $db-&gt;new_scope;
</pre>



<h2>Run the main logic</h2>



<pre>
main();

sub main {
    init;
    user_agent random_ua;

    # Do the searches
    foreach my $search_definition ( values %search_definitions ) {

        # A search definition can have mulitple search URLs 
        # for the same keywords
        foreach my $search_URL ( @{ $search_definition-&gt;{search_URIs} } ) {
            process_search( $search_URL, $search_definition );
        }
    }
}
</pre>



<p>The main logic initializes a Scrappy agent then loops through each search defined (only 1 in this example) and then processes each search <span class="caps">URL. </span> In this example we search the (old) Montana page, then the city pages for Missoula and Bozeman.</p>

<h2>Process the Search</h2>

<p>This part fills out the search form then extracts each listing from the results using <b>Scrappy</b>.  Notice the barewords Scrappy uses: init, user_agent, form_fields, loaded etc.  We then pass each listing to the <em>process_listing</em> function.</p>



<pre>
sub process_search {
    my $search_URL        = shift;
    my $search_definition = shift;

    get $search_URL;
    my $keywords_string = join ' ', @{ $search_definition-&gt;{keywords} };
    my $search_name = $search_definition-&gt;{search_name};
    form fields =&gt; {
        'minAsk' =&gt; $search_definition-&gt;{min_price},
        'maxAsk' =&gt; $search_definition-&gt;{max_price},
        'query'  =&gt; $keywords_string,
    };

    print &quot;Processing search: &quot;, $search_definition-&gt;{search_name},
      &quot; at URL: ${search_URL} with keywords: $keywords_string\n&quot;;

    # Process each listing, looking for keyword match.
    if (loaded) {
        var listings =&gt; grab 'p a', { name =&gt; 'TEXT', link =&gt; '@href' };
        var listings_textos =&gt; grab 'p', { name =&gt; 'TEXT' };
        foreach my $listing ( list var-&gt;{listings} ) {
            process_listing( $listing, $search_URL, $keywords_string, $search_name );
        }
    }
}
</pre>



<h2>Process each Listing</h2>

<p>Now that we've plucked the listings we're interested in, let's store them for later analysis.  Here we build an instance of our custom CraigHome class, and then persist (store) the object using KiokuDB.</p>



<pre>
sub process_listing {
    my $listing         = shift;
    my $search_URL      = shift;
    my $keywords_string = shift;
    my $search_name     = shift;

    my $listing_amount = listing_amount($listing);
    my $listing_id     = listing_id($listing);
    my $listing_object = CraigHome-&gt;new(
        amount          =&gt; $listing_amount,
        text            =&gt; $listing-&gt;{name},
        'link'          =&gt; $listing-&gt;{link},
        id              =&gt; $listing_id,
        search_URL      =&gt; $search_URL,
        search_keywords =&gt; $keywords_string,
        search_name     =&gt; $search_name,
    );
    if ( is_new_listing_id($listing_id) ) {
        $db-&gt;store( $listing_id =&gt; $listing_object );
    }
}
</pre>



<p>Now imagine writing something like this in the 1990's or even early 2000's, ouch.  Modern Perl helps get shit done with grace and elegance.</p>

<h2>Some helper Functions</h2>

<p>For completeness we have the following helper functions that extract the listing amount, listing id and determine if we have already have the listing on store.</p>



<pre>
sub listing_amount {
    my $listing = shift;
    my ($amount) = $listing-&gt;{name} =~ m{^\$(\d+)};

    return $amount;
}

sub listing_id {
    my $listing = shift;
    my ($listing_id) = $listing-&gt;{link} =~ m/(\d+)\.html$/;

    return $listing_id;
}

sub is_new_listing_id {
    my $listing_id = shift;

    return !$db-&gt;lookup($listing_id) ? 1 : 0;
}
</pre>



<h2>Further Analysis</h2>

<p>Now that we have the information on store, we would like to report on it. i.e. retrieve  the listing objects that we just stored.  That part is left as an exercise to the reader or stay tuned for a follow up article.</p>

<h2>Credits</h2>

<p>Thanks to <em>perigrin</em> and <em>doy</em> for penetrating my thick skin with an inkling of knowledge about KiokuDB.</p>

<h2>Disclaimer</h2>

<p>This program is intended for personal use not commercial interests.</p>]]>
    </content>
</entry>

<entry>
    <title>YAPC::2010!</title>
    <link rel="alternate" type="text/html" href="http://www.catalyzed.org/2010/06/yapc2010-a-review.html" />
    <id>tag:www.catalyzed.org,2010://1.88</id>

    <published>2010-06-24T18:00:00Z</published>
    <updated>2010-06-24T17:32:00Z</updated>

    <summary>YAPC this year was great. I met a lot of people I only knew on the interwebs, went to some great talks, and got my ass heckled. I enjoyed every moment of it. Matt Trout gave a great ironman forfeit...</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="2010" label="2010" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="catalyst" label="catalyst" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="extending" label="extending" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="moose" label="moose" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="perl" label="perl" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="poe" label="poe" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="talks" label="talks" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="yapc" label="yapc" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en" xml:base="http://www.catalyzed.org/">
        <![CDATA[<p>YAPC this year was great.</p>

<p>I met a lot of people I only knew on the interwebs, went to some great talks, and got my ass heckled.  I enjoyed every moment of it.</p>

<p>Matt Trout gave a great ironman forfeit talk, Stevan Little gave a great keynote on Tuesday, Nick Perez gave (6) great talks, 2 of which I was able to attend, Jesse Leuhrs showed me how to extend Moose like a boss, Chris Prather told me why MooseX::POE sucks and why I shouldn't use it, and I learned some Klingon from Paul Fenwick.  Jay Shirley talked about a sensible way to use templates to control your UI, keeping designers AND programmers happy, and Cory Watson talked about selling Moose to your bosses and managing your data verification stack with Data::Manager.</p>

<p>My talks went mostly okay.  Intro to Catalyst was a bit of a farce, but hey! We all learned something that day: Catalyst makes things get done faster.  Thumbit was fun to talk about, and I actually got a good deal of hacking done on the code to make it (almost) work.  Google Summer of Code will always be near and dear to my heart, my first talk, which is about my first dip into the magical waters of open source development.</p>

<p>I bid YAPC2010 a fond farewell, and shout outs to every one I met and everyone I got to hang out with after hours.</p>

<p>Until next year!</p>
]]>
        

    </content>
</entry>

<entry>
    <title>Using Bread::Board to Create a Config API</title>
    <link rel="alternate" type="text/html" href="http://www.catalyzed.org/2010/06/using-breadboard-to-create-a-config-api.html" />
    <id>tag:www.catalyzed.org,2010://1.87</id>

    <published>2010-06-11T09:09:00Z</published>
    <updated>2010-06-11T20:51:35Z</updated>

    <summary>I&apos;ve finally been able to play with the massively fun toy that is Bread::Board. What is it, you say? Bread::Board is basically a way to wire application components up in a DRY, and efficient manner. This is extremely useful for...</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="board" label="board" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="bread" label="bread" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="config" label="config" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="services" label="services" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en" xml:base="http://www.catalyzed.org/">
        <![CDATA[<p>I've finally been able to play with the massively fun toy that is Bread::Board.</p>

<p>What is it, you say?</p>

<p>Bread::Board is basically a way to wire application components up in a DRY, and efficient manner.  This is extremely useful for application configuration, and application setup (database handles/connection pooling, configuration file location, logger class setup, etc.).</p>

<p>The example I have put together involves the above, with a relatively sane method for setting up a configuration API so it's reusable and not a TOTAL pain in the ass.</p>

<p>Basically, I looked at <a href="http://github.com/perigrin/blawd">blawd</a> and stole the configuration bits and mangled them into something I could use.</p>

<p>Check it out (this comes from my minimal CMS <a href="http://github.com/dhoss/Deimos">Deimos</a>:</p>

<pre><code>package Deimos::ConfigContainer;
use Moose;
use namespace::autoclean;
use Bread::Board;
use Data::Dumper;
use Deimos::Schema; 
use Config::JFDI;
use Template;

has 'log_file_name' =&gt; (
  is      =&gt; 'ro',
  isa     =&gt; 'Str',
  default =&gt; "deimos.conf"
);

has 'config' =&gt; (
  is =&gt; 'ro',
  lazy_build =&gt; 1,
);

sub _build_config {
  my $self = shift;
  my $cfg = Config::JFDI-&gt;new( path =&gt; $something . $self-&gt;log_file_name );
  return $cfg-&gt;get;
}

sub build {
  my ($self, $service) = @_;
  my $cfg = $self-&gt;config;
  my $c = container Deimos =&gt; as {

    service 'site_title' =&gt; (
        block =&gt; sub {
            my $self = shift;
            return $self-&gt;config-&gt;{'site_title'};
        },
        dependencies =&gt; [ depends_on('config') ],
    );

    service 'log_file' =&gt; $self-&gt;log_file_name;

    service 'config' =&gt; $cfg;

    service 'schema' =&gt; (
        lifecycle =&gt; "Singleton",
        block =&gt; sub {
            warn "config: " . Dumper $cfg;
           return Deimos::Schema-&gt;connect(
               @{ $cfg-&gt;{'Database'}-&gt;{'connect_info'} },
            );
          }
    );

    service 'templates' =&gt; ( 
        block =&gt; sub {
            return Template-&gt;new($cfg-&gt;{'templates'});
        }
    );

    service 'application' =&gt; (
        class        =&gt; 'Deimos',
        dependencies =&gt; {
            schema     =&gt; depends_on('schema'),
            config     =&gt; depends_on('config'),
            site_title =&gt; depends_on('site_title'),
        }
    );
};

    return $c-&gt;fetch($service)-&gt;get;
}

 __PACKAGE__-&gt;meta-&gt;make_immutable;
1;
</code></pre>

<p>Basically, this allows you to either use your configcontainer, or, like I plan to, create a role, and apply it as needed and do $self->config->fetch('service_name');</p>

<p>This makes life MUCH much easier on the configuration front.</p>

<p>I hope this helps someone out there like it helped me when I finally got it figured out.</p>
]]>
        

    </content>
</entry>

<entry>
    <title>Catalyst::Controller::LeakTracker Tutorial</title>
    <link rel="alternate" type="text/html" href="http://www.catalyzed.org/2010/05/catalystcontrollerleaktracker-tutorial.html" />
    <id>tag:www.catalyzed.org,2010://1.86</id>

    <published>2010-05-27T00:00:00Z</published>
    <updated>2010-05-26T22:32:32Z</updated>

    <summary>Why use LeakTracker? You have a Catalyst application that is consuming more and more memory over time. You would like to find out what classes are involved and where you may have cyclic references. Why not try out nothingmuch&apos;s handy...</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="catalystleaktrackerperl" label="catalyst leaktracker perl" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en" xml:base="http://www.catalyzed.org/">
        <![CDATA[<h1>Why use LeakTracker?</h1>

<p>You have a Catalyst application that is consuming more and more memory over time. You would like to find out what classes are involved and where you may have cyclic references.  Why not try out <em>nothingmuch's</em> handy dandy <b>Catalyst::Controller::LeakTracker</b>.</p>

<p><a href="http://suryahunter.com/wiki/hunter/perl_ironman/leaktracker_tutorial">Full Article</a></p>]]>
        
    </content>
</entry>

<entry>
    <title>Transactions with DBIC</title>
    <link rel="alternate" type="text/html" href="http://www.catalyzed.org/2010/05/transactions-with-dbic.html" />
    <id>tag:www.catalyzed.org,2010://1.85</id>

    <published>2010-05-10T05:59:00Z</published>
    <updated>2010-05-09T18:55:58Z</updated>

    <summary>Overview Transactions are an important feature of many database management systems. Transactions allow one to make changes to a data store in a reliable way that can gracefully handle failure. In short you are guaranteed that the changes take place...</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="Perl" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="en" xml:base="http://www.catalyzed.org/">
        <![CDATA[<h1>Overview</h1>

<p>Transactions are an important feature of many database management systems.  Transactions allow one to make changes to a data store in a reliable way that can gracefully handle failure. In short you are guaranteed that the changes take place in their entirety or not at all.  In addition, transactions provide isolation for concurrent transactions to avoid data from being changed out from under you. This petit article demonstrates transactions using <span class="caps">DBI</span>x::Class, a kickass <span class="caps">ORM </span>for Perl.</p>

<p><a href="http://wisdom.webhop.org/wiki/hunter/database/orm/transactions_with_dbic">Full Article</a></p>]]>
        
    </content>
</entry>

</feed>

