Creation of composite objects automatically

[prev] [thread] [next] [Date index for 2005/03/02]

From: Peter Speltz
Subject: Creation of composite objects automatically
Date: 22:32 on 02 Mar 2005
--- "d. Taylor Singletary" <taylor@xxxxxxxx.xxx> wrote:

> Right now, I could do this:
> 
> Vendor->has_many(crossovers=>['Vendor::Crossover'=>'VNDRID']);
> 
> and
> 
> Vendor::Crossover->has_many(contacts=>['Vendor::Contact'=>'CTCTID']);
> 
> but I want the crossover table to be automatically populated just by
> editing/adding the Vendor::Contact and Vendor records.
> 

How do you plan on getting this automatic population?  The only relationship
that automatically populates another table is the is_a .  I agree auto creation
of components related to objects along with object is important.  I've been
working on this for months off and on and finally got something i'm happy with.
I need to doc it 00up and post it soon.  

Here's approach i took:  

First we need inputs for components. So i added some stuff to AsForm so it
makes  Inputs for components based on relationships automatically. 

Then form processing.  I made a wrapper around create_from_cgi called
"untaint_and_create_all from cgi" that creates object and all related objects
from the form and relates them properly. This is triggered by how AsForm (or
rather the sub rename_elements() names the inputs. It prepends them with the
accessor name if they are 'foreign'. And its recursive so it works for your
setup which was exactly like mine. Here's my example -- Ill use it cause its
named clearly:

################################################################################
package Customer;

# must_have -- my own relationship. AsForm knows to make inputs for CstmrPrsn
# object when Customer->to_cgi is called.
Customer->must_have(
        'primary_contact' => 'CstmrPrsn' =>
        qw/name/ ,
        { _FK_ => 'owner_id', owner_table => 'customer', prsn_role => "Primary
Contact"}
);

# a modified might_have -- same but you can specify what col is FK in CstmrPrsn
# and other contraints that row must have. 
Customer->might_have_constr(
        'secondary_contact' => 'CstmrPrsn' =>
        { _FK_ => 'cstmr_id', prsn_role => "Secondary Contact"}
);

Customer->must_have(
        'billing_address' => 'BttlBks::Address' =>
        { _FK_ => 'owner_id', owner_table => 'customer', addr_type =>
"Billing"}
);


Customer->might_have_constr(
        'shipping_address' => 'BttlBks::Address' =>
        qw// ,
        { _FK_ => 'owner_id', owner_table => 'customer', addr_type =>
"Shipping"}
);


package BttlBks::CstmrPrsn;
__PACKAGE__->columns(All => qw/cstmr_id prsn_id prsn_role/);
__PACKAGE__->has_a(prsn_id => "BttlBks::Person", one_to_one => 1);  #
one_to_one
# flag tells AsForm to make inputs for this (like must_have but id stored here)


package Person;
__PACKAGE__->columns(All => qw/prsn_id name dob/);


################################################################################

Thats the database class setup. So now whether i'm making a simple Person on
the /base/person/create_new/  or a complex Customer on
/base/customer/create_new ( I use maypole)

I do it with the same code and template (recursive display_inputs template is
used):

# make form
my $cgi = $class->to_cgi; 

# put inputs to template

# process form:

my ($obj,%errors) = $class->untaint_create_all_from_cgi($params);


That's it. For the customer object i have a Address, CstmrPrsn, Prsn, and
Customer rows, all related that correspond to the accessors: billing_address,
primary_contact accessors in Customer and the prsn_id accessor in CstmrPrsn.

All from 2 lines of perl and a template.

Its really a beautiful thing to see.  I don't know why no one has done it
before except that i bet they have but it was for some company and they
couldn't release it to cpan.  I'd love some discussion on this , answer any
questions, and to post my code for review and modificatoin if anyone is still
interested.

thanks










AsForm should make inputs for related components. For a customer this should be
Customer::Contact
i solved it one way. is feasible and wrote a sub: untaint_create_all_from_cgi
that does this however. I'm gonna post it up this week. I'm trying to figure
out if it should be a plugin or what.  

Anyway its p

=====
pjs


	
		
__________________________________ 
Celebrate Yahoo!'s 10th Birthday! 
Yahoo! Netrospective: 100 Moments of the Web 
http://birthday.yahoo.com/netrospective/

Creation of composite objects automatically
Peter Speltz 22:32 on 02 Mar 2005

Generated at 00:32 on 04 Mar 2005 by mariachi v0.52