On 1/7/07 10:02 AM, Uwe Voelker wrote:
> Then I have a question for John (or anybody else). I would like to use
> an many to many relationship with attributes. This means my map class
> (ProductColorMap in the examples) has an additional field (which is no
> key column). How can I use this?
> 
> Or do I have to give up my many to many relationship and should use two
> seperate relations instead.

Breaking the m-to-m into a 1-to-m and a m-to-1 is the most straightforward
way to do it.

If you want to preserve some of the "flattened" convenience of m-to-m, you
can put proxy methods in the map class.  Example:

    package Product;
    ...
      relationships =>
      [
        product_colors =>
        {
          type       => 'one to many',
          class      => 'ProductColorMap',
          column_map => { id => 'product_id' },
        },
        ...
      ]


    package ProductColorMap;
    ...
      relationships =>
      [
        color =>
        {
          type       => 'many to one',
          class      => 'Color',
          column_map => { color_id => 'id' },
        },
        ...
      ]
    ...

    # Get or create Color object
    sub _color
    {
      my($self) = shift;
      return $self->color || $self->color(Color->new);
    }

    # Proxy these methods to the color object
    foreach my $color_attr (qw(name code ...))
    {
      no strict 'refs';
      *{"color_$color_attr"} = sub { shift->_color->$color_attr() };
    }

Then, in your Product class, using just a 1-to-m to ProductColorMap, you can
make it appear as if those map records actually contain the color columns:

    $p->product_colors({ desc       => 'blah', # map record attr
                         color_name => 'red',  # Color attr
                         color_code => 123, }, # Color attr
                        ...);

On the "fetching" side, you could keep a m-to-m relationship around and use
it as per this thread:

http://www.mail-archive.com/rose-db-object@lists.sourceforge.net/msg01147.ht
ml

or you can modify your 1-to-m Product -> ProductColorMap relationship and
set it to always load color records:

      relationships =>
      [
        product_colors =>
        {
          type => 'one to many',
          class => 'ProductColorMap',
          column_map => { id => 'product_id' },
          manager_args => { require_objects => [ 'color' ] },
        },
        ...
      ]

  # Now this takes only one database query
  my $color_names = map { $_->color_name } $p->product_colors;

-John



-------------------------------------------------------------------------
Take Surveys. Earn Cash. Influence the Future of IT
Join SourceForge.net's Techsay panel and you'll get the chance to share your
opinions on IT & business topics through brief surveys - and earn cash
http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
_______________________________________________
Rose-db-object mailing list
Rose-db-object@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/rose-db-object

Reply via email to