search spec components factored out of T365
[catagits/Reaction.git] / lib / Reaction / Meta / Attribute.pm
index 38035d5..b6ea1a0 100644 (file)
@@ -7,39 +7,65 @@ extends 'Moose::Meta::Attribute';
 #is => 'Bool' ? or leave it open
 has lazy_fail  =>
     (is => 'ro', reader => 'is_lazy_fail',  required => 1, default => 0);
-has lazy_build =>
-    (is => 'ro', reader => 'is_lazy_build', required => 1, default => 0);
+
+around legal_options_for_inheritance => sub {
+  return (shift->(@_), qw/valid_values/);
+};
 
 around _process_options => sub {
     my $super = shift;
     my ($class, $name, $options) = @_;
 
-    my $fail  = $options->{lazy_fail}; #will this autovivify?
-    my $build = $options->{lazy_build};
+    my $fail  = $options->{lazy_fail};
 
-    if ( $fail || $build) {
+    if ( $fail ) {
       confess("You may not use both lazy_build and lazy_fail for one attribute")
-        if $fail && $build;
-      confess("You may not supply a default value when using lazy_build or lazy_fail")
-        if exists $options->{default};
+        if $fail && $options->{lazy_build};
 
       $options->{lazy} = 1;
       $options->{required} = 1;
-
-      my $builder = ($name =~ /^_/) ? "_build${name}" : "build_${name}";
-      $options->{default} =  $fail ?
-        sub { confess "${name} must be provided before calling reader" } :
-          sub{ shift->$builder };
+      $options->{default} = sub { confess "${name} must be provided before calling reader" };
     }
 
     #we are using this everywhere so might as well move it here.
     $options->{predicate} ||= ($name =~ /^_/) ? "_has${name}" : "has_${name}"
       if !$options->{required} || $options->{lazy};
 
-
     $super->($class, $name, $options);
 };
 
+foreach my $type (qw(clearer predicate)) {
+
+  my $value_meth = do {
+    if ($type eq 'clearer') {
+      'clear_value'
+    } elsif ($type eq 'predicate') {
+      'has_value'
+    } else {
+      confess "NOTREACHED";
+    }
+  };
+
+  __PACKAGE__->meta->add_method("get_${type}_method" => sub {
+    my $self = shift;
+    my $info = $self->$type;
+    return $info unless ref $info;
+    my ($name) = %$info;
+    return $name;
+  });
+
+  __PACKAGE__->meta->add_method("get_${type}_method_ref" => sub {
+    my $self = shift;
+    if ((my $name = $self->${\"get_${type}_method"}) && $self->associated_class) {
+        return $self->associated_class->get_method($name);
+    } else {
+        return sub { $self->$value_meth(@_); }
+    }
+  });
+}
+
+__PACKAGE__->meta->make_immutable(inline_constructor => 0);
+
 1;
 
 __END__;
@@ -52,14 +78,6 @@ Reaction::Meta::Attribute
 
     has description => (is => 'rw', isa => 'Str', lazy_fail => 1);
 
-    # OR
-    has description => (is => 'rw', isa => 'Str', lazy_build => 1);
-    sub build_description{ "My Description" }
-
-    # OR
-    has _description => (is => 'rw', isa => 'Str', lazy_build => 1);
-    sub _build_description{ "My Description" }
-
 =head1 Method-naming conventions
 
 Reaction::Meta::Attribute will never override the values you set for method names,
@@ -71,10 +89,10 @@ either "_has" or "_build". Otherwise the method names will be in the form of the
 attribute names preceeded by "has_" or "build_". e.g.
 
    #auto generates "_has_description" and expects "_build_description"
-   has _description => (is => 'rw', isa => 'Str', lazy_build => 1);
+   has _description => (is => 'rw', isa => 'Str', lazy_fail => 1);
 
    #auto generates "has_description" and expects "build_description"
-   has description => (is => 'rw', isa => 'Str', lazy_build => 1);
+   has description => (is => 'rw', isa => 'Str', lazy_fail => 1);
 
 =head2 Predicate generation
 
@@ -83,12 +101,7 @@ generated for them if one is not already specified.
 
 =head2 lazy_fail
 
-=head2 lazy_build
-
-lazy_build will lazily build to the return value of a user-supplied builder sub
- The builder sub will recieve C<$self> as the first argument.
-
-lazy_fail will simply fail if it is called without first having set the value.
+lazy_fail will fail if it is called without first having set the value.
 
 =head1 AUTHORS