File Coverage

blib/lib/Teng/Schema/Declare.pm
Criterion Covered Total %
statement 96 97 98.9
branch 17 18 94.4
condition 2 3 66.6
subroutine 22 22 100.0
pod 5 5 100.0
total 142 145 97.9


line stmt bran cond sub pod time code
1             package Teng::Schema::Declare;
2 68     68   200795 use strict;
  68         160  
  68         1686  
3 68     68   319 use warnings;
  68         138  
  68         1602  
4 68     68   1294 use parent qw(Exporter);
  68         745  
  68         334  
5 68     68   3914 use Teng::Schema;
  68         138  
  68         1156  
6 68     68   20610 use Teng::Schema::Table;
  68         167  
  68         18674  
7              
8             our @EXPORT = qw(
9             schema
10             name
11             table
12             pk
13             columns
14             row_class
15             base_row_class
16             inflate
17             deflate
18             default_row_class_prefix
19             );
20             our $CURRENT_SCHEMA_CLASS;
21              
22             sub schema (&;$) {
23 5     5 1 9635 my ($code, $schema_class) = @_;
24 5         13 local $CURRENT_SCHEMA_CLASS = $schema_class;
25 5         18 $code->();
26 5         102 _current_schema();
27             }
28              
29             sub base_row_class($) {
30 1     1 1 5 my $current = _current_schema();
31 1         5 $current->{__base_row_class} = $_[0];
32             }
33              
34             sub default_row_class_prefix ($) {
35 2     2 1 11 _current_schema()->{__default_row_class_prefix} = $_[0];
36             }
37              
38             sub row_namespace ($) {
39 238     238 1 401 my $table_name = shift;
40              
41 238 100       474 my $prefix = defined(_current_schema()->{__default_row_class_prefix}) ? _current_schema()->{__default_row_class_prefix} : do {
42 236         1177 (my $caller = caller(1)) =~ s/::Schema$//;
43 236         689 join '::', $caller, 'Row';
44             };
45 238         682 join '::', $prefix, Teng::Schema::camelize($table_name);
46             }
47              
48             sub _current_schema {
49 487     487   783 my $class = __PACKAGE__;
50 487         682 my $schema_class;
51              
52 487 100       1001 if ( $CURRENT_SCHEMA_CLASS ) {
53 3         6 $schema_class = $CURRENT_SCHEMA_CLASS;
54             } else {
55 484         691 my $i = 1;
56 484         1404 while ( $schema_class = caller($i++) ) {
57 723 100       3426 if ( ! $schema_class->isa( $class ) ) {
58 484         951 last;
59             }
60             }
61             }
62              
63 487 50       1105 if (! $schema_class) {
64 0         0 Carp::confess( "PANIC: cannot find a package name that is not ISA $class" );
65             }
66              
67 68     68   459 no warnings 'once';
  68         151  
  68         2890  
68 487 100       1469 if (! $schema_class->isa( 'Teng::Schema' ) ) {
69 68     68   346 no strict 'refs';
  68         144  
  68         8924  
70 71         133 push @{ "$schema_class\::ISA" }, 'Teng::Schema';
  71         949  
71 71         501 my $schema = $schema_class->new();
72 71         597 $schema_class->set_default_instance( $schema );
73             }
74              
75 487         1288 $schema_class->instance();
76             }
77              
78             sub pk(@);
79             sub columns(@);
80             sub name ($);
81             sub row_class ($);
82             sub inflate_rule ($@);
83             sub table(&) {
84 239     239 1 36618 my $code = shift;
85 239         548 my $current = _current_schema();
86              
87             my (
88 239         472 $table_name,
89             @table_pk,
90             @table_columns,
91             @inflate,
92             @deflate,
93             $row_class,
94             );
95 68     68   387 no warnings 'redefine';
  68         141  
  68         2560  
96            
97 239         425 my $dest_class = caller();
98 68     68   351 no strict 'refs';
  68         165  
  68         1600  
99 68     68   295 no warnings 'once';
  68         142  
  68         22132  
100 239         798 local *{"$dest_class\::name"} = sub ($) {
101 239     239   758 $table_name = shift;
102 239   66     1007 $row_class ||= row_namespace($table_name);
103 239         852 };
104 239     234   608 local *{"$dest_class\::pk"} = sub (@) { @table_pk = @_ };
  239         615  
  234         1603  
105 239     238   575 local *{"$dest_class\::columns"} = sub (@) { @table_columns = @_ };
  239         586  
  238         1750  
106 239     3   551 local *{"$dest_class\::row_class"} = sub (@) { $row_class = shift };
  239         565  
  3         11  
107 239         655 local *{"$dest_class\::inflate"} = sub ($&) {
108 13     13   74 my ($rule, $code) = @_;
109 13 100       37 if (ref $rule ne 'Regexp') {
110 9         113 $rule = qr/^\Q$rule\E$/;
111             }
112 13         52 push @inflate, ($rule, $code);
113 239         723 };
114 239         560 local *{"$dest_class\::deflate"} = sub ($&) {
115 13     13   76 my ($rule, $code) = @_;
116 13 100       40 if (ref $rule ne 'Regexp') {
117 9         76 $rule = qr/^\Q$rule\E$/;
118             }
119 13         40 push @deflate, ($rule, $code);
120 239         670 };
121              
122 239         734 $code->();
123              
124 239         417 my @col_names;
125             my %sql_types;
126 239         663 while ( @table_columns ) {
127 709         1113 my $col_name = shift @table_columns;
128 709 100       1633 if (ref $col_name) {
129 165         283 my $sql_type = $col_name->{type};
130 165         265 $col_name = $col_name->{name};
131 165         372 $sql_types{$col_name} = $sql_type;
132             }
133 709         1692 push @col_names, $col_name;
134             }
135              
136             $current->add_table(
137             Teng::Schema::Table->new(
138             columns => \@col_names,
139             name => $table_name,
140             primary_keys => \@table_pk,
141             sql_types => \%sql_types,
142             inflators => \@inflate,
143             deflators => \@deflate,
144             row_class => $row_class,
145 239 100       1157 ($current->{__base_row_class} ? (base_row_class => $current->{__base_row_class}) : ()),
146             )
147             );
148             }
149              
150             1;
151              
152             __END__
153              
154             =head1 NAME
155              
156             Teng::Schema::Declare - DSL For Declaring Teng Schema
157              
158             =head1 NORMAL USE
159              
160             package MyDB::Schema;
161             use strict;
162             use warnings;
163             use Teng::Schema::Declare;
164              
165             table {
166             name "your_table_name";
167             pk "primary_key";
168             columns qw( col1 col2 col3 );
169             inflate 'col1' => sub {
170             my ($col_value) = @_;
171             return MyDB::Class->new(name => $col_value);
172             };
173             deflate 'col1' => sub {
174             my ($col_value) = @_;
175             return ref $col_value ? $col_value->name : $col_value;
176             };
177             row_class 'MyDB::Row'; # optional
178             };
179              
180             =head1 INLINE DECLARATION
181              
182             use Teng::Schema::Declare;
183             my $schema = schema {
184             table {
185             name "your_table_name";
186             columns qw( col1 col2 col3 );
187             };
188             } "MyDB::Schema";
189              
190             =head1 METHODS
191              
192             =over 4
193              
194             =item C<schema>
195              
196             schema data creation wrapper.
197              
198             =item C<table>
199              
200             set table name
201              
202             =item C<pk>
203              
204             set primary key
205              
206             =item C<columns>
207              
208             set columns
209              
210             =item C<inflate_rule>
211              
212             set inflate rule
213              
214             =item C<row_namespace>
215              
216             create Row class namespace
217              
218             =item C<base_row_class>
219              
220             Specify the default base row class with Teng::Schema::Declare.
221              
222             Default value is L<Teng::Row>.
223              
224             This option is useful when you adds features for My::DB::Row class.
225              
226             =item C<default_row_class_prefix>
227              
228             Specify the default prefix of row class.
229              
230             C<row_class> of each table definition has priority over C<default_row_class_prefix>.
231              
232             e.g.:
233              
234             use Teng::Schema::Declare;
235             my $schema = schema {
236             default_row_class_prefix 'My::Entity';
237             table {
238             name 'user';
239             column qw(name);
240             };
241             };
242             $schema->get_row_class('user'); # => My::Entity::User
243              
244             Default value is determined by the schema class.
245              
246             e.g.:
247              
248             package My::DB::Schema;
249             use Teng::Schema::Declare;
250             table {
251             name 'user';
252             column qw(name);
253             };
254              
255             __PACKAGE__->instance->get_row_class('user'); # => My::DB::Row::User
256             1;
257              
258             =back
259              
260             =cut
261