1 package Catalyst::Model::DBIC::Schema;
4 use base qw/Catalyst::Model Class::Accessor::Fast Class::Data::Accessor/;
6 use UNIVERSAL::require;
10 our $VERSION = '0.12';
12 __PACKAGE__->mk_classaccessor('composed_schema');
13 __PACKAGE__->mk_accessors('schema');
17 Catalyst::Model::DBIC::Schema - DBIx::Class::Schema Model Class
21 Manual creation of a DBIx::Class::Schema and a Catalyst::Model::DBIC::Schema:
27 Create the DBIx:Class schema in MyApp/Schema/FilmDB.pm:
29 package MyApp::Schema::FilmDB;
30 use base qw/DBIx::Class::Schema/;
32 __PACKAGE__->load_classes(qw/Actor Role/);
36 Create some classes for the tables in the database, for example an
37 Actor in MyApp/Schema/FilmDB/Actor.pm:
39 package MyApp::Schema::FilmDB::Actor;
40 use base qw/DBIx::Class/
42 __PACKAGE__->load_components(qw/Core/);
43 __PACKAGE__->table('actor');
47 and a Role in MyApp/Schema/Role.pm:
49 package MyApp::Schema::FilmDB::Role;
50 use base qw/DBIx::Class/
52 __PACKAGE__->load_components(qw/Core/);
53 __PACKAGE__->table('actor');
57 Notice that the schema is in MyApp::Schema, not in MyApp::Model. This way it's
58 usable as a standalone module and you can test/run it without Catalyst.
62 To expose it to Catalyst as a model, you should create a DBIC Model in
63 MyApp/Model/FilmDB.pm:
65 package MyApp::Model::FilmDB;
66 use base qw/Catalyst::Model::DBIC::Schema/;
69 schema_class => 'MyApp::Schema::FilmDB',
78 See below for a full list of the possible config parameters.
82 Now you have a working Model, accessing your separate DBIC Schema. Which can
83 be used/accessed in the normal Catalyst manner, via $c->model():
85 my $actor = $c->model('FilmDB::Actor')->find(1);
87 You can also use it to set up DBIC authentication with
88 Authentication::Store::DBIC in MyApp.pm:
92 use Catalyst qw/... Authentication::Store::DBIC/;
96 __PACKAGE__->config->{authentication}{dbic} = {
97 user_class => 'FilmDB::Actor',
99 password_field => 'password'
102 C<< $c->model() >> returns a L<DBIx::Class::ResultSet> for the source name
103 parameter passed. To find out more about which methods can be called on a
104 ResultSet, or how to add your own methods to it, please see the ResultSet
105 documentation in the L<DBIx::Class> distribution.
107 Some examples are given below:
109 # to access schema methods directly:
110 $c->model('FilmDB')->schema->source(...);
112 # to access the source object, resultset, and class:
113 $c->model('FilmDB')->source(...);
114 $c->model('FilmDB')->resultset(...);
115 $c->model('FilmDB')->class(...);
117 # For resultsets, there's an even quicker shortcut:
118 $c->model('FilmDB::Actor')
119 # is the same as $c->model('FilmDB')->resultset('Actor')
121 # To get the composed schema for making new connections:
122 my $newconn = $c->model('FilmDB')->composed_schema->connect(...);
124 # Or the same thing via a convenience shortcut:
125 my $newconn = $c->model('FilmDB')->connect(...);
127 # or, if your schema works on different storage drivers:
128 my $newconn = $c->model('FilmDB')->composed_schema->clone();
129 $newconn->storage_type('::LDAP');
130 $newconn->connection(...);
132 # and again, a convenience shortcut
133 my $newconn = $c->model('FilmDB')->clone();
134 $newconn->storage_type('::LDAP');
135 $newconn->connection(...);
139 This is a Catalyst Model for L<DBIx::Class::Schema>-based Models. See
140 the documentation for L<Catalyst::Helper::Model::DBIC::Schema> and
141 L<Catalyst::Helper::Model::DBIC::SchemaLoader> for information
142 on generating these Models via Helper scripts. The latter of the two
143 will also generated a L<DBIx::Class::Schema::Loader>-based Schema class
146 =head1 CONFIG PARAMETERS
152 This is the classname of your L<DBIx::Class::Schema> Schema. It needs
153 to be findable in C<@INC>, but it does not need to be inside the
154 C<Catalyst::Model::> namespace. This parameter is required.
158 This is an arrayref of connection parameters, which are specific to your
159 C<storage_type> (see your storage type documentation for more details).
161 This is not required if C<schema_class> already has connection information
162 defined in itself (which would be the case for a Schema defined by
163 L<DBIx::Class::Schema::Loader>, for instance).
165 For L<DBIx::Class::Storage::DBI>, which is the only supported
166 C<storage_type> in L<DBIx::Class> at the time of this writing, the
167 parameters are your dsn, username, password, and connect options hashref.
169 If you need to specify the L<DBIx::Class::Storage::DBI> specific parameter
170 C<on_connect_do>, or the related C<sql_maker> options C<limit_dialect>,
171 C<quote_char>, or C<name_sep>, you can place these options into a hashref
172 as the final element of the C<connect_info> arrayref. If in doubt, don't
173 specify these options. You would know it if you needed them.
177 connect_info => [ 'dbi:Pg:dbname=mypgdb', 'postgres', '' ],
180 'dbi:SQLite:dbname=foo.db',
183 'PRAGMA synchronous = OFF',
189 'dbi:Pg:dbname=mypgdb',
195 'some SQL statement',
196 'another SQL statement',
203 Allows the use of a different C<storage_type> than what is set in your
204 C<schema_class> (which in turn defaults to C<::DBI> if not set in current
205 L<DBIx::Class>). Completely optional, and probably unnecessary for most
206 people until other storage backends become available for L<DBIx::Class>.
216 Instantiates the Model based on the above-documented ->config parameters.
217 The only required parameter is C<schema_class>. C<connect_info> is
218 required in the case that C<schema_class> does not already have connection
219 information defined for it.
223 Accessor which returns the connected schema being used by the this model.
224 There are direct shortcuts on the model class itself for
225 schema->resultset, schema->source, and schema->class.
227 =item composed_schema
229 Accessor which returns the composed schema, which has no connection info,
230 which was used in constructing the C<schema> above. Useful for creating
231 new connections based on the same schema/model. There are direct shortcuts
232 from the model object for composed_schema->clone and composed_schema->connect
236 Shortcut for ->composed_schema->clone
240 Shortcut for ->composed_schema->connect
244 Shortcut for ->schema->source
248 Shortcut for ->schema->class
252 Shortcut for ->schema->resultset
256 Provides an accessor for the connected schema's storage object.
257 Used often for debugging and controlling transactions.
264 my $self = shift->NEXT::new(@_);
266 my $class = ref($self);
267 my $model_name = $class;
268 $model_name =~ s/^[\w:]+::(?:Model|M):://;
270 croak "->config->{schema_class} must be defined for this model"
271 unless $self->{schema_class};
273 my $schema_class = $self->{schema_class};
275 $schema_class->require
276 or croak "Cannot load schema class '$schema_class': $@";
278 if( !$self->{connect_info} ) {
279 if($schema_class->storage && $schema_class->storage->connect_info) {
280 $self->{connect_info} = $schema_class->storage->connect_info;
283 croak "Either ->config->{connect_info} must be defined for $class"
284 . " or $schema_class must have connect info defined on it";
288 $self->composed_schema($schema_class->compose_namespace($class));
289 $self->schema($self->composed_schema->clone);
291 $self->schema->storage_type($self->{storage_type})
292 if $self->{storage_type};
294 # XXX This is temporary, until DBIx::Class::Storage::DBI supports the
295 # same syntax and we switch our requisite to that version somewhere
296 # down the line. This syntax is already committed into DBIx::Class
297 # dev branch post-0.06.
298 # At that time, this whole block can revert back to just being:
299 # $self->schema->connection(@{$self->{connect_info}});
301 my $connect_info = [ @{$self->{connect_info}} ];
302 my ($on_connect_do, %sql_maker_opts);
303 if($DBIx::Class::VERSION < 0.069) {
305 my $last_info = $self->{connect_info}->[-1];
306 if(ref $last_info eq 'HASH') {
307 if($on_connect_do = $last_info->{on_connect_do}) {
310 for my $sql_maker_opt (qw/limit_dialect quote_char name_sep/) {
311 if(my $opt_val = $last_info->{$sql_maker_opt}) {
313 $sql_maker_opts{$sql_maker_opt} = $opt_val;
316 pop(@$connect_info) if $used;
320 $self->schema->connection(@$connect_info);
322 if($DBIx::Class::VERSION < 0.069) {
323 $self->schema->storage->on_connect_do($on_connect_do)
325 foreach my $sql_maker_opt (keys %sql_maker_opts) {
326 $self->schema->storage->sql_maker->$sql_maker_opt(
327 $sql_maker_opts{$sql_maker_opt}
332 # XXX end of compatibility block referenced above
335 foreach my $moniker ($self->schema->sources) {
336 my $classname = "${class}::$moniker";
337 *{"${classname}::ACCEPT_CONTEXT"} = sub {
339 shift->model($model_name)->resultset($moniker);
346 sub clone { shift->composed_schema->clone(@_); }
348 sub connect { shift->composed_schema->connect(@_); }
350 sub storage { shift->schema->storage(@_); }
354 General Catalyst Stuff:
356 L<Catalyst::Manual>, L<Catalyst::Test>, L<Catalyst::Request>,
357 L<Catalyst::Response>, L<Catalyst::Helper>, L<Catalyst>,
359 Stuff related to DBIC and this Model style:
361 L<DBIx::Class>, L<DBIx::Class::Schema>,
362 L<DBIx::Class::Schema::Loader>, L<Catalyst::Helper::Model::DBIC::Schema>,
363 L<Catalyst::Helper::Model::DBIC::SchemaLoader>
367 Brandon L Black, C<blblack@gmail.com>
371 This program is free software, you can redistribute it and/or modify it
372 under the same terms as Perl itself.