MooseX::DataModel - Create object models from datastructures
package MyModel { use MooseX::DataModel; version => (isa => 'Int'); description => (isa => 'Str', required => 1); sub do_something { my $self = shift; if(shift->version == 3) ... } # Moose is imported for your convenience has foo => (...); } my $obj = MyModel->MooseX::DataModel::new_from_json('{"version":3,"description":"a json document"}'); # $obj is just a plain old Moose object print $obj->version; my $obj = MyModel->new({ version => 6, description => 'A description' }); $obj->do_something;
Working with "plain datastructures" (nested hashrefs, arrayrefs and scalars) that come from other systems can be a pain.
Normally those datastructures are not arbitrary: they have some structure to them: most of them come to express "object like" things. MooseX::DataModel tries to make converting these datastructures into objects in an easy, declarative fashion.
Lots of times
MooseX::DataModel also helps you validate the datastructures. If you get an object back, it conforms to your object model. So if you declare a required key, and the passed datastructure doesn't contain it: you will get an exception. If the type of the key passed is different from the one declared: you get an exception. The advantage over using a JSON validator, is that after validation you still have your original datastructure. With MooseX::DataModel you get full-blown objects, to which you can attach logic.
Just use MooseX::DataModel in a class. It will import three keywords key, array, object. With these keywords we can specify attributes in our class
key
array
object
Declares an attribute named "attribute" that is of type $type. $type can be a string with a Moose type constraint (Str, Int), or any user defined subtype (MyPositiveInt). Also it can be the name of a class. If it's a class, MooseX::DataModel will coerce a HashRef to the specified class (using the HashRef as the objects' constructor parameters).
package VersionObject { use MooseX::DataModel; key major => (isa => 'Int'); key minor => (isa => 'Int'); } package MyObject { use MooseX::DataModel; key version => (isa => 'VersionObject'); } my $o = MyObject->MooseX::DataModel::new_from_json('{"version":{"major":3,"minor":5}}'); # $o->version->isa('VersionObject') == true print $o->version->major; # prints 3 print $o->version->minor; # prints 5
required => 1: declare that this attribute is obliged to be set in the passed datastructure
package MyObject { use MooseX::DataModel; key version => (isa => 'Int', required => 1); } my $o = MyObject->MooseX::DataModel::new_from_json('{"document_version":3}'); # exception, since "version" doesn't exist my $o = MyObject->MooseX::DataModel::new_from_json('{"version":3}'); print $o->version; # prints 3
location => $location: $location is a string that specifies in what key of the datastructure to find the attributes' value:
package MyObject { use MooseX::DataModel; key Version => (isa => 'Int', location => 'document_version'); } my $o = MyObject->MooseX::DataModel::new_from_json('{"document_version":3}'); print $o->Version; # prints 3
Declares an attribute that holds an array whose elements are of a certain type.
$type, required and location work as in "key"
package MyObject { use MooseX::DataModel; key name => (isa => 'Str', required => 1); array likes => (isa => 'Str', required => 1, location => 'his_tastes'); } my $o = MyObject->MooseX::DataModel::new_from_json('{"name":"pplu":"his_tastes":["cars","ice cream"]}"); print $o->likes->[0]; # prints 'cars'
Declares an attribute that holds an hash ("JS object") whose elements are of a certain type. This is useful when in the datastructure you have a hash with arbitrary keys (for known keys you would describe an object with the "key" keyword.
package MyObject { use MooseX::DataModel; key name => (isa => 'Str', required => 1); object likes => (isa => 'Int', required => 1, location => 'his_tastes'); } my $o = MyObject->MooseX::DataModel::new_from_json('{"name":"pplu":"his_tastes":{"cars":9,"ice cream":6}}"); print $o->likes->{ cars }; # prints 9
Your class gets the default Moose constructor. You can pass it a hashref with the datastructure
my $o = MyObject->new({ name => 'pplu', his_tastes => { cars => 9, 'ice cream' => 6 }});
There is a convenience constructor for parsing a JSON (so you don't have to do it from the outside)
my $o = MyObject->MooseX::DataModel::from_json("JSON STRING");
All this can be done with plain Moose, using subtypes, coercions and declaring the appropiate attributes (that's what really happens on the inside, although it's not guaranteed to stay that way forever). MooseX::DataModel just wants to help you write less code :)
The source code is located here: https://github.com/pplu/moosex-datamodel
Please report bugs to:
Copyright (c) 2015 by CAPSiDE This code is distributed under the Apache 2 License. The full text of the license can be found in the LICENSE file included with this module.
To install MooseX::DataModel, copy and paste the appropriate command in to your terminal.
cpanm
cpanm MooseX::DataModel
CPAN shell
perl -MCPAN -e shell install MooseX::DataModel
For more information on module installation, please visit the detailed CPAN module installation guide.