Как настроить схему 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 конфликтует с Moosenew конструктор: это автоматически обрабатывается 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 будет обновлен для учета любых необходимых изменений.

Извиняюсь, если я упускаю суть.

Другие вопросы по тегам