X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=lib%2FMoose%2FPolicy.pm;h=ebc704f6c2e1c0481d583680cf787cf436ec747c;hb=3d1dec0aeed65b0c5d61de697ee1250f22ab2a75;hp=799a5138d10b8af5b91a673fb77021ea01e351aa;hpb=8e7059d61ce3df788e3831108c1045d606020d25;p=gitmo%2FMoose-Policy.git diff --git a/lib/Moose/Policy.pm b/lib/Moose/Policy.pm index 799a513..ebc704f 100644 --- a/lib/Moose/Policy.pm +++ b/lib/Moose/Policy.pm @@ -1,150 +1,200 @@ package Moose::Policy; +use Moose 'confess', 'blessed'; -# vim:ts=4:sw=4:et:sta +our $VERSION = '0.04'; +our $AUTHORITY = 'cpan:STEVAN'; -use strict; -use warnings; +sub import { + shift; + + my $policy = shift || return; + + unless (Class::MOP::is_class_loaded($policy)) { + # otherwise require it ... + eval { Class::MOP::load_class($policy) }; + confess "Could not load policy module '$policy' because : $@" + if $@; + } + + my $package = caller(); + $package->can('meta') and + croak("'$package' already has a meta() method, this is very problematic"); + + my $metaclass = 'Moose::Meta::Class'; + $metaclass = $policy->metaclass($package) + if $policy->can('metaclass'); -our $VERSION = '0.01'; + my %options; -use Moose (); -use Carp 'confess'; -use Scalar::Util 'blessed'; + # build options out of policy's constants + $policy->can($_) and $options{"$_"} = $policy->$_($package) + for (qw( + attribute_metaclass + instance_metaclass + method_metaclass + )); + + # create a meta object so we can install &meta + my $meta = $metaclass->initialize($package => %options); + $meta->add_method('meta' => sub { + # we must re-initialize so that it works as expected in + # subclasses, since metaclass instances are singletons, this is + # not really a big deal anyway. + $metaclass->initialize((blessed($_[0]) || $_[0]) => %options) + }); +} + +1; + +__END__ + +=pod =head1 NAME -Moose::Policy - moose-mounted police +Moose::Policy - Moose-mounted police =head1 SYNOPSIS -This class allows you to specify your project-wide or company-wide Moose -meta policy in one location. - package Foo; - use Moose::Policy 'My::MooseBestPractice'; + use Moose::Policy 'Moose::Policy::FollowPBP'; use Moose; has 'bar' => (is => 'rw', default => 'Foo::bar'); has 'baz' => (is => 'ro', default => 'Foo::baz'); -=head1 USAGE + # Foo now has (get, set)_bar methods as well as get_baz - use Moose::Policy 'My::Policy'; - use Moose; - ... - no Moose; +=head1 DEPRECATION NOTICE -=over +B. -=item YOU MUST +L replaces the L module. The +other policies included in this distribution do not yet have standalone MooseX +modules, as of November, 2010. - use Moose::Policy 'My::Policy'; +=head1 DESCRIPTION -=item BEFORE +This module allows you to specify your project-wide or even company-wide +Moose meta-policy. - use Moose; +Most all of Moose's features can be customized through the use of custom +metaclasses, however fiddling with the metaclasses can be hairy. Moose::Policy +removes most of that hairiness and makes it possible to cleanly contain +a set of meta-level customizations in one easy to use module. -=back +This is still an release of this module and it should not be considered to +be complete by any means. It is very basic implemenation at this point and +will likely get more feature-full over time, as people request features. +So if you have a suggestion/need/idea, please speak up. -=head2 The Policy +=head2 What is a meta-policy? -The argument to C is a package name. This package is -require()'d and queried for the following constants: +A meta-policy is a set of custom Moose metaclasses which can be used to +implement a number of customizations and restrictions on a particular +Moose class. -=over +For instance, L enforces that all +specified Moose classes can only use single inheritance. It does this +by trapping the call to C on the metaclass and only allowing +you to assign a single superclass. -=item metaclass +The L policy changes the default behavior of +accessors to fit the recomendations found in Perl Best Practices. -Defaults to C<'Moose::Meta::Class'>. +=head1 CAVEATS -=item attribute_metaclass +=head2 Always load Moose::Policy first. -=item instance_metaclass +You B put the following line of code: -=item method_metaclass + use Moose::Policy 'My::Policy'; -=back +before this line: -These values are then used to setup your $package->meta object. + use Moose; -Your policy package could be simply a list of constants. +This is because Moose::Policy must be given the opportunity to set the +custom metaclass before Moose has set it's default metaclass. In fact, if +you try to set a Moose::Policy and there is a C method available, +not only will kittens die, but your program will too. - package My::Policy; - use constant attribute_metaclass => 'My::Moose::Meta::Attribute'; +=head2 Policies are class scoped -But the methods are told what package is using the policy, so they could -concievably give different answers. +You must repeat the policy for each class you want to use it. It is B +inherited. This may change in the future, probably it will be a Moose::Policy +itself to allow Moose policies to be inherited. - package My::FancyPolicy; +=head1 THE POLICY - sub attribute_metaclass { - my $self = shift; - my ($user_package) = @_; - return('Our::Attributes::Stricter') - if $user_package =~ m/^Private::Banking::Money/; - return('Our::Attributes'); - } +A Policy is set by passing C a package name. This +package is then queried for what metaclasses it should use. The possible +metaclass values are: -=head1 AUTHOR +=over -Stevan Little Estevan@iinteractive.comE +=item B -In response to a feature request by Eric Wilhelm and suggestions by Matt -Trout. +This defaults to C. -Documentation and some code are Eric's fault. +=item B -=head1 COPYRIGHT AND LICENSE +=item B -... +=item B -=head1 SEE ALSO +=back -L, L +For examples of what a Policy actually looks like see the examples in +C and the test suite. More docs to come on this later (probably +a cookbook or something). -=cut +=head1 METHODS -sub import { - shift; +=over 4 - my $policy = shift || return; +=item B - unless (Moose::_is_class_already_loaded($policy)) { - ($policy->require) or confess "Could not load policy module " . - "'$policy' because : $UNIVERSAL::require::ERROR"; - } +=back - my $package = caller(); - $package->can('meta') and - croak("'$package' already has a meta() method"); +=head1 FUTURE PLANS - my $metaclass = 'Moose::Meta::Class'; - $metaclass = $policy->metaclass($package) - if $policy->can('metaclass'); +As I said above, this is the first release and it is by no means feature complete. +There are a number of thoughts on the future direction of this module. Here are +some random thoughts on that, in no particular order. - my %options; +=over 4 - # build options out of policy's constants - $policy->can($_) and $options{":$_"} = $policy->$_($package) - for (qw( - attribute_metaclass - instance_metaclass - method_metaclass - )); +=item Make set of policy roles - # create a meta object so we can install &meta - my $meta = $metaclass->initialize($package => %options); - $meta->add_method('meta' => sub { - # we must re-initialize so that it works as expected in - # subclasses, since metaclass instances are singletons, this is - # not really a big deal anyway. - $metaclass->initialize((blessed($_[0]) || $_[0]) => %options) - }); -} +Roles are an excellent way to combine sets of behaviors together into one, and +custom metaclasses are actually better composed by roles then by inheritence. +The ideal situation is that this module will provide a set of roles which can be +used to compose your meta-policy with relative ease. -1; +=back -__END__ +=head1 BUGS + +All complex software has bugs lurking in it, and this module is no +exception. If you find a bug please either email me, or add the bug +to cpan-RT. +=head1 AUTHOR + +Stevan Little Estevan@iinteractive.comE + +Eric Wilhelm + +=head1 COPYRIGHT AND LICENSE + +Copyright 2006-2007 by Infinity Interactive, Inc. + +L + +This library is free software; you can redistribute it and/or modify +it under the same terms as Perl itself. + +=cut