[html-formfu] DBIC: setting accessor for a Select element
triggers options_from_model()
Zbigniew Lukasiak
zzbbyy at gmail.com
Thu Feb 28 01:42:57 GMT 2008
On Wed, Feb 27, 2008 at 11:01 PM, Carl Franks <fireartist at gmail.com> wrote:
> On 22/02/2008, Andreas Marienborg <omega at palle.net> wrote:
> >
> > On Feb 22, 2008, at 12:08 PM, Carl Franks wrote:
> >
> > > On 21/02/2008, Steve Caldwell <info-formfu at caldwellhb.com> wrote:
> > >> I'm building a form that has a Select element that I'm mapping to a
> > >> non-column accessor on my DBIC object, as described in "non-column
> > >> accessors" in the HTML::FormFu::Model::DBIC POD, like this:
> > >>
> > >> ---
> > >> action: /foo
> > >> elements:
> > >> - type: Select
> > >> name: bar
> > >> label: Your Bar
> > >> db:
> > >> accessor: bar
> > >> options:
> > >> - [ 01, January ]
> > >> - [ 02, February ]
> > >>
> > >> When I then try and populate it from my DBIC object:
> > >>
> > >> $form->defaults_from_model( $myobj );
> > >>
> > >> HTML::FormFu::Model::DBIC::options_from_model gets called (thanks to
> > >> line 44 in HTML::FormFu::Element::_Group), which then overwrites the
> > >> options I've set from my select list with a bunch of stuff from the
> > >> database. This is obviously not what I want here.
> > >>
> > >> Anyone else come across this problem? The work-around isn't that
> > >> much
> > >> work (manually populate from and save to my object instead of using
> > >> defaults_from_model() and save_to_model()), but it would be cooler
> > >> if it
> > >> all worked correctly.
> > >
> > > I agree that this is broken.
> > > I think Select automatically calling options_from_model() is a case of
> > > *too much magic*
> > >
> > > (sidenote) - I know you've only just subscribed to the list, so a
> > > quick explanation, so that you understand my following proposal:
> > > FormFu in svn has been changed so that you set Model/DBIC options
> > > with:
> > > $field->{model_config}{DBIC}
> > > instead of:
> > > $field->{db}
> > >
> > > This will be in the next cpan release. However, setting {db} will
> > > still work, and Do The Right Thing, it'll just print a warning that
> > > it's deprecated and will be removed at some point in the future.
> > >
> > > The reason for this, is the model was implemented as a bit of a
> > > rush-job and we need to get it working properly to support multiple
> > > models - much like how Catalyst handles models.
> > > (/sidenote)
> > >
> > > I suggest we require that a new option be set to run
> > > options_from_model(), such as:
> > >
> > > ---
> > > element:
> > > type: Select
> > > name: foo
> > > model_config:
> > > DBIC:
> > > options_from_model: 1
> > >
> > > (or, in the old, deprecated, style):
> > >
> > > ---
> > > element:
> > > type: Select
> > > name: foo
> > > db:
> > > options_from_model: 1
> > >
> > > Any opinions on this?
> >
> >
> > Could the default be to run it if:
> >
> > - no options_from_model: 0 (false) exists
> > AND
> > - no options already set on the select?
>
> okay, we need to revisit this :(
>
> I've moved HTML/FormFu/Model/DBIC.pm out into a separate distribution.
> $form->model_class() has been renamed to default_model() and no longer
> defaults to 'DBIC'.
> (more on that to come in another mail!)
>
> However - there's still DBIC-specific code in Element/_Group.pm to
> handle options_from_model()
> - this is bad, and needs dealt with.
>
> I can see 2 ways to deal with this:
>
> 1) Create a new system to provide hooks that model classes can attach
> to, so the user doesn't need to do anything.
>
> 2) Use the hooks provided by the current plugin system, and require
> the user to specifically add it to the Select field.
> e.g.
> ---
> type: Select
> name: foo
> plugins: [ 'DBIC::LoadOptions' ]
> model_config:
> DBIC:
> model: Foo
>
> I'm inclined to prefer solution 2, because I foresee the following
> problems with solution 1:
> - because we currently don't require the user to load the models in
> the form config, there's no guarantee that the model will be available
> during process(), so the hooks won't get run anyway.
> - adding yet-more hooks will make the formfu internals more complex
>
> Any thoughts?
Here is my proposal:
sub post_process {
my $self = shift;
$self->next::method(@_);
my $args = $self->model_config;
# only call options_from_model if there's no options already
# and {options_from_model} isn't 0
my $option_count = scalar @{ $self->options };
my $option_flag = exists $args->{options_from_model}
? $args->{options_from_model}
: 1;
if ( $option_count == 0 && $option_flag != 0 ) {
$self->options(
[ $self->form->model( $args->{model_name}
)->options_from_model( $self, $args ) ] );
}
}
Minimal change from current. I haven't got any intuition about using
multiple models in one form - but if we allow for one default model -
then the last significant line could be:
[ $self->form->model()->options_from_model( $self, $args ) ] );
The model should know that it is a DBIC model and choose the right
part of $args passed to it. Or even you could get rid of that level
in the hash - as it does not really make sense to have both DBIC and
LDAP options for one field:
- type: Select
name: type2_id
model_config:
DBIC:
resultset: Type2
LDAP:
some_ldap_option: value
Does that make sense? I cannot imagine any situation when this would
be needed. So I would say just do:
- type: Select
name: type2_id
model_config:
model_name: DBIC
resultset: Type2
--
Zbigniew
http://perlalchemy.blogspot.com/
More information about the HTML-FormFu
mailing list