perldancermoomoops

Can I instantiate an object in Dancer to return a value to display?


I have the following code in my Dancer app module:

package Deadlands;
use Dancer ':syntax';
use Dice;

our $VERSION = '0.1';

get '/' => sub {
    my ($dieQty, $dieType);
    $dieQty = param('dieQty');
    $dieType = param('dieType');
    if (defined $dieQty && defined $dieType) {
        return Dice->new(dieType => $dieType, dieQty => $dieQty)->getStandardResult();
    }
    template 'index';
};

true;

I have a Moops class called Dice.pm that works just fine if I test it with a .pl file, but when I try to access it through the web browser, I get the following error: Can't locate object method "new" via package "Dice" (perhaps you forgot to load "Dice"?).

Can I do this with Dancer?

Here is the pertinent code from Dice.pm:

use 5.14.3;
use Moops;

class Dice 1.0 {
    has dieType => (is => 'rw', isa => Int, required => 1);
    has dieQty => (is => 'rw', isa => Int, required => 1);
    has finalResult => (is => 'rw', isa => Int, required => 0);

    method getStandardResult() {
        $self->finalResult(int(rand($self->dieType()) + 1));
        return $self->finalResult();
    }
}

Solution

  • I was going to say you forgot the package Dice in your Dice.pm, but after reading up on Moops I am confused about the namespaces.

    Let's take a look at the documentation for Moops.

    If you use Moops within a package other than main, then package names used within the declaration are "qualified" by that outer package, unless they contain "::". So for example:

    package Quux;
    use Moops;
    
    class Foo { }       # declares Quux::Foo
    
    class Xyzzy::Foo    # declares Xyzzy::Foo
       extends Foo { }  # ... extending Quux::Foo
    
    class ::Baz { }     # declares Baz
    

    If the class Dice is in Dice.pm it will actually become Dice::Dice if I read this correctly. So you would have to use Dice and create your object with Dice::Dice->new.

    In order to make the package Dice within Dice.pm using Moops, I believe you need to declare the class like this:

    class ::Dice 1.0 {
        #  ^------------- there are two colons here!
    
        has dieType => (is => 'rw', isa => Int, required => 1);
        has dieQty => (is => 'rw', isa => Int, required => 1);
        has finalResult => (is => 'rw', isa => Int, required => 0);
    
        method getStandardResult() {
            $self->finalResult(int(rand($self->dieType()) + 1));
            return $self->finalResult();
        }
    }
    

    You can then do:

    use Dice;
    Dice->new;