draft work on new C::M::DBIC::Schema, untested, and still needs some compat work
[catagits/Catalyst-Model-DBIC-Schema.git] / lib / Catalyst / Model / DBIC / Schema.pm
CommitLineData
ad91060a 1package Catalyst::Model::DBIC::Schema;
2
3use strict;
3aedaa5a 4use base qw/Catalyst::Model/;
ad91060a 5use NEXT;
6use UNIVERSAL::require;
7use Carp;
bfcd6e3d 8use Data::Dumper;
7db6da78 9require DBIx::Class;
ad91060a 10
3aedaa5a 11our $VERSION = '0.17_01';
ad91060a 12
13=head1 NAME
14
15Catalyst::Model::DBIC::Schema - DBIx::Class::Schema Model Class
16
17=head1 SYNOPSIS
18
aabc1d75 19Manual creation of a DBIx::Class::Schema and a Catalyst::Model::DBIC::Schema:
20
21=over
22
23=item 1.
24
25Create the DBIx:Class schema in MyApp/Schema/FilmDB.pm:
26
27 package MyApp::Schema::FilmDB;
28 use base qw/DBIx::Class::Schema/;
29
30 __PACKAGE__->load_classes(qw/Actor Role/);
31
32=item 2.
33
34Create some classes for the tables in the database, for example an
35Actor in MyApp/Schema/FilmDB/Actor.pm:
36
37 package MyApp::Schema::FilmDB::Actor;
38 use base qw/DBIx::Class/
07edc53e 39
aabc1d75 40 __PACKAGE__->load_components(qw/Core/);
41 __PACKAGE__->table('actor');
07edc53e 42
aabc1d75 43 ...
44
45and a Role in MyApp/Schema/Role.pm:
46
47 package MyApp::Schema::FilmDB::Role;
48 use base qw/DBIx::Class/
07edc53e 49
aabc1d75 50 __PACKAGE__->load_components(qw/Core/);
4a3e80e9 51 __PACKAGE__->table('role');
07edc53e 52
aabc1d75 53 ...
54
55Notice that the schema is in MyApp::Schema, not in MyApp::Model. This way it's
56usable as a standalone module and you can test/run it without Catalyst.
57
58=item 3.
59
60To expose it to Catalyst as a model, you should create a DBIC Model in
61MyApp/Model/FilmDB.pm:
62
63 package MyApp::Model::FilmDB;
64 use base qw/Catalyst::Model::DBIC::Schema/;
07edc53e 65
aabc1d75 66 __PACKAGE__->config(
67 schema_class => 'MyApp::Schema::FilmDB',
68 connect_info => [
69 "DBI:...",
70 "username",
71 "password",
72 {AutoCommit => 1}
73 ]
74 );
75
76See below for a full list of the possible config parameters.
77
78=back
79
80Now you have a working Model, accessing your separate DBIC Schema. Which can
81be used/accessed in the normal Catalyst manner, via $c->model():
82
83 my $actor = $c->model('FilmDB::Actor')->find(1);
84
85You can also use it to set up DBIC authentication with
86Authentication::Store::DBIC in MyApp.pm:
87
88 package MyApp;
07edc53e 89
aabc1d75 90 use Catalyst qw/... Authentication::Store::DBIC/;
07edc53e 91
aabc1d75 92 ...
07edc53e 93
aabc1d75 94 __PACKAGE__->config->{authentication}{dbic} = {
95 user_class => 'FilmDB::Actor',
96 user_field => 'name',
97 password_field => 'password'
98 }
99
100C<< $c->model() >> returns a L<DBIx::Class::ResultSet> for the source name
101parameter passed. To find out more about which methods can be called on a
102ResultSet, or how to add your own methods to it, please see the ResultSet
103documentation in the L<DBIx::Class> distribution.
104
105Some examples are given below:
106
3aedaa5a 107 # You can access schema-level methods directly from the top-level model:
07edc53e 108 $c->model('FilmDB')->source(...);
109 $c->model('FilmDB')->resultset(...);
110 $c->model('FilmDB')->class(...);
3aedaa5a 111 $c->model('FilmDB')->any_other_schema_method(...);
c12b7310 112
07edc53e 113 # For resultsets, there's an even quicker shortcut:
114 $c->model('FilmDB::Actor')
115 # is the same as $c->model('FilmDB')->resultset('Actor')
ad91060a 116
ad91060a 117=head1 DESCRIPTION
118
7b39f3f0 119This is a Catalyst Model for L<DBIx::Class::Schema>-based Models. See
ef91bcf9 120the documentation for L<Catalyst::Helper::Model::DBIC::Schema> for
121information on generating these Models via Helper scripts.
ad91060a 122
123=head1 CONFIG PARAMETERS
124
125=over 4
126
127=item schema_class
128
129This is the classname of your L<DBIx::Class::Schema> Schema. It needs
aabc1d75 130to be findable in C<@INC>, but it does not need to be inside the
131C<Catalyst::Model::> namespace. This parameter is required.
ad91060a 132
133=item connect_info
134
135This is an arrayref of connection parameters, which are specific to your
7db6da78 136C<storage_type> (see your storage type documentation for more details).
ad91060a 137
0f2fd2c0 138This is not required if C<schema_class> already has connection information
d89e6c8a 139defined inside itself (which isn't highly recommended, but can be done)
0f2fd2c0 140
7db6da78 141For L<DBIx::Class::Storage::DBI>, which is the only supported
142C<storage_type> in L<DBIx::Class> at the time of this writing, the
143parameters are your dsn, username, password, and connect options hashref.
144
3aedaa5a 145See L<DBIx::Class::Storage::DBI/connect_info> for more details.
7db6da78 146
147Examples:
148
07edc53e 149 connect_info => [ 'dbi:Pg:dbname=mypgdb', 'postgres', '' ],
150
151 connect_info => [
152 'dbi:SQLite:dbname=foo.db',
153 {
154 on_connect_do => [
155 'PRAGMA synchronous = OFF',
156 ],
157 }
158 ],
159
160 connect_info => [
161 'dbi:Pg:dbname=mypgdb',
162 'postgres',
163 '',
164 { AutoCommit => 0 },
165 {
166 on_connect_do => [
167 'some SQL statement',
168 'another SQL statement',
169 ],
170 }
171 ],
7db6da78 172
ad91060a 173=item storage_type
174
175Allows the use of a different C<storage_type> than what is set in your
176C<schema_class> (which in turn defaults to C<::DBI> if not set in current
3aedaa5a 177L<DBIx::Class>).
ad91060a 178
179=back
180
181=head1 METHODS
182
183=over 4
184
185=item new
186
187Instantiates the Model based on the above-documented ->config parameters.
0f2fd2c0 188The only required parameter is C<schema_class>. C<connect_info> is
189required in the case that C<schema_class> does not already have connection
190information defined for it.
ad91060a 191
3aedaa5a 192=item COMPONENT
c12b7310 193
3aedaa5a 194Tells the Catalyst component architecture that the encapsulated schema
195object is to be returned for $c->model calls for this model name.
b8427e0b 196
ad91060a 197=back
198
199=cut
200
201sub new {
46878f2e 202 my $self = shift->NEXT::new(@_);
ad91060a 203
204 my $class = ref($self);
205 my $model_name = $class;
206 $model_name =~ s/^[\w:]+::(?:Model|M):://;
207
0f2fd2c0 208 croak "->config->{schema_class} must be defined for this model"
209 unless $self->{schema_class};
ad91060a 210
211 my $schema_class = $self->{schema_class};
212
1aeb6e1e 213 $schema_class->require
3aedaa5a 214 or croak "Cannot load schema_class '$schema_class': $@";
cd7e6e4f 215
3aedaa5a 216 my $schema_obj = $schema_class->clone;
217 $schema_obj->storage_type($self->{storage_type}) if $self->{storage_type};
218 $schema_obj->connection(@{$self->{connect_info}}) if $self->{connect_info};
7db6da78 219
3aedaa5a 220 if(!$schema_obj->storage) {
221 croak "Either ->config->{connect_info} must be defined for $class"
222 . " or $schema_class must have connect info defined on it. "
223 . "Here's what we got:\n"
224 . Dumper($self);
7db6da78 225 }
226
3aedaa5a 227 $self->{schema_obj} = $schema_obj;
7db6da78 228
ad91060a 229 no strict 'refs';
230 foreach my $moniker ($self->schema->sources) {
0b2a7108 231 my $classname = "${class}::$moniker";
3aedaa5a 232 # XXX -- Does this need to be dynamic, or can it be done w/ COMPONENT too?
7db6da78 233 *{"${classname}::ACCEPT_CONTEXT"} = sub {
ad91060a 234 shift;
c12b7310 235 shift->model($model_name)->resultset($moniker);
ad91060a 236 }
237 }
238
239 return $self;
240}
241
3aedaa5a 242sub COMPONENT { shift->{schema_obj} }
b8427e0b 243
ad91060a 244=head1 SEE ALSO
245
7b39f3f0 246General Catalyst Stuff:
247
248L<Catalyst::Manual>, L<Catalyst::Test>, L<Catalyst::Request>,
249L<Catalyst::Response>, L<Catalyst::Helper>, L<Catalyst>,
250
251Stuff related to DBIC and this Model style:
252
253L<DBIx::Class>, L<DBIx::Class::Schema>,
ef91bcf9 254L<DBIx::Class::Schema::Loader>, L<Catalyst::Helper::Model::DBIC::Schema>
ad91060a 255
256=head1 AUTHOR
257
258Brandon L Black, C<blblack@gmail.com>
259
260=head1 COPYRIGHT
261
262This program is free software, you can redistribute it and/or modify it
263under the same terms as Perl itself.
264
265=cut
266
2671;