[Dbix-class] Deferred validation via accessors

Paul Makepeace paulm at paulm.com
Fri Jul 30 20:31:53 GMT 2010


I'm hoping to use custom accessors to do some validation of incoming
data with reference to existing column data.

I have three fields: foo_enabled, bar_enabled, and default_view.
Constraint 1: one of foo_enabled or bar_enabled must be on/1 (i.e.
neither off/0)
Constraint 2: default_view can take either of 'foo' or 'bar' (not null etc)
Constraint 3: default_view can only take its value if the
corresponding {foo,bar}_enabled is set

There's a deadlock here if you can't defer checking. Say we have
foo_enabled=1, bar_enabled=0, default_view=foo then flip to
foo_enabled=0, bar_enabled=1, default_view=bar we'd have to order our
accessor calls to have both 1 (which is annoying).

One option seemed to me to have a pre-update() check rather than
having it in the accessor.

What do folks to here?

Paul, who skimmed ::Cookbook & ::ResultSource but didn't see anything jump out

PS Here's some code to see if I'm at least on the right track as far as it goes,

__PACKAGE__->add_columns(
	bar_enabled => { accessor => '_bar_enabled' },
	foo_enabled => { accessor => '_foo_enabled' },
	default_view => { accessor => '_default_view' },
);

sub default_view {
	my ($self, $value) = @_;

	if (defined $value) {
		unless ($value ~~ ['foo', 'bar']) {
			die "default_view must be one of 'foo', 'bar'";
		}
		foreach my $view qw(foo bar) {
			if ($value eq $view && !$self->"${view}_enabled") {
				die "${view}_enabled must be set before default_view can be $view";
			}
		}
		$self->_default_view($value);
	}
	return $self->_default_view;
}


sub bar_enabled {
	my ($self, $value) = @_;

	if (defined $value) {
		if (!$value) {	# switching if off
			if (!$self->_foo_enabled) {
				die "bar_enabled cannot be 0 if foo_enabled is 0";
			}
			unless ($self->_default_view ne 'bar') {
				die "bar_enabled cannot be 0 if default_view is bar";
			}
		}
		$self->_bar_enabled($value);
	}
	return $self->_bar_enabled;
}


sub foo_enabled {
	my ($self, $value) = @_;

	if (defined $value) {
		if (!$value) {	# switching if off
			if (!$self->_bar_enabled) {
				die "foo_enabled cannot be 0 if bar_enabled is 0";
			}
			if ($self->_default_view eq 'foo') {
				die "foo_enabled cannot be 0 if default_view is foo";
			}
		}
		$self->_foo_enabled($value);
	}
	return $self->_foo_enabled;
}

(If there's a cute way of avoiding that copy&paste I'm all ears, it's
been a long night :))



More information about the DBIx-Class mailing list