DBIx :: Класс абстрактный родительский ResultSet

Я пытаюсь найти чистый объектно-ориентированный способ решения проблемы, с которой я столкнулся, с помощью DBIx :: Class. У меня есть таблица User, содержащая информацию, общую для всех пользователей. У каждого пользователя также может быть много разных классов, каждый из которых имеет свою уникальную необходимую информацию. Так, например, пользователь может быть администратором и автором. Существуют отдельные таблицы для классов администратора и автора.

Что я хочу сделать, так это создать общий базовый класс для доступа ко всем классам из пользовательского объекта. Итак, базовый класс с именем Schema :: UserClass и два подкласса с именем Schema :: UserClass :: Admin и Schema :: UserClass :: Author. Я бы хотел иметь следующие возможности:

# Get current user
my $user = MyApp->get_user();

# Get user classes
my @classes = $user->classes->all();
for my $class (@classes) {
    # Print class name
    print $class->name;
}

Аналогичная проблема представлена ​​здесь: http://dbix-class.35028.n2.nabble.com/OO-advice-do-a-subclass-do-something-else-td5614176.html. Но решение, на мой взгляд, является второстепенным, поскольку требует добавления нового отношения для каждого класса.

Я не понимаю, как можно установить связь с базовым классом, зная все подклассы. Любая помощь приветствуется.


person msikora    schedule 27.05.2012    source источник


Ответы (1)


Решение, которое я нашел, тоже не самое лучшее, но оно работает. Если у меня будет время, я могу объединить этот код в модуль CPAN, чтобы сделать его немного красивее.

package ParentSchema::Result::Class;

use strict;
use warnings;

use parent 'DBIx::Class::Core';

__PACKAGE__->add_columns(
  "user_id",
  {
    data_type => "integer",
    size => 32,
    is_foreign_key => 1,
    is_auto_increment => 0,
    is_nullable => 0,
    default_value => '',
  },
);

# stuff common to all schemas

__PACKAGE__->belongs_to(
  "user",
  "Schema::Result::User",
  { 'foreign.id' => "self.user_id" },
  { is_deferrable => 1, on_delete => "CASCADE", on_update => "CASCADE" },
);

1;

package Schema::Result::Class::Author

use strict;
use warnings;

use parent 'ParentSchema::Class';

__PACKAGE__->table('class_author');

# class spesific stuff

__PACKAGE__->meta->make_immutable;

1;


package Schema::Result::User;

use strict;
use warnings;

use parent 'DBIx::Class::Core';

use Module::Pluggable::Object;
use String::CamelCase qw(decamelize);

__PACKAGE__->add_columns(
  "id",
  {
    data_type => "integer",
    size => 32,
    is_auto_increment => 1,
    is_nullable => 0,
    default_value => '',
  },
);

my $class_path = 'Schema::Result::Class';

my $mp = Module::Pluggable::Object->new(
    search_path => [ $class_path ]
);
my @class_plugins = $mp->plugins;

foreach my $class (@class_plugins) {
  (my $name = $class) =~ s/^\Q${class_path}\E//;
  __PACKAGE__->might_have(
    decamelize($name),
    $class,
    { "foreign.user_id" => "self.id" },
    { cascade_copy => 0, cascade_delete => 0 },
  );
}

__PACKAGE__->meta->make_immutable;

1;
person msikora    schedule 30.05.2012