Search code examples
perlmoose

How to call all() on a Mongoose::Join object


I use mongoose to set up the following (simplified and compacted) data model:

package Model::Tag;
use Moose; 
use Mongoose::Class; with 'Mongoose::Document';
has 'value'         => (is  => 'rw', isa => 'Str', required => 1);
no Moose;
__PACKAGE__->meta->make_immutable;

package Model::Document;
use Moose; 
use Mongoose::Class; with 'Mongoose::Document';
has 'title'         => (is => 'rw', isa => 'Str', required => 1);
has_many 'tags'     => (is => 'rw', isa => 'Model::Tag');
no Moose;
__PACKAGE__->meta->make_immutable;

The important parts of my test are:

package main;
use strict; 
use warnings;
use Data::Dumper;

my $expected; my $got;

my $doc = Model::Document->new(title => 'My new document with many tags');
my $tag1 = Model::Tag->new(value => 'foo');
my $tag2 = Model::Tag->new(value => 'bar');

my $x1 = $doc->tags->add($tag1);
my $x2 = $doc->tags->add($tag2);

# print "x1 = $x1 x2 = $x2 \n";

my $document_tags = $doc->tags;
print Dumper $document_tags;

can_ok($document_tags, 'all');

my $tag_array_ref = $document_tags->all();

Now the problem:

The dumped output of $document_tags is a Mongoose::Join object:

$VAR1 = bless( {
             'delete_buffer' => {},
             'with_class' => 'Model::Tag',
             'buffer' => {
                           '58102804' => bless( {
                                                  'value' => 'foo'
                                                }, 'Model::Tag' ),
                           '58069732' => bless( {
                                                  'value' => 'bar'
                                                }, 'Model::Tag' )
                         }
           }, 'Mongoose::Join' ); 

And the documentation about Mongoose::Join lists the METHODS:

add, remove, find, find_one, first, all, hash_on, hash_array, query, collection, with_collection_name

but calling

$document_tags->all();

causes an error

Can't use an undefined value as a HASH reference at C:/Perl/site/lib/Mongoose.pm line 132.

What is the problem?

Thanks in advance for your help and ideas.


Solution

  • The error message is coming from Mongoose, not your test program directly. Line 132 of Mongoose.pm from the most recent version of Mongoose (0.23) is in the method that establishes a connection to MongoDB.

    Following that lead, I then noticed that your test code doesn't include a call to Mongoose->db(). This is needed in order to specify the database to connect to. After adding that and trying your test program, I also noticed that your document wasn't saved to MongoDB first before attempting to retrieve attributes (i.e., the tags) from it.

    Here is your test code with the changes I made to resolve the problem. The key bits start with the line # Connect to database.

    package Model::Tag;
    use Moose;
    use Mongoose::Class; with 'Mongoose::Document';
    has 'value'         => (is  => 'rw', isa => 'Str', required => 1);
    no Moose;
    __PACKAGE__->meta->make_immutable;
    
    package Model::Document;
    use Moose;
    use Mongoose::Class; with 'Mongoose::Document';
    has 'title'         => (is => 'rw', isa => 'Str', required => 1);
    has_many 'tags'     => (is => 'rw', isa => 'Model::Tag');
    no Moose;
    __PACKAGE__->meta->make_immutable;
    
    package main;
    use strict;
    use warnings;
    use Data::Dumper;
    
    my $doc = Model::Document->new(title => 'My new document with many tags');
    my $tag1 = Model::Tag->new(value => 'foo');
    my $tag2 = Model::Tag->new(value => 'bar');
    
    my $x1 = $doc->tags->add($tag1);
    my $x2 = $doc->tags->add($tag2);
    
    my $document_tags = $doc->tags;
    print Dumper $document_tags;
    
    # Connect to database
    Mongoose->db('foo');
    # and save our document first
    $doc->save();
    
    # now we can retrieve the array (note, not array ref) of tags
    my @tag_array = $document_tags->all();
    print Dumper(\@tag_array);