Skip to Content

Moose and KiokuDB, one week in, part 2 Syndicate content

Dave Sherohman's picture

My second trip to #kiokudb came about when I got to the point of wanting to edit my objects through a web interface, which called for identifying the object I was editing. While Kioku was assigning unique IDs to each object which would be perfect for the purpose, the objects themselves didn't have access to their IDs and so couldn't provide them to my templates for insertion in the pages. Starting from my root node and walking the object graph every time seemed unreasonable and

$dir->store($obj);
$obj->id($dir->object_to_id($conf));
$dir->store($obj);
was thoroughly unsatisfactory, even ignoring its issues with handling objects stored indirectly by reference.

The answer, as mentioned by Yuval in his response to my last post, was to bring in KiokuDB::Role::ID. I had previously looked at it and dismissed it, since the docs say it's "for objects who choose their own ID" and choosing my own IDs wasn't my objective.

This turned out to basically be an XY problem, resolved by using KiokuDB::Role::UUIDs to generate the Kioku ID someplace where my objects could see (and remember) it, then "choose [my] own ID" to be the one it generated.

It took a bit of messing around with Moose and MooseX::Declare to actually get this solution to compile, as it was my first time explicitly using roles, but I got it to run... only to be greeted by "deep recursion" warnings as soon as I tried to ->store an object which was using this technique. A trip back to #kiokudb led to the discovery of a recursive dependency between two of the UUID-related roles when using Moose 0.92 and KiokuDB 0.33.

Although I was given enough information to patch my Kioku install and fix it locally until the next release officially resolves it, I opted to go with the workaround of calling generate_uuid manually without actually attaching the role to my class. I also refined the technique slightly by adding the ability to specify my own IDs at construction, giving the final version of my test module for this:

package Foo;

use MooseX::Declare;
use KiokuDB::Role::ID;
use KiokuDB::Role::UUIDs;

class Foo with (KiokuDB::Role::ID) {

has 'name' => (
  is            => 'ro',
  isa           => 'Str',
  required      => 1,
);

has 'id' => (
  is            => 'ro',
  isa           => 'Str',
  required      => 0,
);

method kiokudb_object_id {
  return $self->{id} ||= shift->KiokuDB::Role::UUIDs::generate_uuid;
}

}

1;

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.

$self->{id} ||= ... is better

Anonymous's picture

$self->{id} ||= ... is better written as

use MooseX::Declare;

class Foo with (KiokuDB::Role::ID, KiokuDB::Role::UUIDs) {
    use MooseX::Types::Moose qw(Str);

    has id => (
        isa => Str,
        is => "ro",
        lazy_build => 1,
    );

    method _build_id { $self->generate_uuid }

    method kiokudb_object_id { $self->id }
}

This does not violate the encapsulation of the object's fields, and keeps the 'id' attribute set.

Good catch.

Dave Sherohman's picture

I've been using lazy_build on one of my other classes, but didn't think to apply it here. Such are the perils of being a Moose n00b, I guess.