Stories
Slash Boxes
Comments
NOTE: use Perl; is on undef hiatus. You can read content, but you can't post it. More info will be forthcoming forthcomingly.

All the Perl that's Practical to Extract and Report

use Perl Log In

Log In

[ Create a new account ]

jk2addict (4946)

jk2addict
  (email not shown publicly)
http://today.icantfocus.com/blog/
AOL IM: chrislaco (Add Buddy, Send Message)
Yahoo! ID: chrislaco@sbcglobal.net (Add User, Send Message)
Jabber: laco@scribblewerks.com

Journal of jk2addict (4946)

Wednesday August 02, 2006
11:38 AM

Forest, Trees and Handel 1.0

[ #30516 ]
Warning: no-coherent think out loud rambling ahead. I've been knee deep in refactoring for Handel 1.x. For the most part, it's going well and I've had to resort to minuscule amounts of magic to alter/enhance/molest DBIC schemas on the fly. The current progress can be found here. It's been a long journey, mostly spent figuring out how to genericize the use of DBIC schemas away from the actual Cart/Order/Item classes. The Intro and Storage manual pages give a basic overview of how it is currently. Unfortunately, I'm at a point where I can't see the forest any more because I've been staring at the trees too long. From the Storage perspective, I can call create/search methods, and get generic Storage::Result objects. it all works. Everything is happy.

my $storage = Handel::Storage::Cart->new({
    schema_class      => 'Handel::Cart::Schema',
    schema_source     => 'Carts',
    connection_info   => ['dbi:SQLite:handel.db'],
    item_relationship => 'items'
});

# returns Storage::Result object
my $result = $storage->create({
    shopper => 1,
    name    => 'My Favorites'
});
print $result->name;

# returns Handel::Iterator, that inflates to Storage::Result objects
my $results = $storage->search;
while (my $result = $results->next) {
    print $result->name;
};

Where I'm having problems is trying to use the storage results from the top level classes without making any assumptions on where the results came from. Right now, it's all DBIC, but it could just as well be result objects from a custom storage layer.

package Handel::Cart;
__PACKAGE__->storage_class('Handel::Storage::Cart');

sub new {
    my ($self, $data) = @_;
    my $result = $self->storage->create($data);

    # creates a new Handel::Cart instance, storing storage result as needed
    return $self->create_instance($result);
};

sub add {
    my ($self, $data) = @_;
    my $result = $self->result;

    # which is worse here?
    my $item = $result->add($data);

    # or, where add_item in storage does $dbicresult->add_related('items', $data)
    $my $item = $self->storage->add_item($self->result, $data);

    # or
    $my $item = $result->storage->add_item($self->result, $data);
    ...
};

My real struggle is one of relationships. In a DBIC world, I create a cart, then add items into the cart result itself using add_related(), instead of adding new items through the item->create pathway. That's a strange thing to try and abstract away from. Creating a new cart above is easy. Adding an item to that new cart can go many ways, and I'm not sure which way sucks worse than the others. In a DBIC world, one would almost never add an item to the items table using the item schema class, and would almost always add an item through the cart->add_to_item or cart_add_related relationship. This means Cart is a first class citizen, and items aren't. But above the DBIC level, abstracted away, I get the urge to treat the Items abstraction as equally as the Carts.

sub add {
    my ($self, $data) = @_;
    my $result = $result;

    # like Handel::Cart::Item->storage->create($data)
    my $item Handel::Cart::Item->new($data);
    $result->storage->add_item($item);
};

From an abstraction standpoint, this code makes sense to me. I'm creating a new item using the Item class/storage from top to bottom. But I lose all of the DBIC add_related and relationship magic. It sucks if I'm using DBIC. It's great if I'm going something like:

package Handel::Cart;
__PACKAGE__->storage_class('Handel::Google::CheckoutAPI::Cart');

If any of this makes sense to you. I'm sorry. I ramble, and I have too much code in my head the formulate sane questions. :-) Thoughts?

The Fine Print: The following comments are owned by whoever posted them. We are not responsible for them in any way.
 Full
 Abbreviated
 Hidden
More | Login | Reply
Loading... please wait.
  • I think I finally got past my mental block. It's not the most elegant solution, but hey, I'm a double music major. What the hell do I know. :-) The answer I settled on was: do both.

    Handel::Cart::add {
        return $self->result->add_item($data);
    };
    ...
    $result::add_item {
        return $self->storage->add_item($self, $item);
    };
    ...
    $storage::add_item {
        return $result->add_related($self->item_relationship, $data);
    };

    So, people writing custom storage layers can either t