[Dbix-class] has_a mutator: set_rel_single

David Kamholz davekam at pobox.com
Fri Jul 29 18:58:09 CEST 2005

There are a number of possibilities for how we want this mutator to  
behave. First of all, it's important to correctly conceptualize the  
has_a relationship (and separate it from might_have, must_have, is_a,  
or whatever else). Basically, it is the mirror image of a has_many  
relationship. The has_many direction is easier to cnceptualize -- you  
have an accessor for retrieving the list of related rows, and a  
mutator for adding a new row. The has_a direction is more subtle.  
 From the point of view of _all_ rows that participate it's a many-to- 
one relationship, but from the point of view of a single row, it's  
essentially one-to-one. However, it's a peculiar kind of one-to-one.

For example, many species may belong to one genus. On the other hand,  
a specific species might turn out to be a member of any of the known  
genera, or even of a new one, but it doesn't make sense to say that  
it actually belongs to more than one. The currently known genera just  
represent a potential set among which the species may belong to one.  
It may be desirable to reclassify it many times in the future, but at  
any given moment it can only be considered belonging to one (leaving  
out the possibility of "unknown" or "unresolved").

I would like to propose that there are at least three distinct usage  
cases for a has_a mutator. I will use species and genus to refer to  
the columns in the respective tables, so it's clear which direction  
the relationship is going.

(1) The user would like to assign the species to a new genus. This  
involves inserting a row into the genus table, possibly with relevant  
data to fill in the rows, and storing the key in the species table.

(2) The user would like to reassign the species to a different genus.  
This involves changing the key in the species row to refer to a  
different genus row.

(3) The user would like to modify something in the genus row.

The last case is the easiest to handle -- it can be done by simply  
calling the get_rel_single() accessor, then calling the necessary  
column mutators on the returned object. The first two are trickier.  
The logical way to distinguish them is to allow a hash of column  
names and values to be passed and recognize (2) by the fact that a  
primary key was present (it could be more than one column). Any other  
columns present in the hash could either be ignored or cause an  
error. (I think it would be very confusing if they were used to  
update the genus row indicated by the primary key!) Case (1) could be  
assumed if no primary key was present. Or it could require a "create"  
or "force" attribute of some sort, and the mutator would simply give  
an error if it had no primary keys and no create/force attribute.

Does this seem like a reasonable overview of the problem domain?  

Dave (ningu)

More information about the Dbix-class mailing list