1 package SL::Helper::Object;
6 my ($class, @args) = @_;
8 my $caller = (caller)[0];
11 my $method = shift @args;
12 my $args = shift @args;
13 die "invalid method '$method' for $class" unless $class->can($method);
14 $class->$method($caller, $args);
18 my %args_string_by_key = (
21 standard => '(@_[1..$#_])',
24 my %pre_context_by_key = (
26 scalar => 'my $return =',
27 list => 'my @return =',
30 my %post_context_by_key = (
36 my %known_delegate_args = map { $_ => 1 } qw(target_method args force_context class_function);
38 my $_ident = '^[a-zA-Z0-9_]+$';
39 my $_cident = '^[a-zA-Z0-9_:]+$';
42 my ($class, $caller, $args) = @_;
44 die 'delegate needs an array ref of parameters' if 'ARRAY' ne ref $args;
45 die 'delegate needs an even number of args' if @$args % 2;
48 my $target = shift @$args;
49 my $delegate_args = shift @$args;
50 my $params = 'HASH' eq ref $delegate_args->[0] ? $delegate_args->[0] : {};
52 $known_delegate_args{$_} || die "unknown parameter '$_'" for keys %$params;
54 die "delegate: target '$target' must match /$_cident/" if $target !~ /$_cident/;
55 die "delegate: target_method '$params->{target_method}' must match /$_ident/" if $params->{target_method} && $params->{target_method} !~ /$_ident/;
57 my $method_joiner = $params->{class_function} ? '::' : '->';
59 for my $method (@$delegate_args) {
62 die "delegate: method name '$method' must match /$_ident/" if $method !~ /$_ident/;
64 my $target_method = $params->{target_method} // $method;
66 my ($pre_context, $post_context) = ('', '');
67 if (exists $params->{force_context}) {
68 $pre_context = $pre_context_by_key { $params->{force_context} };
69 $post_context = $post_context_by_key{ $params->{force_context} };
70 die "invalid context '$params->{force_context}' to force" unless defined $pre_context && defined $post_context;
73 my $target_code = ucfirst($target) eq $target ? $target : "\$_[0]->$target";
75 my $args_string = $args_string_by_key{ $params->{args} // 'standard' };
76 die "invalid args handling '$params->{args}'" unless defined $target_code;
79 sub ${caller}::$method {
80 $pre_context $target_code$method_joiner$target_method$args_string; $post_context
83 " or die "could not create ${caller}::$method: $@";
98 SL::Helper::Object - Meta Object Helper Mixin
102 use SL::Helper::Object (
104 $target => [ qw(method1 method2 method3 ...) ],
105 $target => [ { DELEGATE_OPTIONS }, qw(method1 method2 method3 ...) ],
112 Sick of writing getter, setter? No because Rose::Object::MakeMethods has you covered.
114 Sick of writing all the rest that Rose can't do? Put it here. Functionality in this
115 mixin is passed as an include parameter, but are still described as functions:
121 =item C<delegate PARAMS>
123 Creates a method that delegates to the target. If the target string starts with
124 a lower case character, the generated code will be called on an object found
125 within the calling object by calling an accessor. This way, it is possible to
126 delegate to an object:
129 backend_obj => [ qw(save) ],
135 $_[0]->backend_obj->save
138 If it starts with an upper case letter, it is assumed that it is a class name:
141 'Backend' => [ qw(save) ],
150 Possible delegate args are:
154 =item * C<target_method>
156 Optional. If not given, the generated method will dispatch to the same method
157 in the target class. If this is not possible, this can be used to overwrite it.
161 Controls how the arguments are passed.
163 If set to C<none>, the generated code will not bother passing args. This has the benefit
164 of not needing to splice the caller class out of @_, or to touch @_ at all for that matter.
166 If set to C<raw>, the generated code will pass @_ without changes. This will
167 result in the calling class or object being left in the arg, but is fine if the
168 delegator is called as a function.
170 If set to C<standard> (which is also the default), the original caller will be
171 spliced out and replaced with the new calling context.
173 =item * C<force_context>
175 Forces the given context on the delegated method. Valid arguments can be
176 C<void>, C<scalar>, C<list>. Default behaviour simply puts the call at the end
177 of the sub so that context is propagated.
179 =item * C<class_function>
181 If true, the function will be called as a class function instead of a method call.
193 Sven Schöling E<lt>s.schoeling@linet-services.deE<gt>