Как настроить схему DBIx::Class с Moose - конкретное руководство
Мне было довольно сложно найти информацию о том, как собрать DBIx::Class
структура схемы с использованием Moose
, Как это сделать правильно (по сути работает) и в современном Perl (хороший стиль, быстро, без предупреждений)?
Это мои цели:
- следуй за лося
Moose::Manual::BestPractices
, особенно:- использование
namespace::autoclean
а также - использование
__PACKAGE__->meta->make_immutable
,
- использование
- использовать общие базовые классы для
Result
а такжеResultSet
- при использовании каких-либо магических трюков есть комментарий, объясняющий их (во время исследования я нашел руководство, предлагающее
sub BUILDARGS { $_[2] }
объясни не спрашивай) - переместить общий код, например
MooseX::NonMoose
(при необходимости) или__PACKAGE__->load_components
в общий базовый класс, как это предлагаетсяDBIx::Class::Manual::Cookbook
Вот проблемы, с которыми я столкнулся:
- когда используешь
__PACKAGE__->meta->make_immutable
Я получил предупреждения какNot inlining 'new' for MyApp::Schema::Result::MyTable since it is not inheriting the default Moose::Object::new
- при переводе всех звонков на
__PACKAGE__->load_components
кResult
базовый класс мойdatetime
столбцы не раздуты
2 ответа
Решения возникших проблем:
make_immutable
конфликтует сMoose
new
конструктор: это автоматически обрабатываетсяuse MooseX::NonMoose
; в отличие от его документации никаких дополнительных аргументов или опций не требуется; остерегайтесь этогоDBIx::Class::Schema
не имеетnew
метод и, следовательно,MyApp::Schema
не нужен этот помощникInflateColumn::DateTime
не раздувается при загрузке в базовый класс: это было вызвано порядком компонентовload_components()
; в документации нет никаких намеков на то, что порядок должен иметь значение, и я подал отчет об ошибке по этому поводу; переупорядочение помогло
С приведенными выше решениями мой пример схемы DBIx::Class с Moose выглядит так:
Схема класса:
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;
общий Result
базовый класс:
# 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;
общий ResultSet
базовый класс:
package MyApp::Schema::ResultSet;
use Moose;
use MooseX::MarkAsMethods autoclean => 1;
use MooseX::NonMoose;
extends 'DBIx::Class::ResultSet';
__PACKAGE__->meta->make_immutable;
1;
пример ResultSet
класс для стола 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;
пример Result
класс для стола 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;
Что не так с использованием use_moose
в DBIx:: Class:: Schema:: Loader? (например dbicdump -o use_moose=1 MyApp::Schema <dsn> <user> <pass>
Это то, что use_moose=1
в DBIx::Class::Schema::Loader
0.07039 генерирует для схемы:
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;
И класс результатов:
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;
А вот документация по созданию класса Moosified ResultSet
Похоже, у него есть некоторые посторонние use strict
а также use warnings
но не важная персона Хорошая часть в том, что если что-то изменится, надеюсь, DBIx::Class::Schema::Loader
будет обновлен для учета любых необходимых изменений.
Извиняюсь, если я упускаю суть.