first part of fix for attributes and roles mess. metclass coompat bug still lurks
[catagits/Reaction.git] / lib / Reaction / InterfaceModel / Action.pm
1 package Reaction::InterfaceModel::Action;
2
3 use Reaction::Meta::InterfaceModel::Action::Class;
4 use metaclass 'Reaction::Meta::InterfaceModel::Action::Class';
5
6 use Reaction::Meta::Attribute;
7 use Reaction::Class;
8
9 use namespace::clean -except => [ qw(meta) ];
10
11 sub _debug { $ENV{REACTION_IM_ACTION_DEBUG} }
12
13 has error_message => (
14   is => 'rw',
15   isa => 'Str',
16   metaclass => 'Reaction::Meta::Attribute'
17 );
18 has target_model => (
19   is => 'ro',
20   required => 1,
21   metaclass => 'Reaction::Meta::Attribute'
22 );
23
24 has ctx => (
25   isa => 'Catalyst',
26   is => 'ro',
27   lazy_fail => 1,
28   metaclass => 'Reaction::Meta::Attribute',
29   weak_ref => 1,
30 );
31
32 sub parameter_attributes {
33   shift->meta->parameter_attributes;
34 }
35
36 sub parameter_hashref {
37   my ($self) = @_;
38   my %params;
39   foreach my $attr ($self->parameter_attributes) {
40     my $reader = $attr->get_read_method;
41     my $predicate = $attr->get_predicate_method;
42     warn "${\$attr->name} has default: ${\$attr->has_default}" if _debug();
43     next if defined($predicate) && !$self->$predicate
44          && ($attr->is_lazy_fail || !$attr->has_default);
45     $params{$attr->name} = $self->$reader;
46   }
47   return \%params;
48 }
49
50 sub can_apply {
51   my ($self) = @_;
52   foreach my $attr ($self->parameter_attributes) {
53     my $predicate = $attr->get_predicate_method;
54     if ($self->attribute_is_required($attr)) {
55       confess "No predicate for required attribute ${\$attr->name} for ${self}"
56         unless $predicate;
57       if( !$self->$predicate && ($attr->is_lazy_fail || !$attr->has_default) ) {
58         warn "${\$attr->name} is required but hasn't been set" if _debug();
59         return 0;
60       }
61     }
62     if ($attr->has_valid_values) {
63       unless ($predicate && !($self->$predicate)) {
64         my $reader = $attr->get_read_method;
65         unless( $attr->check_valid_value($self, $self->$reader) ) {
66           warn "\${\$self->$reader} isn't a valid value for ${\$attr->name}" if _debug();
67           return 0;
68         }
69       }
70     }
71   }
72   return 1;
73 };
74 sub error_for {
75   my ($self, $attr) = @_;
76   confess "No attribute passed to error_for" unless defined($attr);
77   unless (ref($attr)) {
78     my $meta = $self->meta->find_attribute_by_name($attr);
79     confess "Can't find attribute ${attr} on $self" unless $meta;
80     $attr = $meta;
81   }
82   return $self->error_for_attribute($attr);
83 };
84 sub error_for_attribute {
85   my ($self, $attr) = @_;
86   my $reader = $attr->get_read_method;
87   my $predicate = $attr->get_predicate_method;
88   if ($self->attribute_is_required($attr)) {
89     unless ($self->$predicate) {
90       return $attr->name." is required";
91     }
92   }
93   if ($self->$predicate && $attr->has_valid_values) {
94     unless ($attr->check_valid_value($self, $self->$reader)) {
95       return "Not a valid value for ".$attr->name;
96     }
97   }
98   return; # ok
99 };
100 sub attribute_is_required {
101   my ($self, $attr) = @_;
102   return $attr->is_required;
103 };
104
105 sub sync_all { }
106
107 __PACKAGE__->meta->make_immutable;
108
109
110 1;
111
112 =head1 NAME
113
114 Reaction::InterfaceModel::Action
115
116 =head1 SYNOPSIS
117
118 =head1 DESCRIPTION
119
120 =head2 target_model
121
122 =head2 ctx
123
124 =head2 parameter_attributes
125
126 =head1 SEE ALSO
127
128 L<Reaction::Meta::Attribute>
129
130 =head1 AUTHORS
131
132 See L<Reaction::Class> for authors.
133
134 =head1 LICENSE
135
136 See L<Reaction::Class> for the license.
137
138 =cut