Myco
view release on metacpan or search on metacpan
lib/Myco/Entity/Meta.pm view on Meta::CPAN
if ( $template_filtering eq 'block') {
# No thanks... schedule trashing of this attrs metadata
push @blocked_template_attrs, $aname;
next;
}
}
# Make this template attrib a native attribute of this entity class
delete $attr->{template};
_gen_schema_field($class_schema, $aname, $attr);
push @installed_template_attrs, $attr;
}
# Axe blocked template attributes
map { delete $attributes->{$_} } @blocked_template_attrs;
## coderefs for this attribute's accessors
foreach my $getset (qw(get set)) {
my $accessor = $getset.'_'.$aname;
my $code = UNIVERSAL::can($class, $accessor);
unless ($code) {
# No locally defined getter method... fall back
# to the SUPER-ish 'get' / 'set'
my $super_getset = UNIVERSAL::can($class, $getset);
$code = do {
if ($getset eq 'get') {
sub { $super_getset->($_[0], $aname) }
} else {
sub { $super_getset->(shift, $aname, @_) }
}
};
}
# This should never happen... since Class::Tangram's get()
# ain't goin' nowhere
Myco::Exception::Meta->throw
(error => "Class $class -- unable to locate coderef for " .
"method $accessor")
unless $code;
my $md_acc_setter = 'set_'.$getset.'ter';
$attr->$md_acc_setter($code);
}
# Set up ui->attribute_options hash
my $attr_ui = $attr->get_ui;
if (my $opts = $attr_ui->get_options) {
for my $option ( keys %$opts ) {
$meta_ui_attr_opts->{$option} = []
unless exists $meta_ui_attr_opts->{$option};
push @{ $meta_ui_attr_opts->{$option} }, $aname;
}
}
# Set up default ui->widget if needed
my $values = $attr->get_values;
my $widget = $attr_ui->get_widget;
if ( defined $values and @$values
and (!defined $widget
or ! @$widget
or $widget->[0] eq 'textfield')) {
$attr_ui->set_widget( [ 'popup_menu' ]);
}
#######################################
## Enforce attrib 'readonly' nature
#######################################
if ( $attr->get_readonly ) {
no strict 'refs';
# install set_ATTRIB() blocker
my $bad_setter = 'set_'.$aname;
*{$class.'::'.$bad_setter} = sub {
Myco::Exception::MNI->throw
(error => "unknown method/attribute $class"
. "->$bad_setter called. Attribute is read-only");
} unless UNIVERSAL::can($class, $bad_setter);
# install ATTRIB() blocker
*{$class.'::'.$aname} = sub {
Myco::Exception::MNI->throw
(error => "unknown method/attribute ${class}->$aname"
.'called');
} unless UNIVERSAL::can($class, $aname);
}
}
## create proper displayname anon sub, if we can
my $ui_dname_closure;
if (my $dname_spec = $meta_ui->get_displayname) {
# ui..displayname is set... turn it into a proper anon sub
my $ui_dname_sub = do {
my $dname_spec_type = ref $dname_spec;
if (! $dname_spec_type) {
# dname_spec is an attrib name... make sure it's valid
Myco::Exception::Meta->throw
(error => "Class $class, 'ui displayname' specified with " .
"invalid attribute name")
unless exists $attributes->{$dname_spec};
# fetch coderef to this attribute's getter method
$attributes->{$dname_spec}->get_getter;
} elsif ($dname_spec_type eq 'CODE') {
# dname_spec itself is a coderef... hopefully it's correct!
$dname_spec;
} else {
Myco::Exception::Meta->throw
(error => "Class $class, 'ui displayname' must be name of " .
"attribute or coderef");
}
};
# Okay! Now wrap it in an instance method friendly closure
$ui_dname_closure = sub {
my $referent = shift;
Myco::Exception::Meta->throw
(error => "displayname() error -- may only be called as " .
"instance method")
unless ref $referent;
# generate the displayname for $referent object
return $ui_dname_sub->($referent);
};
lib/Myco/Entity/Meta.pm view on Meta::CPAN
push @hits, $pkg;
push @hits, _can($pkg, $meth);
} else {
push @hits, _can($pkg, $meth);
}
}
}
return @hits;
}
sub _parse_SQL_string_length {
my ($attr, $opts) = @_;
if (exists $opts->{sql}) {
my ($length) = $opts->{sql} =~
/\b(?:VAR)?CHAR\(\s*(\d*)\s*\)/i;
if (defined $length) {
my $type_opt = $attr->get_type_options;
$attr->set_type_options( $type_opt = {} ) unless ref $type_opt;
$type_opt->{string_length} = $length
}
}
}
sub _gen_schema_field {
my ($class_schema, $newattr, $newmeta) = @_;
my $type = $newmeta->get_type;
my $tangram_opts = $newmeta->get_tangram_options || {};
# Generate 'sql' option if meta data type_option 'string_length' is set
if ( $type =~ /^\s*string\s*$/
and exists($newmeta->{type_options})
and defined($newmeta->{type_options}{string_length})
and ! defined($tangram_opts->{sql}) ) {
$tangram_opts->{sql} = 'VARCHAR('
.$newmeta->{type_options}{string_length}.')';
}
# Add metadata-added attribute to $schema
$class_schema->{fields}{$type}{$newattr} = $tangram_opts;
}
=head2 add_attribute
$metadata->add_attribute(
name => 'doneness',
tangram_options => {required => 1},
type => 'int',
synopsis => "How you'd like your meat cooked",
syntax_msg => "single number: 0 through 5",
values => [qw(0 1 2 3 4, 5)],
value_labels => {0 => 'rare',
1 => 'medium-rare',
2 => 'medium',
3 => 'medium-well',
4 => 'well',
5 => 'charred'},
ui => { label => "Cook until..",
widget => [ 'popup_menu' ] },
);
Adds a Myco::Entity::Meta::Attribute object containing metadata
that describes an attribute. Valid named parameters are as follows:
=over
=item * name [required]
=item * readonly
=item * syntax_msg
=item * synopsis
=item * tangram_options
=item * template
=item * type [required]
=item * type_options
=item * value_labels
=item * values
=item * ui
=back
For more detail see ATTRIBUTES section from
L<Myco::Entity::Meta::Attribute|Myco::Entity::Meta::Attribute>
Note: an attribute declared via C<add_attribute()> overrides any same-named
attribute declared directly in a C<$schema data> structure.
=cut
sub add_attribute {
my $self = shift;
my $attributes = $self->get_attributes;
$self->set_attributes($attributes = {}) unless (defined $attributes);
my $attr = eval { Myco::Entity::Meta::Attribute->new(@_); };
Myco::Exception::Meta->throw
(error => "Exception during attempt to constuct the new ".
"::Meta::Attribute metadata object for entity class " .
$self->get_name .
" - syntax error with add_attribute() parameters? Raw " .
"exception message:\n$@") if $@;
$attributes->{$attr->get_name} = $attr;
}
=head2 add_query
$metadata->add_query( %query_attributes );
Adds a Myco::Entity::Meta::Query object. For more detail see
( run in 3.204 seconds using v1.01-cache-2.11-cpan-364913b4093 )