Parameterized roles are nifty (and I've probably used them more than is
good for my health), but in this scenario a more elegant approach (IMHO)
would be to create a trait to be applied to the method metaclass that will
do the validation you need, and syntactic sugar (see Moose::Exporter) to
handle the work of it.  Ideally you'd end up with something like:

    use Moose;
    use MooseX::MethodValidation;

    validated_method foo => sub { ... };

validated_method() being the sugar that will take the class metaclass,
method name, and method body; then create/apply the method using the
trait'ed method metaclass.  You may need to do a little experimenting to
see what works best here vis-a-vis how much to do in the sugar and how much
to do in the trait.

This approach has the advantage that you can easily create validated
methods in the same manner as method modifiers (around, before, etc), and
you can also easily determine which methods are validated by checking their
metaclasses to see if they do the validation trait.  It also tends to make
it pretty obvious about what's going on (not how, but what) with a minimum
of fuss.

                                 -Chris

On Sun, Jan 8, 2012 at 11:57 PM, <makk...@gmail.com> wrote:

> I'd look to moving this logic into a parameterised role, with the
> parameters being the methods you are looking at validating. Have a look at
> MooseX::Role::Parameterized for details on how to do this.
>
> Take care,
> Mark.
>
> On 9 Jan 2012, at 05:14, Bill Moseley <mose...@hank.org> wrote:
>
> > I have have a number of classes that include methods that need input
> > validation.  I use a validation class for each method which means
> > validation is called the same way every time its used.  That is, I have a
> > common pattern I'm using on a number of methods and wondering if anyone
> can
> > suggest a more clever approach so I don't end up repeating similar code.
> >
> > A code example might make it clearer:
> >
> > package MyModel::User;
> > use Moose;
> > extends 'MyModel::Base';
> >
> >
> > # This method is called by the consumer to create a new user,
> > # and the $user_data passed here is assumed to have been validated.
> >
> > sub new_user {
> >    my ( $self, $user_data ) = @_;
> >
> >    return $self->ORM_layer( 'User' )->create( $user_data );
> > }
> >
> >
> > # Here's the code that gets repeated for every method that requires
> > validation.
> >
> > around new_user => sub {
> >    my ( $orig, $self, $args ) = @_;
> >
> >    # Fetch validation instance for
> >    my $validation_class = $self->validation_class_for_method( 'new_user'
> );
> >    my $validation_instance = $validation_class->new( $args );
> >
> >    # Throw exception object with validation failures unless data passes
> > validation.
> >    $validation_instance->thow_exception unless
> > $validation_instance->validates_ok;
> >
> >    return;
> > };
> >
> >
> > So, I'm looking for a suggestion how to avoid the explicit wrapper.  One
> > option I was considering was something Catalyst-like with subroutine
> > attributes:
> >
> > sub new_user : Validate {
> >    ...
> > }
> >
> > Then all methods with the "Validate" attribute would automatically get
> > wrapped, although I'm not clear if that's the best approach or even its
> > implementation.
> >
> > Thanks,
> >
> >
> >
> >
> >
> > --
> > Bill Moseley
> > mose...@hank.org
>



-- 
Chris Weyl
Ex astris scientia

Reply via email to