Skip to content

Instantly share code, notes, and snippets.

@jshirley
Created April 17, 2012 20:16
Show Gist options
  • Save jshirley/2408731 to your computer and use it in GitHub Desktop.
Save jshirley/2408731 to your computer and use it in GitHub Desktop.
package MyApp::Model::DataManager;
use Moose;
extends 'Data::Manager';
sub new_from_schema {
my ( $class, $schema, @classes ) = @_;
my $verifiers = $class->_default_verifiers;
my $scope_to_resultsource = {};
foreach my $name ( $schema->sources ) {
my $source = $schema->resultset($name)->new_result({});
next unless $source->can('meta');
next unless $source->meta->does_role('MyApp::TraitFor::Result::Verifier');
$verifiers->{$source->verify_scope} = $source->verifier;
$scope_to_resultsource->{ $source->verify_scope } = "Schema::$name";
}
$class->new(
verifiers => $verifiers,
scope_to_resultsource => $scope_to_resultsource
);
}
no Moose;
__PACKAGE__->meta->Make_immutable; 1;
package MyApp::Schema::Result::Person;
...
with 'MyApp::TraitFor::Result::Verifier';
# Data::Verify Code (from ::Verify role)
sub _build_verify_scope { 'person' }
sub _build_verify_profile {
my ( $self ) = @_;
return {
'profile' => {
'name' => {
'required' => 1,
'type' => 'Str',
'max_length' => '255',
'min_length' => 1
},
'email' => {
'required' => 1,
'type' => Email,
'min_length' => 1
},
},
'filters' => [ 'trim' ]
};
}
package MyApp::TraitFor::Result::Verifier;
use Moose::Role;
use Data::Verifier;
has 'verify_scope' => (
is => 'ro',
isa => 'Str',
required => 1,
lazy => 1,
builder => '_build_verify_scope',
);
has 'verifier' => (
is => 'ro',
isa => 'Data::Verifier',
builder => '_build_verifier',
lazy => 1,
handles => {
'verify' => 'verify'
}
);
has '_verify_profile' => (
is => 'ro',
isa => 'HashRef',
lazy => 1,
builder => '_build_verify_profile',
);
sub _build_verifier {
my ( $self ) = @_;
Data::Verifier->new( $self->_verify_profile );
}
# reflects from DBIC definitions
sub _build_verify_profile {
my ( $self ) = @_;
my $profile = {};
foreach my $column ( $self->columns ) {
my $info = $self->column_info( $column );
next if $info->{is_auto_increment};
next if $info->{is_foreign_key};
my %parts = ();
my $type = 'Str';
if ( $info->{extra}->{verify_properties} ) {
%parts = %{ $info->{extra}->{verify_properties} };
}
if ( $parts{type} ) {
# No op, coming from verify_properties
}
# Skip if we have a dynamic setup
elsif ( $info->{set_on_create} or
$info->{set_on_update} or
$info->{dynamic_default_on_create} or
$info->{dynamic_default_on_update}
) {
next;
}
elsif ( $info->{data_type} =~ /^text|varchar|char$/ ) {
$type = 'Str';
if ( exists $info->{size} ) {
$parts{max_length} = $info->{size};
}
$parts{min_length} = 1;
}
elsif ( $info->{data_type} =~ /^date|datetime$/ ) {
$type = 'DateTime';
my $method = "parse_$info->{data_type}";
$parts{coercion} = Data::Verifier::coercion(
from => 'Str',
via => sub {
my $fmt = $_;
my $dt;
try {
$dt = DateTime::Format::MySQL->$method($fmt);
} catch {
$dt = DateTime::Format::MySQL->parse_date($fmt);
};
$dt;
}
);
}
elsif ( $info->{data_type} =~ /^int|integer$/ ) {
$type = 'Int';
}
elsif ( $info->{data_type} =~ /^double|float|decimal$/ ) {
$type = 'Num';
}
my $required = 1;
$required = 0 if $info->{is_nullable};
$required = 0 if $info->{dynamic_default_on_create};
if ( defined $info->{default_value} ) {
$required = 0;
$parts{default} = $info->{default_value};
}
$profile->{$info->{accessor} || $column} = {
%parts,
type => $type,
required => $required,
};
}
return { filters => [ qw(trim) ], profile => $profile };
}
no Moose::Role;
1;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment