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.
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);