<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Arisdottle</title>
	<atom:link href="http://arisdottle.net/feed/" rel="self" type="application/rss+xml" />
	<link>http://arisdottle.net</link>
	<description>Adventures in Modern Perl</description>
	<lastBuildDate>Fri, 07 Oct 2011 17:29:39 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.2.1</generator>
		<item>
		<title>Multiple Table Inheritance?</title>
		<link>http://arisdottle.net/2011/10/multiple-table-inheritance/</link>
		<comments>http://arisdottle.net/2011/10/multiple-table-inheritance/#comments</comments>
		<pubDate>Fri, 07 Oct 2011 16:43:57 +0000</pubDate>
		<dc:creator>amiri</dc:creator>
				<category><![CDATA[databases]]></category>
		<category><![CDATA[iron man competition]]></category>
		<category><![CDATA[object-relation mapping]]></category>
		<category><![CDATA[perl]]></category>
		<category><![CDATA[DBIx::Class]]></category>
		<category><![CDATA[Perl]]></category>
		<category><![CDATA[PostgreSQL]]></category>

		<guid isPermaLink="false">http://arisdottle.net/?p=78</guid>
		<description><![CDATA[DBIx::Class::ResultSource::MultipleTableInheritance is finally out. The idea behind multiple table inheritance is to combine multiple tables behind a view that is writable and updateable like a normal table, which can allow you to do all sorts of nifty things. The combination of the tables is accomplished via a set of triggers and rules for insertion and [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://metacpan.org/module/DBIx::Class::ResultSource::MultipleTableInheritance">DBIx::Class::ResultSource::MultipleTableInheritance</a> is finally out.</p>
<p>The idea behind multiple table inheritance is to combine multiple tables behind a view that is writable and updateable like a normal table, which can allow you to do all sorts of nifty things. The combination of the tables is accomplished via a set of triggers and rules for insertion and deletion. These rules are the heart of the beast. Check out the synopsis for some examples.</p>
<p><a href="http://www.shadowcat.co.uk/blog/matt-s-trout/">mst</a> first <a href="http://conferences.yapceurope.org/lpw2008/talk/1657">spoke</a> about this at the <a href="http://conferences.yapceurope.org/lpw2008/talks">London Perl Workshop</a> in 2008, and he recorded <a href="http://www.shadowcat.co.uk/archive/conference-video/nwepm/postgres/">a video about it</a> at nwe.pm in 2009.</p>
<p>The rule-generation is <a class="zem_slink" title="PostgreSQL" href="http://www.postgresql.org" rel="homepage">Postgres</a>-specific now, but theoretically, if a database has writable views, MTI should be able to support it. Theoretically.</p>
<p>Try it out!</p>
<div class="zemanta-pixie" style="margin-top: 10px; height: 15px;"><a class="zemanta-pixie-a" title="Enhanced by Zemanta" href="http://www.zemanta.com/"><img class="zemanta-pixie-img" style="float: right;" src="http://img.zemanta.com/zemified_e.png?x-id=4a2dc6ab-13d4-486d-81d3-1479496cef1c" alt="Enhanced by Zemanta" /></a></div>
]]></content:encoded>
			<wfw:commentRss>http://arisdottle.net/2011/10/multiple-table-inheritance/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Strange Interviewing Experiences</title>
		<link>http://arisdottle.net/2010/02/strange-interviewing-experiences/</link>
		<comments>http://arisdottle.net/2010/02/strange-interviewing-experiences/#comments</comments>
		<pubDate>Thu, 11 Feb 2010 04:36:12 +0000</pubDate>
		<dc:creator>amiri</dc:creator>
				<category><![CDATA[economy]]></category>
		<category><![CDATA[job interviews]]></category>
		<category><![CDATA[jobs]]></category>
		<category><![CDATA[perl]]></category>
		<category><![CDATA[economic crisis]]></category>
		<category><![CDATA[job hunting]]></category>
		<category><![CDATA[Perl]]></category>

		<guid isPermaLink="false">http://arisdottle.net/?p=56</guid>
		<description><![CDATA[I moved from New York where I had a good job with bad bosses to Los Angeles, California, one of the epicenters of the economic crisis. I&#8217;ve been on my new job for 3 weeks now, and I am settling in enough to reflect a bit on the job hunt. It sure was strange! Perl [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://arisdottle.net/wp-content/uploads/2011/01/StrangeInterviewingExperiences.jpg"><img class="begin_post_pic" title="StrangeInterviewingExperiences" src="http://arisdottle.net/wp-content/uploads/2011/01/StrangeInterviewingExperiences.jpg" alt="" width="150" height="150" /></a>I moved from New York where I had a good job with bad bosses to Los Angeles, California, one of the epicenters of the economic crisis.</p>
<p>I&#8217;ve been on my new job for 3 weeks now, and I am settling in enough to reflect a bit on the job hunt.</p>
<p>It sure was strange!</p>
<p><a class="zem_slink" title="Perl" rel="wikipedia" href="http://en.wikipedia.org/wiki/Perl">Perl</a> experts kept telling me a couple of things over and over:</p>
<blockquote><p>Interviewer: How do you switch a hash&#8217;s keys and values?<br />
Me: reverse %hash…<br />
Interviewer: WRONG! You fail!<br />
Me: Um…<br />
Interviewer How would you print sorted the values of a hash?<br />
Me: print sort values %hash…<br />
Interviewer: WRONG! You fail!<br />
Me: Wait a second, that&#8217;s correct…<br />
Interviewer: No it&#8217;s not. Next question. Have you ever written your own assembly implementation of partial sort?</p></blockquote>
<p>The above happened to me twice. Not in so many words, but you get the idea: combine a flagrantly outdated understanding of Perl with the desire to show off hardcore l33tn355, and keep the belly laughs coming!</p>
]]></content:encoded>
			<wfw:commentRss>http://arisdottle.net/2010/02/strange-interviewing-experiences/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Some Module Ideas</title>
		<link>http://arisdottle.net/2009/07/some-module-ideas/</link>
		<comments>http://arisdottle.net/2009/07/some-module-ideas/#comments</comments>
		<pubDate>Wed, 08 Jul 2009 17:20:56 +0000</pubDate>
		<dc:creator>amiri</dc:creator>
				<category><![CDATA[object-oriented programming]]></category>
		<category><![CDATA[object-relation mapping]]></category>
		<category><![CDATA[perl]]></category>
		<category><![CDATA[Create read update and delete]]></category>
		<category><![CDATA[DBIx::Class]]></category>
		<category><![CDATA[Moose]]></category>
		<category><![CDATA[Remote procedure call]]></category>
		<category><![CDATA[Representational State Transfer]]></category>

		<guid isPermaLink="false">http://arisdottle.net/?p=25</guid>
		<description><![CDATA[I hope I&#8217;m not too late in my third week of posting for the iron man contest. My last post was on May 31, and so I should have posted something by June 7, but I was traveling cross-country to my original hometown of Los Angeles! Talk about a car city. I think that&#8217;s a [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://arisdottle.net/wp-content/uploads/2011/01/SomeModuleIdeas.jpg"><img class="begin_post_pic" title="SomeModuleIdeas" src="http://arisdottle.net/wp-content/uploads/2011/01/SomeModuleIdeas.jpg" alt="" width="150" height="150" /></a>I hope I&#8217;m not too late in my third week of posting for the iron man contest. My last post was on May 31, and so I should have posted something by June 7, but I was traveling cross-country to my original hometown of Los Angeles! <a href="http://metalabel.com/derailleur/An_Iron_Man_With_Stone_Age_Technology.html">Talk about a car city</a>. I think that&#8217;s a good enough excuse. We&#8217;ll see if I get busted back to paper man.</p>
<p>I wanted to extend on my last post about a way to make sure your multiple-table-inheritance database can be updated properly across whatever views you are running your app off of. But I just got some new code to look at for that, and haven&#8217;t quite grokked it yet. So that will have to wait till next time.</p>
<p>Meanwhile, I&#8217;d like to present a couple of ideas I have been working on in my Metalabel rewrite, and perhaps solicit some feedback. I&#8217;d love to hear suggestions or strategies. The first is a module some people have seen around—it is called <a href="http://github.com/amiri/Moosifier">Moosifier</a>, and it takes <a href="http://search.cpan.org/~ilmari/DBIx-Class-Schema-Loader-0.04006/lib/DBIx/Class/Schema/Loader.pm">DBIx::Class Schema::Loader</a> result class files, reads them, and adds <a href="http://search.cpan.org/~drolsky/Moose-0.81/lib/Moose.pm">Moose</a> bits at the top and bottom to allow you to use your auto-generated classes with <a href="http://search.cpan.org/~mstrout/Reaction/">Reaction</a> or whatever.</p>
<p>Before:</p>
<pre><code>
    package Test::Schema::Amazon;

    use strict;
    use warnings;

    use base 'DBIx::Class';

    __PACKAGE__-&gt;load_components("TimeStamp", "Core");
    __PACKAGE__-&gt;table("amazon");
    __PACKAGE__-&gt;add_columns(
      "asin",
      {
        data_type =&gt; "text",
        default_value =&gt; undef,
        is_nullable =&gt; 1,
        size =&gt; undef,
      },
    ...
    1;
</code></pre>
<p>After:</p>
<pre><code>
    package Test::Schema::Amazon;

    use Moose;

    extends 'DBIx::Class';

    has 'asin' =&gt; (
                    isa =&gt; SimpleStr,
                    is =&gt; 'rw',
                    required =&gt; 0

    );
    has 'locale' =&gt; (
                    isa =&gt; SimpleStr,
                    is =&gt; 'rw',
                    required =&gt; 0

    );
    has 'filename' =&gt; (
                    isa =&gt; SimpleStr,
                    is =&gt; 'rw',
                    required =&gt; 0

    );
    has 'refetchdate' =&gt; (
                    isa =&gt; Int,
                    is =&gt; 'rw',
                    required =&gt; 0

    );

    use namespace::autoclean;

    __PACKAGE__-&gt;load_components("TimeStamp", "Core");
    __PACKAGE__-&gt;table("amazon");
    __PACKAGE__-&gt;add_columns(
      "asin",
      {
        data_type =&gt; "text",
        default_value =&gt; undef,
        is_nullable =&gt; 1,
        size =&gt; undef,
      },
    ...
    __PACKAGE__-&gt;meta-&gt;make_immutable(inline_constructor =&gt; '0');
    1;
</code></pre>
<p>I wrote it because I thought I was going to be using Reaction in my rewrite, but <a href="http://www.catalyzed.org/mt/mt-cp.cgi?__mode=view&amp;blog_id=1&amp;id=34">phaylon</a> advised against it. <a href="http://search.cpan.org/~mstrout/Reaction-0.002000/lib/Reaction/Manual/Intro.pod">It adds a whole other layer to Catalyst&#8217;s M, V and C</a>, and I agreed that it&#8217;s wisest to make sure the basic rewrite is solid before adding a whole new layer, and, for instance, having to think about chopping my as-yet-unwritten templates into widgets or what have you.</p>
<p>Thus <a href="http://github.com/amiri/Moosifier">Moosifier</a>. It&#8217;s pretty darned simple: it works by reading the result class files and using a bunch of regexes to extract the <a href="http://search.cpan.org/~drolsky/Moose-0.81/lib/Moose/Manual/Attributes.pod">Moose attributes</a> from the <code>__PACKAGE__-&gt;add_columns(...)</code> lines. I was excited to put it up and finish it, but no sooner had I done so than I hit upon another problem. Now that I had my classes written, I had to make my controllers.</p>
<p>Metalabel 2.0 needs at least 76 controllers. There&#8217;s no way I&#8217;m going to write those by hand. I could use myapp/script/myapp_create.pl helper script to make skeleton controllers, of course. But that&#8217;s just a skeleton. What about <a href="http://search.cpan.org/~hkclark/Catalyst-Manual-5.8000/lib/Catalyst/Manual/Tutorial/04_BasicCRUD.pod">basic CRUD</a>? There&#8217;s no way I&#8217;m going to write CRUD for 76 controllers by hand.</p>
<p>I asked on <a href="irc://irc.perl.org/catalyst">#catalyst</a> whether there are any tools to help generate CRUD automatically in your controllers, and glob recommended <a href="http://search.cpan.org/~lsaunders/Catalyst-Controller-DBIC-API-1.003000/lib/Catalyst/Controller/DBIC/API.pm">Catalyst::Controller::DBIC::API</a>, for which there are <a href="http://search.cpan.org/~lsaunders/Catalyst-Controller-DBIC-API-1.003000/lib/Catalyst/Controller/DBIC/API/RPC.pm">RPC</a> and <a href="http://search.cpan.org/~lsaunders/Catalyst-Controller-DBIC-API-1.003000/lib/Catalyst/Controller/DBIC/API/REST.pm">REST</a> implementations. Of course, these just provide a way to write your CRUD. They don&#8217;t do it for you. So I had a new automation problem: &#8220;How can I automate the creation of basic but smart RPC or REST controllers for my Catalyst app, based on my DBIx::Class::Schema::Loader result classes?&#8221;</p>
<p>Of course I asked on irc first. Knowing that I had done something similar with Moosifier, <a href="http://www.shadowcat.co.uk/blog/matt-s-trout/">mst</a> suggested that instead of reading the files from disk, I take the table info directly from the database using DBIx::Class::Schema::Loader. Why the hell not? It makes much more sense than stepping through a file with regexes and substitutions and such.</p>
<p>The goal is to create 76+ controllers (in this case, of the RPC subclass) like this sample code from the <a href="http://search.cpan.org/~lsaunders/Catalyst-Controller-DBIC-API-1.003000/lib/Catalyst/Controller/DBIC/API.pm">Catalyst::Controller::DBIC::API documentation</a>:</p>
<pre>        <code>
    package MyApp::Controller::API::RPC::Artist;
    use base qw/Catalyst::Controller::DBIC::API::RPC/;

    __PACKAGE__-&gt;config ( action =&gt; { setup =&gt; { PathPart =&gt; 'artist', Chained =&gt; '/api/rpc/rpc_base' } },
    class =&gt; 'MyAppDB::Artist', # DBIC schema class
    create_requires =&gt; ['name', 'age'], # columns required to create
    create_allows =&gt; ['nickname'], # additional non-required columns that create allows
    update_allows =&gt; ['name', 'age', 'nickname'], # columns that update allows
    list_returns =&gt; [qw/name age/], # columns that list returns
    list_prefetch =&gt; ['cds'], # relationships that are prefetched when no prefetch param is passed
    list_prefetch_allows =&gt; [ # every possible prefetch param allowed
        'cds',
        qw/ cds /,
        { cds =&gt; 'tracks' },
        { cds =&gt; [qw/ tracks /] }
    ],
    list_ordered_by =&gt; [qw/age/], # order of generated list
    list_search_exposes =&gt; [qw/age nickname/, { cds =&gt; [qw/title year/] }],
    );
</code>
</pre>
<p>I figure I can dump out such a controller for every table I need by pulling the whole database into a hash using DBIx::Class::Schema::Loader, and using this hash to populate the <code>__PACKAGE__-&gt;config(...)</code> for each table/controller. For instance, the class name is easy. So is <code>create_requires</code>: those are the non-nullable columns in the table, besides any auto-incrementing serials or sequences. <code>create_allows</code> is every column but those in <code>create_required</code>, also excluding serials and sequences. <code>update_allows</code> is the columns in both <code>create_allows</code> and <code>create_requires</code>. I can&#8217;t escape some manual labor here: I am going to make <code>list_returns</code> return every column in the table. I&#8217;ll go through the controllers by hand to customize those. The same with <code>list_prefetch_allows</code>: the object of every relationship identified by DBIx::Class::Schema::Loader is going into <code>list_prefetch_allows</code> (none are going into the default <code>list_prefetch</code>). I&#8217;ll have to customize those manually, as well. <code>list_ordered_by</code> may need to be manually specified later as well, but using date column if it exists might be a good default. <code>list_search_exposes</code> will expose everything by default.</p>
<p>So, I am in the process of writing 2 modules to do this: one for RPC and one for REST. They&#8217;ll be on my <a href="http://github.com/amiri">github</a> soon.</p>
<p>Meanwhile, using DBIx::Class::Schema::Loader to read table definitions directly from the database in these modules has made me realize I need to change Moosifier to do the same. In fact, D::C::S::Loader simply needs to be able to write the Moose declarations itself. Moosifier needs to move into Loader.</p>
<p>That&#8217;s my next project.</p>
<p>EDIT:</p>
<p><a href="http://github.com/amiri/DBIx-Class-Schema-Loader-0.04999_07/tree/master">There&#8217;s a branch for it now</a>. I need some tests though.</p>
]]></content:encoded>
			<wfw:commentRss>http://arisdottle.net/2009/07/some-module-ideas/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>A Meager Attempt at CatchUp</title>
		<link>http://arisdottle.net/2009/06/a-meager-attempt-at-catchup/</link>
		<comments>http://arisdottle.net/2009/06/a-meager-attempt-at-catchup/#comments</comments>
		<pubDate>Mon, 29 Jun 2009 19:17:53 +0000</pubDate>
		<dc:creator>amiri</dc:creator>
				<category><![CDATA[iron man competition]]></category>
		<category><![CDATA[object-relation mapping]]></category>
		<category><![CDATA[perl]]></category>
		<category><![CDATA[web development]]></category>
		<category><![CDATA[CPAN]]></category>
		<category><![CDATA[Perl]]></category>

		<guid isPermaLink="false">http://arisdottle.net/?p=46</guid>
		<description><![CDATA[Well, I am definitely busted back down to paper man now. But I have a real good reason. I was JFDI. I was learning to test (I&#8217;d say I am level 1 for the moment). Boy, is testing a strange enterprise for the beginning tester. Like millions before me, I did &#8220;testing&#8221; the other way [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://arisdottle.net/wp-content/uploads/2011/01/AMeagerAttemptatCatchUp.jpg"><img class="begin_post_pic" title="AMeagerAttemptatCatchUp" src="http://arisdottle.net/wp-content/uploads/2011/01/AMeagerAttemptatCatchUp.jpg" alt="" width="150" height="150" /></a></p>
<p>Well, I am definitely busted back down to paper man now. But I have a real good reason. I was <a href="http://warpedreality.org/2009/06/the-power-of-jfdi.html">JFDI</a>. I was <a href="http://samcrawley.wordpress.com/2009/06/29/the-three-stages-of-learning-to-test/">learning to test</a> (I&#8217;d say I am level 1 for the moment). Boy, is testing a strange enterprise for the beginning tester. Like millions before me, I did &#8220;testing&#8221; the other way round: write, run, tweak, run, tweak, run, etc., etc., ad infinitum. Basically, you have to turn your mind inside out and think about your code in what feels like a pretty much inverted way. But I like the discipline it imposes.</p>
<p>I was working on <a href="http://search.cpan.org/~amiri/Catalyst-Helper-Controller-DBIC-API-REST-0.03/lib/Catalyst/Helper/Controller/DBIC/API/REST.pm">Catalyst::Helper::Controller::DBIC::API::REST</a>, which I blogged about <a href="http://metalabel.com/derailleur/Automatic_CRUD_in_your_Controllers.html">once before</a>. It&#8217;s my first <a class="zem_slink" title="CPAN" rel="homepage" href="http://www.cpan.org/">CPAN</a> module, and I&#8217;m very proud of that fact! I&#8217;m not so proud of the fact that I had to upload the thing about 5 times to get it right. In any case, it&#8217;s a good feeling to be a contributing member of the thriving <a class="zem_slink" title="Perl" rel="homepage" href="http://www.perl.org/">Perl 5</a> community. Thanks <a href="http://search.cpan.org/~ribasushi/">ribasushi</a>, <a href="http://search.cpan.org/~ilmari/">ilmari</a>, <a href="http://www.shadowcat.co.uk/blog/matt-s-trout/">mst</a>, <a href="http://blog.cachemiss.com/">Caelum</a>, <a href="http://warpedreality.org/">arcanez</a>, <a href="http://www.opensourcery.com/blog/hans-dieter-pearcey">confound</a>, <a href="http://search.cpan.org/~lsaunders/">lukes</a>, Fitz Elliott, and everyone else I bothered while putting that thing together.</p>
]]></content:encoded>
			<wfw:commentRss>http://arisdottle.net/2009/06/a-meager-attempt-at-catchup/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Automatic CRUD in your Controllers</title>
		<link>http://arisdottle.net/2009/06/automatic-crud-in-your-controllers/</link>
		<comments>http://arisdottle.net/2009/06/automatic-crud-in-your-controllers/#comments</comments>
		<pubDate>Mon, 15 Jun 2009 15:54:09 +0000</pubDate>
		<dc:creator>amiri</dc:creator>
				<category><![CDATA[object-relation mapping]]></category>
		<category><![CDATA[perl]]></category>
		<category><![CDATA[CPAN]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[Perl]]></category>
		<category><![CDATA[Representational State Transfer]]></category>

		<guid isPermaLink="false">http://arisdottle.net/?p=38</guid>
		<description><![CDATA[The first version of the module to generate CRUDdy controllers automatically is up on my github. It&#8217;s for REST first. RPC comes next. It doesn&#8217;t use the normal syntax of calls to Catalyst::Helper (e.g., myapp_create.pl)&#8211;or, rather, it uses the normal syntax differently. When you type $ catalyst.pl myapp $ cd myapp $ script/myapp_create.pl controller API::REST [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://arisdottle.net/wp-content/uploads/2011/01/AutomaticCRUDinyourControllers.jpg"><img class="begin_post_pic" title="AutomaticCRUDinyourControllers" src="http://arisdottle.net/wp-content/uploads/2011/01/AutomaticCRUDinyourControllers.jpg" alt="" width="150" height="150" /></a>The first version of the module to generate CRUDdy controllers automatically is up <a href="http://github.com/amiri/Catalyst-Helper-Controller-DBIC-API-REST-0.01/tree/master">on my github</a>. It&#8217;s for <a href="http://search.cpan.org/~lsaunders/Catalyst-Controller-DBIC-API-1.003000/lib/Catalyst/Controller/DBIC/API/REST.pm">REST</a> first. <a href="http://search.cpan.org/~lsaunders/Catalyst-Controller-DBIC-API-1.003000/lib/Catalyst/Controller/DBIC/API/RPC.pm">RPC</a> comes next. It doesn&#8217;t use the normal syntax of calls to <a href="http://search.cpan.org/~flora/Catalyst-Devel-1.18/lib/Catalyst/Helper.pm">Catalyst::Helper</a> (e.g., myapp_create.pl)&#8211;or, rather, it uses the normal syntax differently. When you type</p>
<pre><code>
$ catalyst.pl myapp
$ cd myapp
$ script/myapp_create.pl controller API::REST DBIC::API::REST myapp
</code></pre>
<p>Instead of you naming the specific controller you want to create, as usual, you just write <code>API::REST</code>. The module loads your schema from the name of your app, e.g., <code>myapp</code>, and makes all your controllers in lib/myapp/Controller/API/REST/.</p>
<p>This module is incomplete. It remains to basically fill in the template to supply a whole<code>__PACKAGE__-&gt;config(...)</code>. I also need to write out the lib/myapp/Controller/API.pm and the lib/myapp/Controller/API/REST.pm, in order to supply the base of <a href="http://search.cpan.org/~lsaunders/Catalyst-Controller-DBIC-API-1.003000/lib/Catalyst/Controller/DBIC/API.pm#setup">the chain all the result-class controllers use</a>. I think I&#8217;ll release this one to <a class="zem_slink" title="CPAN" rel="homepage" href="http://www.cpan.org/">CPAN</a> when I&#8217;m done, cause this one is independent, unlike the moosified branch of Loader.</p>
<p>Any and all feedback welcome. Hit me up on <a class="zem_slink" title="Internet Relay Chat" rel="wikipedia" href="http://en.wikipedia.org/wiki/Internet_Relay_Chat">IRC</a> (amiri).</p>
]]></content:encoded>
			<wfw:commentRss>http://arisdottle.net/2009/06/automatic-crud-in-your-controllers/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>I’m In Ur Loader</title>
		<link>http://arisdottle.net/2009/06/im-in-ur-loader/</link>
		<comments>http://arisdottle.net/2009/06/im-in-ur-loader/#comments</comments>
		<pubDate>Sun, 14 Jun 2009 00:34:41 +0000</pubDate>
		<dc:creator>amiri</dc:creator>
				<category><![CDATA[object-oriented programming]]></category>
		<category><![CDATA[object-relation mapping]]></category>
		<category><![CDATA[perl]]></category>
		<category><![CDATA[Moose]]></category>

		<guid isPermaLink="false">http://arisdottle.net/?p=31</guid>
		<description><![CDATA[So, I&#8217;ve been working on this Loader thing, trying to get it to write Moose attributes for all sorts of class data and stuff. One major problem was that Loader runs through its cycle twice, and it dumps the schema twice. The first time there&#8217;s no relationship information, because it hasn&#8217;t gotten it. The second [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://arisdottle.net/wp-content/uploads/2011/01/ICanHasArrayRef.jpg"><img class="begin_post_pic" title="ICanHasArrayRef" src="http://arisdottle.net/wp-content/uploads/2011/01/ICanHasArrayRef.jpg" alt="" width="150" height="150" /></a>So, I&#8217;ve been working on this <a href="http://github.com/amiri/DBIx-Class-Schema-Loader-0.04999_07/tree/master">Loader</a> thing, trying to get it to write <a class="zem_slink" title="Moose (Perl)" rel="wikipedia" href="http://en.wikipedia.org/wiki/Moose_%28Perl%29">Moose</a> attributes for all sorts of class data and stuff.</p>
<p>One major problem was that Loader runs through its cycle twice, and it dumps the schema twice. The first time there&#8217;s no relationship information, because it hasn&#8217;t gotten it. The second time, after it gets the info and writes its relationship declarations&#8230; you still can&#8217;t get it! There&#8217;s a huge <code>{_dump_storage}</code> key in Loader&#8217;s <code>$self</code>, but if I wanted to parse that language, I would have stayed getting it from the files on disk. I honestly still don&#8217;t know what Loader does with all the relationship info after writing it out.</p>
<p>Well, that was dispiriting. So I gave up and just decided to get the info again and build my own relationship hash while iterating through the classes. It works pretty well.</p>
<p>One outstanding issue is how more subtly to handle relationships to other tables. Right now, if the relationship method is <code>might_have</code> Loader says</p>
<pre><code>
has 'posted_item' =&gt; (
	isa =&gt; 'Test::Schema::PostedItem',
	is =&gt; 'rw',
);
</code></pre>
<p>If the relationship method is <code>has_many</code>, Loader says</p>
<pre><code>
has 'discussion_topics' =&gt; (
	isa =&gt; ArrayRef['Test::Schema::DiscussionTopic'],
	is =&gt; 'rw',
);
</code></pre>
<p>It&#8217;s sort of a one-trick pony.</p>
]]></content:encoded>
			<wfw:commentRss>http://arisdottle.net/2009/06/im-in-ur-loader/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>How I Learned to Write a Real Database Schema</title>
		<link>http://arisdottle.net/2009/05/how-i-learned-to-write-a-real-database-schema/</link>
		<comments>http://arisdottle.net/2009/05/how-i-learned-to-write-a-real-database-schema/#comments</comments>
		<pubDate>Sun, 31 May 2009 20:07:22 +0000</pubDate>
		<dc:creator>amiri</dc:creator>
				<category><![CDATA[databases]]></category>
		<category><![CDATA[perl]]></category>
		<category><![CDATA[web development]]></category>
		<category><![CDATA[Database]]></category>
		<category><![CDATA[Domain model]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[Object-relational mapping]]></category>
		<category><![CDATA[Perl]]></category>
		<category><![CDATA[PostgreSQL]]></category>
		<category><![CDATA[Relational database]]></category>
		<category><![CDATA[SQL]]></category>
		<category><![CDATA[Unique key]]></category>

		<guid isPermaLink="false">http://arisdottle.net/?p=8</guid>
		<description><![CDATA[This is about how I learned to make a real database schema. It was my first exposure to roles and the generally more robust practice of &#8220;multiple inheritance&#8221; object-oriented database design. This is one wheel I would never have reinvented on my own, either. So, I had no clue what I was doing, really. My [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://arisdottle.net/wp-content/uploads/2011/01/HowILearnedtoWriteARealDatabaseSchema.jpg"><img class="begin_post_pic" title="HowILearnedtoWriteARealDatabaseSchema" src="http://arisdottle.net/wp-content/uploads/2011/01/HowILearnedtoWriteARealDatabaseSchema.jpg" alt="" width="150" height="150" /></a>This is about how I learned to make a real database schema. It was my first exposure to roles and the generally more robust practice of <a href="http://www.shadowcat.co.uk/archive/conference-video/nwepm/postgres/">&#8220;multiple inheritance&#8221; object-oriented database design</a>. This is one wheel I would never have reinvented on my own, either.</p>
<p>So, I had no clue what I was doing, really.</p>
<p>My data &#8220;model,&#8221; or my &#8220;<a class="zem_slink" title="Domain model" rel="wikipedia" href="http://en.wikipedia.org/wiki/Domain_model">domain model</a>,&#8221; if it can even be called that, was nowhere near relational. It wasn&#8217;t even a <a href="http://en.wikipedia.org/wiki/Data_warehouse">data-warehouse model</a>. It was just a bunch of stuff in some tables. There were no foreign key constraints.</p>
<p>I had to manually (in the application, which was no where near MVC) update everything to maintain the merest shred of &#8220;referential integrity.&#8221; In virtually every Mason component there was a huge &lt;%init&gt; block that not only pulled in data, but did maps, sorts, extractions, validation, etc. I might as well have been grepping through spreadsheets. I remember the day in early May 2007, when someone I considered a hardcore Perl programmer told me, &#8220;Oh, you&#8217;ll see. My <a class="zem_slink" title="Object-relational mapping" rel="wikipedia" href="http://en.wikipedia.org/wiki/Object-relational_mapping">ORM</a> keeps it real simple. You do all that stuff application side.&#8221; Ah, hubris.</p>
<p>Here&#8217;s how it used to look:</p>
<p><a href="http://arisdottle.net/wp-content/uploads/2011/01/MySQLsmall.png"><img class="alignnone size-full wp-image-16" title="MySQLsmall" src="http://arisdottle.net/wp-content/uploads/2011/01/MySQLsmall.png" alt="" width="400" height="394" /></a></p>
<p>Here&#8217;s how it looks now:</p>
<p><a href="http://arisdottle.net/wp-content/uploads/2011/01/Pgsmall.png"><img class="alignnone size-full wp-image-17" title="Pgsmall" src="http://arisdottle.net/wp-content/uploads/2011/01/Pgsmall.png" alt="" width="600" height="251" /></a></p>
<p>Wow. You can&#8217;t even really read the newer graph it&#8217;s so dense and interrelated.</p>
<p>The thing is, the current model grew organically, and I was just updating my MySQL tables and my class files manually for every additional column and accessor. After 18 months of that, adding new features, expanding this, modifying that, I had grown myself an unmanageably large helping  of spaghetti. Everything was application side, remember? No constraints in the DB, no transactions.</p>
<p>I knew I needed some help. I hired shadowcat, and they told me first to send them my current domain model. I did. They pretty much threw it out and we rewrote it from scratch.</p>
<p>Let&#8217;s take a couple of objects as an example.</p>
<ul>
<li> User</li>
<li> Artist</li>
<li> Album</li>
<li> Metalabel</li>
<li> Track</li>
<li> Label</li>
<li> Scout</li>
<li> Blog</li>
<li> Photo</li>
<li> Friend</li>
</ul>
<p>I&#8217;m only going to talk about a couple of these in detail, but you&#8217;ll get the idea. This first thing <a href="http://www.catalyzed.org/mt/mt-cp.cgi?__mode=view&amp;id=34&amp;blog_id=1">phaylon</a> noticed was that a user can do a couple of different things. A user can be an artist or a label and a user can create a metalabel. A metalabel does a subset of the functions of a user: it can make friends and it can post blogs and some other stuff. <a href="http://www.shadowcat.co.uk/blog/matt-s-trout/">mst</a> said &#8220;Smells like a role.&#8221; phaylon agreed, and came up with a couple of class declarations:</p>
<pre><code>
role Creator {
    has blog_entries_about isa ArrayRef[BlogEntry];
    has blog_entries isa ArrayRef[BlogEntry];
    has bulletins isa ArrayRef[Bulletin];
    has comments_about isa ArrayRef[Comment];
    has comments isa ArrayRef[Comments];
    has discussions isa ArrayRef[DiscussionTopic];
    has events isa ArrayRef[Event];
    has friend_requests isa ArrayRef[Friend] where is_accepted is false;
    has friends isa ArrayRef[Friend] where is_accepted is true;
    has photos isa ArrayRef[Photo];
    might have style isa CustomStyle;
    has creator isa ArtistIdentity |
                    Band |
                    Label |
                    Metalabel |
                    Scout |
                    User;
}
</code></pre>
<p>This Creator role will be consumed by all 5 classes that can “create” stuff. Those classes are ArtistIdentity, Band, Label, Metalabel, Scout, and User. Each of those classes have their own definitions. For instance:</p>
<pre><code>
class User does Addressable, Artworkable, Bloggable, Commentable, Creator, Discussable, Pollable {
    has artist_identities isa ArrayRef[ArtistIdentity];
    has credit isa CurrencyValue;
    has messages_out isa ArrayRef[Message::Private] where sender is me;
    has messages_in isa ArrayRef[Message::Private] where recipient is me;
    has messages_out isa ArrayRef[Message::Bulletin] where sender is me;
    has messages_out isa ArrayRef[Message::Bulletin::Friend] where sender is me;
    has rsvps isa ArrayRef[Event::RSVP];
    has metalabels isa ArrayRef[Metalabel];
    has labels isa ArrayRef[Label];
    has playlist isa Playlist;
    has address isa Address;
    has favorite isa Genre | Subgenre;
    might have open_id isa <a class="zem_slink" title="OpenID Foundation" rel="crunchbase" href="http://www.crunchbase.com/company/openid-foundation">OpenID</a>;
    has mail_preferences isa MailPreference;
}

</code></pre>
<p>In the User class, we first define the roles it consumes. You can see it consumes multiple roles, among them, Creator. So far, this is fairly clear, I hope. It&#8217;s just a sort of <a href="http://search.cpan.org/dist/MooseX-Declare/lib/MooseX/Declare.pm">MooseX::Declare</a>-like pseudocode now, but the basic idea is that every class does stuff. Some classes do the same stuff. That is a role. Some classes are really just instances of other superclasses. Like the Label, for instance:</p>
<pre><code>class Label isa User, does Addressable, Bloggable, Creator, Commentable, Discussable, Genred, Pollable {
    has address isa Address;
    has artists isa ArrayRef[Label::Artist];
    has billing isa Billing;
    might have paypal_id isa PayPalID
    has company_name isa Str;
    has is_incorporated isa Bool;
    has corp_state isa Str;
    has tax_id isa Str;
}
</code></pre>
<p>The real mind-bending stuff for me came when we actually began implementing this stuff in <a class="zem_slink" title="SQL" rel="wikipedia" href="http://en.wikipedia.org/wiki/SQL">SQL</a>. The most important conceptual thing for me was how everything that consumes a role has to have a unique ID. Because a role is implemented in SQL as a primary-key only table!</p>
<pre><code>
create table creator (
    id integer primary key not null
);
</code></pre>
<p>Obviously, if 5 classes are going to be consuming this role, you cannot just start each class&#8217;s table with “id serial primary key not null,” because then you coulnd&#8217;t look up a Creator by its ID. Ther would be multiple Creators with the same ID, and your database would be useless.</p>
<p>So all role consuming classes share a sequence:</p>
<pre><code>create sequence entity_seq start 1;
...

create table artist_identity (
    id integer primary key not null default nextval('entity_seq'),
    date timestamp not null default 'now',
    "user" integer not null,
    name text
);

</code></pre>
<p>This doesn&#8217;t only go for things like Creators, which are “active” tables, but also for things like Albums, which can be acted upon. My Album in Moosey pseudocode is:</p>
<pre><code>
class Album does Artworkable, Bloggable, Commentable, Discussable, Genred, Pollable, Videoable {
    has tracks isa ArrayRef[Track];
    has artist isa MusicProvider;
    has title isa NonEmptySimpleStr;
    has coverart;
    has notes isa Str;
    has is_deleted isa Bool;
    has date isa TimeStamp;
    has creation_date isa Date;
    has album_only isa Bool;
    has free isa Bool;
}
</code></pre>
<p>So, the Album object does 7 roles. It can be acted upon in 7 ways. It obviously also needs to share in the database-wide unique sequence, so I can look up any particular, say, Bloggable item by its ID:</p>
<pre><code>
create table album (
    id integer primary key not null default nextval('entity_seq'),
    date timestamp not null default 'now',
    provided_by integer not null,
    title text,
    creation_date date not null,
    notes text,
    album_only boolean,
    free boolean,
    deleted boolean
);
</code></pre>
<p>Finally, each object that consumes any role needs to have foreign keys to that role. So, the Album object needs a FK to each role it consumes. It needs 7 Fks:</p>
<pre><code>
alter table album add foreign key (id) references artworkable (id);
alter table album add foreign key (id) references bloggable (id);
alter table album add foreign key (id) references commentable (id);
alter table album add foreign key (id) references discussable (id);
alter table album add foreign key (id) references genred (id);
alter table album add foreign key (id) references pollable (id);
alter table album add foreign key (id) references videoable (id);
</code></pre>
<p>My User object needs 8:</p>
<pre><code>alter table "user" add foreign key (id) references addressable (id);
alter table "user" add foreign key (id) references artworkable (id);
alter table "user" add foreign key (id) references bloggable (id);
alter table "user" add foreign key (id) references commentable (id);
alter table "user" add foreign key (id) references creator (id);
alter table "user" add foreign key (id) references discussable (id);
alter table "user" add foreign key (id) references pollable (id);
alter table "user" add foreign key (id) references videoable (id);
</code></pre>
<p>This is to make updating your tables across views easier when records are created or deleted.</p>
<p>I still don&#8217;t fully understand that bit, so I&#8217;ll try to write about it next time. Meanwhile, if you&#8217;re not doing something like the above, and you find yourself doing lots of manual record updates in your code, you&#8217;re not using your database effectively!</p>
]]></content:encoded>
			<wfw:commentRss>http://arisdottle.net/2009/05/how-i-learned-to-write-a-real-database-schema/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
