Как сделать связь DBIx :: Class с фиксированным условием соединения? - PullRequest
7 голосов
/ 23 февраля 2009

У нас есть таблица ссылок, которая может обрабатывать несколько типов объектов на одной стороне, и я не могу понять, как добраться из одного из этих объектов в таблицу ссылок с помощью has_many.

Пример: таблица ссылок содержит:

id link_id link_table resource_id
1  1       page       3
2  1       page       5
3  2       page       3
4  1       not_page   1

Построить отношения со стороны ресурса достаточно просто:

Resource->has_many(links => 'Link', 'resource_id');

но мне не удалось получить соответствующие отношения со стороны страницы:

Page->has_many(links => 'Link', 'link_id');

получит ссылку not_page

Page->has_many(links => 'Link', {'foreign.link_id' => 'self.id', 'foreign.link_table' => 'page'});

выдает ошибку 'Invalid rel cond val page' (что меня не удивляет).

Page->has_many(links => 'Link', {'foreign.link_id' => 'self.id', 'foreign.link_table' => '"page"'});

выдает ошибку 'Invalid rel cond val "page". Отбрасывание обратной косой черты не помогло.

DBIx :: Class :: Relationship :: Base говорит:

Условием должно быть SQL :: Abstract -стандартное представление соединения между таблицами

и я пробовал различные варианты, такие как:

Page->has_many(links => 'Link', {'foreign.link_id' => 'self.id', 'foreign.link_table' => {'=', 'page'}});

но безуспешно.

Если бы я добавил другое поле в таблицу страниц, которое всегда содержит значение 'page', я мог бы сделать

Page->has_many(links => 'Link', {'foreign.link_id' => 'self.id', 'foreign.link_table' => 'self.what_table_am_i'});

но вряд ли это оптимальное решение.

Возможно разделение таблицы ссылок на отдельную таблицу для каждого типа, но это существующий проект, который рассматривается для адаптации к DBIx :: Class, и могут быть другие места, где таблица разбивается на несколько столы доставляют больше хлопот, чем стоит.

Ответы [ 2 ]

3 голосов
/ 23 февраля 2009

Вы должны просто создать метод-обертку, который вызывает отношения с необходимыми аргументами:

Page->has_many(__all_links => 'Link', 'link_id');

sub links {
    shift->__all_links({link_table => 'page'});
}

Это было бы довольно легко превратить в компонент DBIx :: Class, если у вас есть несколько таблиц, которые должны иметь такую ​​логику соединения.

1 голос
/ 20 августа 2010

Это можно указать в вызове has_many следующим образом:

Page->has_many(links => 'Link', 'link_id',
                    { where => { link_table => 'page'} });

См .: DBIx :: Класс поваренной книги

...