[Dbix-class] Deferred validation via accessors

Rob Kinyon rob.kinyon at gmail.com
Sat Jul 31 01:42:01 GMT 2010


On Fri, Jul 30, 2010 at 18:19, Paul Makepeace <paulm at paulm.com> wrote:
> On Fri, Jul 30, 2010 at 13:48, Rob Kinyon <rob.kinyon at gmail.com> wrote:
>> On Fri, Jul 30, 2010 at 16:31, Paul Makepeace <paulm at paulm.com> wrote:
>>> I'm hoping to use custom accessors to do some validation of incoming
>>> data with reference to existing column data.
>>
>> [snip lots of explanation that isn't helping much]
>>
>> Why on earth are you setting stuff manually? It's obvious...
>
> (Without the condescending tone it just wouldn't get through their
> thick skull, right?)

Believe it or not, the condescending tone doesn't come naturally to me.

>> So, code _THOSE_ up and
>> have those do the right settings for foo_enabled, bar_enabled, and
>> default_view. If someone wants to set things to "illegal" values, they
>> should be able to. But, you'll be able to find those very easily with
>> grep because they're the only ones actually using foo_enabled,
>> bar_enabled, and/or default_view. All code outside the ResultSource
>> should use set_view_to() or whatever.
>
> I'd be interested to hear what you think that abstracted method would be called.

How about enable_foo() and enable_bar()?

> I'm not seeing an abstraction that simultaneously requires setting two
> booleans and a string to the name of one of them that doesn't end up
> being clunky or overly magical. On top of that, requires extra work in
> the controller presenting those vars from the form to the model.
>
> Compare,
>
>  $r->foo_enabled(..params('foo_enabled'));
>  $r->bar_enabled(..params('foo_enabled'));
>  $r->default_view(..params('default_view'));
>
> with,
>
>  $r->wtf(foo => ..params('foo_enabled'), bar =>
> ..params('foo_enabled'), default_view => ..params('default_view'));

You're not approaching this with an open mind. Of course, please note
that I have ABSOLUTELY NO F'ING CLUE what your actual foo and bar are.
Your original explanation was not quite crystalline in its clarity
when describing the business cases.

As for the code, I would envision it behaving something like this:

You provide a table with a header of 3 columns and two rows of data
looking something like:

<table>
  <th>
    <td>View Name</td><td>Enabled</td><td>Default</td>
  </th>
  <tr>
    <td>Foo</td><td><checkbox></td><td><radiobutton></td>
  </tr>
  <!-- Repeat for bar -->
</table>

You would also have some JS that would do the following:
    1) Link the radio buttons as if they were in a group
    2) Mark a given button as disabled if its checkbox is turned off
    3) If a radiobutton is disabled when it is the set value, then the
default goes "elsewhere"
    4) If a checkbox is unchecked and it was the only one checked,
alert that this is unacceptable and disable the submit button

Then, in your server code, you would do something like:

foreach my $name ( qw( foo bar ) ) {
    if ( $.params("checked_$name") ) {
        $row->enable_foo( is_default => $.params("default_$name") );
    }
}
$row->update; # Automatically checks for dirtiness so you don't have to.

> Not horrid, but definitely 'meh', and nothing's occurring to me at all
> what "wtf" should be called.

Now, you have an API on $row that maps how the user is thinking of the UI.

> Oh, and there's still having to override the accessors to die on any
> attempt to set a value thru' them.

NO! You do _NOT_ want to do this. You want to have a "backdoor" that
allows you to do something in a script that your application shouldn't
be allowed to do. For example, if you want to convert a new client
from their old application to yours. Their former provider may have
been an idiot and allowed them to have no views enabled for a given
row. Clearly, this is idiotic, but it is a state that needs to be
loadable.

Basically, putting those sort of overridden accessors means you don't
trust your programmers. That's not Perl - that's Java. You're support
to trust the coders and distrust the users.

> Catching the update is looking pretty good.

There are very few reasons to override update. If you find yourself
trying to do so, that's generally a good sign you're doing something
wrong. It's only after you have exhausted every other possible path
that overriding update should be considered as a good idea.

-- 
Thanks,
Rob Kinyon



More information about the DBIx-Class mailing list