How to create a DBIx :: Class relation with a fixed join condition?

We have a link table that can handle several types of objects on the one hand, and I cannot figure out how to get from one of these objects to the link table using has_many.

Example: a link table contains:

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

Building relationships on the side of the resource is quite simple:

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

but I was not able to get the appropriate relationship from the page side:

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

will get a not_page link

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

gives the error "Unacceptable error" (which is not surprising for me).

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

gives an error message "Invalid rel cond val". Throwing a backslash didn't help.

DBIx :: Class :: Relationship :: Base says:

The condition must be SQL :: Abstract - a representation of the join style between tables

and I tried various options, for example:

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

but without any success.

If I added another field to the page table, which always contains the value "page", I could do

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

but this is hardly the best solution.

Separating the link table into a separate one for each type may be possible, but this is an existing project that is being considered for adaptation to DBIx :: Class, and there may be other places where splitting the table into several other tables is more trouble than it costs.

+7
perl dbix-class
source share
2 answers

You just need to create a wrapper method that calls the required arguments:

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

It would be quite easy to turn into a DBIx :: Class component if you have several tables that should have this join logic.

+3
source share

It can be specified in the has_many call as follows:

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

See: DBIx :: Class Cookbook

+1
source share

All Articles