I found it rather difficult to find information about how to assemble a DBIx::Class
schema structure using Moose
. How to do that correctly (essentially working) and in modern Perl (good style, fast, without warnings)?
These are my goals:
Moose::Manual::BestPractices
, especially:
namespace::autoclean
and__PACKAGE__->meta->make_immutable
.Result
and ResultSet
sub BUILDARGS { $_[2] }
explained by don't ask)MooseX::NonMoose
(if necessary) or __PACKAGE__->load_components
, into common base class as suggested by DBIx::Class::Manual::Cookbook
These are the problems I ran into:
__PACKAGE__->meta->make_immutable
I got warnings like Not inlining 'new' for MyApp::Schema::Result::MyTable since it is not inheriting the default Moose::Object::new
__PACKAGE__->load_components
to the Result
base class my datetime
columns didn't get inflatedThe solutions to the problems that arose:
make_immutable
conflicts with a non-Moose
new
constructor: this is automatically handled by use MooseX::NonMoose
; in contrast to its documentation no further arguments or options are necessary; beware that DBIx::Class::Schema
has no new
method and therefore, MyApp::Schema
does not need this helperInflateColumn::DateTime
not inflating when loaded in base class: This was triggered by the order of components given to load_components()
; there is no hint in the documentation that order should matter and I've filed a bug report about this; reordering helpedWith the solutions above included my example DBIx::Class schema with Moose looks like this:
Schema class:
package MyApp::Schema;
use Moose; # we want Moose
use MooseX::MarkAsMethods autoclean => 1; # this helps removing unused symbols like Moose keywords
# do NOT 'use MooseX::NonMoose' here because Schema class has no 'new' method
extends 'DBIx::Class::Schema'; # the Moose way of inheritance
# load all table modules automatically
__PACKAGE__->load_namespaces(
# ResultSet class for tables without custom ResultSet class
# (would be DBIx::Class::ResultSet otherwise)
default_resultset_class => '+MyApp::Schema::ResultSet',
);
# tell Moose this class is finished: some Moose stuff is removed and things go faster
__PACKAGE__->meta->make_immutable;
1;
Common Result
base class:
# a base class for all table class of this app
package MyApp::Schema::Result;
use Moose;
use MooseX::MarkAsMethods autoclean => 1;
use MooseX::NonMoose; # this is important for correctly handling DBIx::Class' new
extends 'DBIx::Class::Core';
# this is the right place to implement generic stuff
# DBIx::Class::Cookbook recommends loading components in a central place
__PACKAGE__->load_components(qw/
InflateColumn::DateTime
...
/);
__PACKAGE__->meta->make_immutable;
1;
Common ResultSet
base class:
package MyApp::Schema::ResultSet;
use Moose;
use MooseX::MarkAsMethods autoclean => 1;
use MooseX::NonMoose;
extends 'DBIx::Class::ResultSet';
__PACKAGE__->meta->make_immutable;
1;
Example ResultSet
class for table my_table
:
package MyApp::Schema::ResultSet::MyTable;
use Moose;
use MooseX::MarkAsMethods autoclean => 1;
extends 'MyApp::Schema::ResultSet';
sub oldest {
my $self = shift;
$self->search({}, {order_by => {-ASC => 'date'}})->first;
}
__PACKAGE__->meta->make_immutable;
1;
Example Result
class for table my_table
:
package MyApp::Schema::Result::MyTable;
use Moose;
use MooseX::MarkAsMethods autoclean => 1;
extends 'MyApp::Schema::Result';
__PACKAGE__->table("my_table");
__PACKAGE__->add_columns(
id => {data_type => "integer", is_auto_increment => 1},
date => {data_type => "date"},
);
__PACKAGE__->set_primary_key("id");
__PACKAGE__->meta->make_immutable;
1;
What's wrong with using use_moose
in DBIx::Class::Schema::Loader? (e.g. dbicdump -o use_moose=1 MyApp::Schema <dsn> <user> <pass>
This is what use_moose=1
in DBIx::Class::Schema::Loader
0.07039 generates for the schema:
use utf8;
package MyApp::Schema;
# Created by DBIx::Class::Schema::Loader
# DO NOT MODIFY THE FIRST PART OF THIS FILE
use Moose;
use MooseX::MarkAsMethods autoclean => 1;
extends 'DBIx::Class::Schema';
__PACKAGE__->load_namespaces;
# Created by DBIx::Class::Schema::Loader v0.07039 @ 2014-03-19 22:50:18
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:7Hx1RMeFsxCqo5YaLOzPdQ
# You can replace this text with custom code or comments, and it will be preserved on regeneration
__PACKAGE__->meta->make_immutable(inline_constructor => 0);
1;
And the Result Class:
use utf8;
package MyApp::Schema::Result::Example;
# Created by DBIx::Class::Schema::Loader
# DO NOT MODIFY THE FIRST PART OF THIS FILE
use strict;
use warnings;
use Moose;
use MooseX::NonMoose;
use MooseX::MarkAsMethods autoclean => 1;
extends 'DBIx::Class::Core';
...yadda...
# Created by DBIx::Class::Schema::Loader v0.07039 @ 2014-03-19 22:50:18
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:yTmu6Rh9TAEwxqgDClBdtg
# You can replace this text with custom code or comments, and it will be preserved on regeneration
__PACKAGE__->meta->make_immutable;
1;
And here's the documentation for creating a Moosified ResultSet class
Looks like it does have some extraneous use strict
and use warnings
but no biggie.
The good part is that if anything changes, hopefully the DBIx::Class::Schema::Loader
will be updated to account for any needed changes.
Apologies if I'm missing the point.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With