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 69     69   413428 use strict;
  69         213  
  69         2217  
3 69     69   395 use warnings;
  69         157  
  69         1980  
4 69     69   1355 use parent qw(Exporter);
  69         799  
  69         424  
5 69     69   5291 use Teng::Schema;
  69         199  
  69         2280  
6 69     69   29955 use Teng::Schema::Table;
  69         206  
  69         27100  
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 13462 my ($code, $schema_class) = @_;
24 5         14 local $CURRENT_SCHEMA_CLASS = $schema_class;
25 5         18 $code->();
26 5         117 _current_schema();
27             }
28              
29             sub base_row_class($) {
30 1     1 1 6 my $current = _current_schema();
31 1         9 $current->{__base_row_class} = $_[0];
32             }
33              
34             sub default_row_class_prefix ($) {
35 2     2 1 21 _current_schema()->{__default_row_class_prefix} = $_[0];
36             }
37              
38             sub row_namespace ($) {
39 242     242 1 404 my $table_name = shift;
40              
41 242 100       480 my $prefix = defined(_current_schema()->{__default_row_class_prefix}) ? _current_schema()->{__default_row_class_prefix} : do {
42 240         1557 (my $caller = caller(1)) =~ s/::Schema$//;
43 240         840 join '::', $caller, 'Row';
44             };
45 242         724 join '::', $prefix, Teng::Schema::camelize($table_name);
46             }
47              
48             sub _current_schema {
49 495     495   765 my $class = __PACKAGE__;
50 495         701 my $schema_class;
51              
52 495 100       1039 if ( $CURRENT_SCHEMA_CLASS ) {
53 3         6 $schema_class = $CURRENT_SCHEMA_CLASS;
54             } else {
55 492         684 my $i = 1;
56 492         1479 while ( $schema_class = caller($i++) ) {
57 735 100       3711 if ( ! $schema_class->isa( $class ) ) {
58 492         891 last;
59             }
60             }
61             }
62              
63 495 50       1021 if (! $schema_class) {
64 0         0 Carp::confess( "PANIC: cannot find a package name that is not ISA $class" );
65             }
66              
67 69     69   648 no warnings 'once';
  69         189  
  69         4635  
68 495 100       1449 if (! $schema_class->isa( 'Teng::Schema' ) ) {
69 69     69   717 no strict 'refs';
  69         296  
  69         14141  
70 72         137 push @{ "$schema_class\::ISA" }, 'Teng::Schema';
  72         927  
71 72         675 my $schema = $schema_class->new();
72 72         540 $schema_class->set_default_instance( $schema );
73             }
74              
75 495         1290 $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 243     243 1 50311 my $code = shift;
85 243         577 my $current = _current_schema();
86              
87             my (
88 243         648 $table_name,
89             @table_pk,
90             @table_columns,
91             @inflate,
92             @deflate,
93             $row_class,
94             );
95 69     69   570 no warnings 'redefine';
  69         212  
  69         3914  
96            
97 243         439 my $dest_class = caller();
98 69     69   454 no strict 'refs';
  69         197  
  69         2608  
99 69     69   437 no warnings 'once';
  69         1129  
  69         34677  
100 243         878 local *{"$dest_class\::name"} = sub ($) {
101 243     243   867 $table_name = shift;
102 243   66     995 $row_class ||= row_namespace($table_name);
103 243         856 };
104 243     238   700 local *{"$dest_class\::pk"} = sub (@) { @table_pk = @_ };
  243         688  
  238         1298  
105 243     242   671 local *{"$dest_class\::columns"} = sub (@) { @table_columns = @_ };
  243         629  
  242         1698  
106 243     3   658 local *{"$dest_class\::row_class"} = sub (@) { $row_class = shift };
  243         654  
  3         12  
107 243         642 local *{"$dest_class\::inflate"} = sub ($&) {
108 17     17   131 my ($rule, $code) = @_;
109 17 100       40 if (ref $rule ne 'Regexp') {
110 13         272 $rule = qr/^\Q$rule\E$/;
111             }
112 17         83 push @inflate, ($rule, $code);
113 243         737 };
114 243         638 local *{"$dest_class\::deflate"} = sub ($&) {
115 17     17   137 my ($rule, $code) = @_;
116 17 100       39 if (ref $rule ne 'Regexp') {
117 13         153 $rule = qr/^\Q$rule\E$/;
118             }
119 17         65 push @deflate, ($rule, $code);
120 243         654 };
121              
122 243         812 $code->();
123              
124 243         433 my @col_names;
125             my %sql_types;
126 243         730 while ( @table_columns ) {
127 725         1165 my $col_name = shift @table_columns;
128 725 100       1534 if (ref $col_name) {
129 168         276 my $sql_type = $col_name->{type};
130 168         274 $col_name = $col_name->{name};
131 168         441 $sql_types{$col_name} = $sql_type;
132             }
133 725         1650 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 243 100       1458 ($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