2009-02-23 14 views
7

Mamy tabelę linków, która może obsługiwać wiele typów obiektów po jednej stronie, i nie mogę się dowiedzieć, jak dostać się z jednego z tych obiektów do tabeli linków za pomocą has_many.Jak utworzyć relację DBIx :: Class ze stałym warunkiem łączenia?

Przykład: link tabela zawiera:

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

Budowanie relacji z boku zasobów jest dość prosta:

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

ale nie byłem w stanie uzyskać odpowiednie relacja od strony:

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

by otrzymać link not_page

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

daje 'Nieprawidłowy rel cond stronę val' błąd (co nie było zaskoczeniem, że do mnie).

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

podaje błąd "Nieprawidłowy błąd warunkowy". Rzucanie odskoków nie pomogło.

DBIx::Class::Relationship::Base mówi:

Warunkiem musi być SQL::Abstract -Style reprezentacja sprzężenia między tabelami

i próbowałem różne opcje stamtąd, takich jak:

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

ale bez żadnego sukcesu.

Jeśli dodałem kolejne pole do tablicy stron, które zawsze zawiera wartość „strona” Mogłem zrobić

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

ale to prawie optymalne rozwiązanie.

Podział tabeli linków na oddzielny dla każdego typu może być możliwy, ale jest to istniejący projekt, który jest rozważany pod kątem adaptacji do DBIx :: Class i mogą istnieć inne miejsca, w których podział tabeli na wiele inne stoły są bardziej kłopotliwe, niż są warte.

+0

Chcesz "belongs_to" po drugiej stronie "has_many"? – jrockway

+0

The has_many był ważniejszy, więc postanowiłem nie dodawać więcej komplikacji do pytania niż to konieczne. Mam nadzieję, że odpowiedź Briana jest możliwa do zmodyfikowania w przypadku belongs_to. – Cebjyre

Odpowiedz

3

Należy tylko dokonać metody otoki, który wywołuje relacji z wymaganymi argumentami:

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

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

byłoby to dość łatwo przekształcić składnik DBIx :: Class jeśli masz wiele tabel, które musisz mieć ten rodzaj logiki łączenia.

+0

Świetne, dzięki. Zrób ciasteczko. – Cebjyre

+0

A jak to może być używane z search()? Próbowałem: $ c-> model ("Strona") -> szukaj (undef, {prefetch => "links"}) -> all; Ale mówi: DBIx :: Class :: ResultSet :: all(): Brak takich powiązań relacji na stronie –

1

Może być określony w zaproszeniu has_many tak:

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

Patrz: DBIx::Class Cookbook

Powiązane problemy