1package Bread::Board::Service::WithParameters; 2our $AUTHORITY = 'cpan:STEVAN'; 3# ABSTRACT: Services with parameters 4$Bread::Board::Service::WithParameters::VERSION = '0.37'; 5use Moose::Role; 6use MooseX::Params::Validate qw(validated_hash); 7 8use Bread::Board::Types; 9 10with 'Bread::Board::Service'; 11 12has 'parameters' => ( 13 traits => [ 'Hash', 'Copy' ], 14 is => 'ro', 15 isa => 'Bread::Board::Service::Parameters', 16 lazy => 1, 17 coerce => 1, 18 builder => '_build_parameters', 19 handles => { 20 'has_parameters' => 'count' 21 } 22); 23 24has '_parameter_keys_to_remove' => ( 25 is => 'rw', 26 isa => 'ArrayRef', 27 clearer => '_clear_parameter_keys_to_remove', 28 predicate => '_has_parameter_keys_to_remove', 29); 30 31before 'get' => sub { 32 my $self = shift; 33 my %params = $self->check_parameters(@_); 34 $self->_parameter_keys_to_remove( [ keys %params ] ); 35 $self->params({ %{ $self->params }, %params }); 36}; 37 38after 'get' => sub { 39 my $self = shift; 40 return unless $self->_has_parameter_keys_to_remove; 41 map { $self->_clear_param( $_ ) } @{ $self->_parameter_keys_to_remove }; 42 $self->_clear_parameter_keys_to_remove; 43}; 44 45sub _build_parameters { +{} } 46 47sub check_parameters { 48 my $self = shift; 49 return validated_hash(\@_, ( 50 %{ $self->parameters }, 51 # NOTE: 52 # cache the parameters in a per-service 53 # basis, this should be more than adequate 54 # since each service can only have one set 55 # of parameters at a time. If this does end 56 # up breaking then we can give it a better 57 # key at that point. 58 # - SL 59 (MX_PARAMS_VALIDATE_CACHE_KEY => Scalar::Util::refaddr($self)) 60 )) if $self->has_parameters; 61 return (); 62} 63 64sub has_required_parameters { 65 my $self = shift; 66 scalar grep { ! $_->{optional} } values %{ $self->parameters }; 67} 68 69sub has_parameter_defaults { 70 my $self = shift; 71 scalar grep { $_->{default} } values %{ $self->parameters }; 72} 73 74no Moose::Role; 1; 75 76__END__ 77 78=pod 79 80=encoding UTF-8 81 82=head1 NAME 83 84Bread::Board::Service::WithParameters - Services with parameters 85 86=head1 VERSION 87 88version 0.37 89 90=head1 DESCRIPTION 91 92This is a sub-role of L<Bread::Board::Service>, for parameterized 93services. These are services that will instantiate different values 94depending on parameters that are passed to the C<get> method. You can 95pass those parameters via the L<< C<service_params> attribute of 96C<Bread::Board::Dependency>|Bread::Board::Dependency/service_params 97>>, or via the L<< C<inflate> method of 98C<Bread::Board::Service::Deferred::Thunk>|Bread::Board::Service::Deferred::Thunk/inflate 99>>. 100 101=head1 ATTRIBUTES 102 103=head2 C<parameters> 104 105Read-only hashref, will be passed as-is to L<< 106C<MooseX::Params::Validate>'s 107C<validated_hash>|MooseX::Params::Validate/validated_hash >>, so you 108can use things like C<optional> and C<default> in addition to type 109constraints: 110 111 service something => ( 112 class => 'Thing', 113 parameters => { 114 type => { isa => 'Str', default => 'text' }, 115 }, 116 ); 117 118This attribute uses coercions on L<< 119C<Bread::Board::Service::Parameters>|Bread::Board::Types/Bread::Board::Service::Parameters 120>> so that you can also say: 121 122 service something => ( 123 class => 'Thing', 124 parameters => ['type'], 125 ); 126 127and it will be equivalent to: 128 129 service something => ( 130 class => 'Thing', 131 parameters => { 132 type => { optional => 0 }, 133 }, 134 ); 135 136=head1 METHODS 137 138=head2 C<has_parameters> 139 140Predicate for the L</parameters> attribute. 141 142=head2 C<has_parameter_defaults> 143 144Returns true if any of the L</parameters> have a C<default> value. 145 146=head2 C<has_required_parameters> 147 148Returns true if any of the L</parameters> does I<not> have C<optional> 149set to true. 150 151=head2 C<check_parameters> 152 153 my %parameters = $service->check_parameters(name1=>$value1,name2=>$value2); 154 my %parameters = $service->check_parameters({name1=>$value1,name2=>$value2}); 155 156If any L</parameters> are defined, this function validates its 157arguments against the parameters' definitions (using 158L<MooseX::Params::Validate>). It will die if the validation fails, or 159return the validated parameters (including default value) if it 160succeeds. 161 162=head2 C<get> 163 164I<Before> the C<get> method, arguments to C<get> are passed through 165L</check_parameters> and added to the L<< 166C<params>|Bread::Board::Service/params >> hashref. I<After> the C<get> 167method, those keys/values will be removed. In practice, this makes all 168parameters available to the actual C<get> method body. 169 170=head1 AUTHOR 171 172Stevan Little <stevan@iinteractive.com> 173 174=head1 BUGS 175 176Please report any bugs or feature requests on the bugtracker website 177https://github.com/stevan/BreadBoard/issues 178 179When submitting a bug or request, please include a test-file or a 180patch to an existing test-file that illustrates the bug or desired 181feature. 182 183=head1 COPYRIGHT AND LICENSE 184 185This software is copyright (c) 2019, 2017, 2016, 2015, 2014, 2013, 2011, 2009 by Infinity Interactive. 186 187This is free software; you can redistribute it and/or modify it under 188the same terms as the Perl 5 programming language system itself. 189 190=cut 191