Re: Thoughts on a CDBI::AsForm::_to_new()
[prev]
[thread]
[next]
[Date index for 2004/10/25]
--0-1540779504-1098736641=:5251
Content-Type: text/plain; charset=us-ascii
Content-Id:
Content-Disposition: inline
--- Andreas Fromm <Andreas.Fromm@xxxxxx.xxxxxxxxxxxx.xx> wrote:
> -----BEGIN PGP SIGNED MESSAGE-----
> Hash: SHA1
>
> Ithink what Peter is trying to do, is what I'm also trying to do. If you
> have the following structure:
>
> table person:
> ~ id serial
> ~ name text
> ~ adress integer references addresses
> ~ phone integer references phones
>
> table addresses
> ~ id serial
> ~ street text
> ~ number text
> ~ city text
> ~ zip text
>
> tabel phones
> ~ id serial
> ~ area text
> ~ number text
>
> - -----------
> MyClass::Person
>
> __PACKAGE__->set-up-everything
> __PACKAGE__->has_a ( adress => MyClass::Addresses )
> __PACKAGE__->has_a ( phone => MyClass::Phones )
>
> - -----------
> CDBI::AsForm will make a form for person with select-boxes for address
> and phone, and what Perter (and I) would like to have is a form
> containing input-boxes for the fields from person, addresses and phones.
> Peter maybe asked for some extramagic of inserting default values for
> the non-referencing fields of person (didn't understand that part
> either). This is the reason why I don't use AsForm.
>
> I have been playing around with something like this a bit, but didn't
> found the time to finish it up. It would be nice to include something
> like this in AsFrom. My idea was to prefix the field names with the
> table name the fields belong to, such as the field 'name' would become
> 'person.name', 'street' => 'address.street' and so on. Maybe
> CDBI::FromCGI could be tweeked to process that kind of requests
> properly, but I never looked at FromCGI in more detail then the description.
>
That's exactly it. With a CDBI system with AsForm, the computer already knows
how to make these inputs. All it needs is for a class to tell it: "HEY, instead
of giving me a select box to choose an address, give me inputs to create a new
address (the result of address->to_cgi or something). Basically, in its rawest
form, this functionality comes just by making to_cgi call its self with the
has_a class when signaled to and put a hashref in the relevant column slot
instead of a single HTML::whatever object. I tried it but the recursive call
failed.
There are some some issues. As Andreas said, column name clashes become a
problem.
I ended up making a system with two parts that lives in my own classes--
1) "has_a_new_inputs" -- a part to generate other inputs for columns in a
class that are foreign keys , which lives in my base model class.
2)"has_a_new" -- a method to tell "has_a_new_inputs" what foreign keys I want
other inputs for, and further more what columns from that foreign class i want
inputs for. This is specified in each end user class.
Attached is the code and a full synopsis. I still haven't figured out what to
do about field name clashes so I just make sure i don't have any.
I hope this is clear enough. I bet AsForm could incorporate this
functionality. I made a feeble attempt at putting the has_a_new_inputs code
into AsForm::_to_new_inputs (new is a keyword in Template Toolkit and won't
work as a parameter). Then modifying AsForm::to_field to recognize a new_inputs
parametr. Then i could say:
# get hashref of HTML::whatever objects instead of a single one.
my $addr_inputs = Person->to_field("address_id", "new_inputs").
I'll try again as a proof of concept.
thanks
=====
pjs
__________________________________________________
Do You Yahoo!?
Tired of spam? Yahoo! Mail has the best spam protection around
http://mail.yahoo.com
--0-1540779504-1098736641=:5251
Content-Type: text/x-c++src; name=has_a_new_inputs
Content-Description: has_a_new_inputs
Content-Disposition: inline; filename=has_a_new_inputs
# expand foreign keys in a CDBI class to inputs for columns of the foreign class
# using AsForm methods.
# TODO make this more robust
sub BaseCDBI::has_a_new_inputs {
my ($self, $r) = @_;
return 0 unless $self->can("has_a_new");
my $has_a_new_cols = $self->has_a_new; # HAS_A_NEW called here
foreach my $col (keys %$has_a_new_cols)
{
my ($has_a_class, @input_cols) = @{$has_a_new_cols->{$col}};
unless ($has_a_class->can('to_field') ) {
warn "Class: $has_a_class can't to_field. Needs AsForm.";
next;
} # sanity check
my %res = map { $_ => $has_a_class->to_field($_) } @input_cols;
$result{$col} = \%res;
}
return \%result;
}
sub Person::has_a_new {
{ address_id => [ qw/Address street number city state zip/ ] },
{ phone_id => [ qw/Phone area number/]
};
Synopsis:
package Person;
Person->has_a(address_id => "Address");
Person->has_a(phone_id => "Phone");
# specify class and columns of that class you want inputs for in place of an
# input for the key column. Class spec won't be necessary in finished version
sub has_a_new {
{ address_id => [ qw/Address street number city state zip/ ] },
{ phone_id => [ qw/Phone area number/]
};
# then in some near by code
$template_args{cgi_inputs} = Person->to_cgi;
my $other_inputs = Person->has_a_new_inputs; #
$template_args{other_inputs} = $other_inputs
# then in a new_person TT template
[% FOREACH $col IN cgi_inputs.keys;
IF other_inputs.$col; # insert other inputs instead of to_cgi default
other_cols = other_inputs.$col; # stupid to lookup again
FOREACH mycol IN other_cols.keys;
"<label> $mycol </label>" other_cols.$mycol.as_XML;
END;
NEXT;
END;
"<label> $col </label>" cgi_inputs.$col.as_XML;
END;
%]
--0-1540779504-1098736641=:5251--