1 package Catalyst::Model::DBIC::Schema;
8 use base qw/Catalyst::Model Class::Accessor::Fast Class::Data::Accessor/;
11 use UNIVERSAL::require;
16 __PACKAGE__->mk_classaccessor('composed_schema');
17 __PACKAGE__->mk_accessors('schema');
21 Catalyst::Model::DBIC::Schema - DBIx::Class::Schema Model Class
25 Manual creation of a DBIx::Class::Schema and a Catalyst::Model::DBIC::Schema:
31 Create the DBIx:Class schema in MyApp/Schema/FilmDB.pm:
33 package MyApp::Schema::FilmDB;
34 use base qw/DBIx::Class::Schema/;
36 __PACKAGE__->load_classes(qw/Actor Role/);
40 Create some classes for the tables in the database, for example an
41 Actor in MyApp/Schema/FilmDB/Actor.pm:
43 package MyApp::Schema::FilmDB::Actor;
44 use base qw/DBIx::Class/
46 __PACKAGE__->load_components(qw/Core/);
47 __PACKAGE__->table('actor');
51 and a Role in MyApp/Schema/FilmDB/Role.pm:
53 package MyApp::Schema::FilmDB::Role;
54 use base qw/DBIx::Class/
56 __PACKAGE__->load_components(qw/Core/);
57 __PACKAGE__->table('role');
61 Notice that the schema is in MyApp::Schema, not in MyApp::Model. This way it's
62 usable as a standalone module and you can test/run it without Catalyst.
66 To expose it to Catalyst as a model, you should create a DBIC Model in
67 MyApp/Model/FilmDB.pm:
69 package MyApp::Model::FilmDB;
70 use base qw/Catalyst::Model::DBIC::Schema/;
73 schema_class => 'MyApp::Schema::FilmDB',
82 See below for a full list of the possible config parameters.
86 Now you have a working Model which accesses your separate DBIC Schema. This can
87 be used/accessed in the normal Catalyst manner, via $c->model():
89 my $actor = $c->model('FilmDB::Actor')->find(1);
91 You can also use it to set up DBIC authentication with
92 Authentication::Store::DBIC in MyApp.pm:
96 use Catalyst qw/... Authentication::Store::DBIC/;
100 __PACKAGE__->config->{authentication}{dbic} = {
101 user_class => 'FilmDB::Actor',
102 user_field => 'name',
103 password_field => 'password'
106 C<< $c->model('Schema::Source') >> returns a L<DBIx::Class::ResultSet> for
107 the source name parameter passed. To find out more about which methods can
108 be called on a ResultSet, or how to add your own methods to it, please see
109 the ResultSet documentation in the L<DBIx::Class> distribution.
111 Some examples are given below:
113 # to access schema methods directly:
114 $c->model('FilmDB')->schema->source(...);
116 # to access the source object, resultset, and class:
117 $c->model('FilmDB')->source(...);
118 $c->model('FilmDB')->resultset(...);
119 $c->model('FilmDB')->class(...);
121 # For resultsets, there's an even quicker shortcut:
122 $c->model('FilmDB::Actor')
123 # is the same as $c->model('FilmDB')->resultset('Actor')
125 # To get the composed schema for making new connections:
126 my $newconn = $c->model('FilmDB')->composed_schema->connect(...);
128 # Or the same thing via a convenience shortcut:
129 my $newconn = $c->model('FilmDB')->connect(...);
131 # or, if your schema works on different storage drivers:
132 my $newconn = $c->model('FilmDB')->composed_schema->clone();
133 $newconn->storage_type('::LDAP');
134 $newconn->connection(...);
136 # and again, a convenience shortcut
137 my $newconn = $c->model('FilmDB')->clone();
138 $newconn->storage_type('::LDAP');
139 $newconn->connection(...);
143 This is a Catalyst Model for L<DBIx::Class::Schema>-based Models. See
144 the documentation for L<Catalyst::Helper::Model::DBIC::Schema> for
145 information on generating these Models via Helper scripts.
147 When your Catalyst app starts up, a thin Model layer is created as an
148 interface to your DBIC Schema. It should be clearly noted that the model
149 object returned by C<< $c->model('FilmDB') >> is NOT itself a DBIC schema or
150 resultset object, but merely a wrapper proving L<methods|/METHODS> to access
151 the underlying schema.
153 In addition to this model class, a shortcut class is generated for each
154 source in the schema, allowing easy and direct access to a resultset of the
155 corresponding type. These generated classes are even thinner than the model
156 class, providing no public methods but simply hooking into Catalyst's
157 model() accessor via the
158 L<ACCEPT_CONTEXT|Catalyst::Component/ACCEPT_CONTEXT> mechanism. The complete
159 contents of each generated class is roughly equivalent to the following:
161 package MyApp::Model::FilmDB::Actor
164 $c->model('FilmDB')->resultset('Actor');
167 In short, there are three techniques available for obtaining a DBIC
171 my $rs = $c->model('FilmDB')->schema->resultset('Actor');
173 # using the shortcut method on the model object
174 my $rs = $c->model('FilmDB')->resultset('Actor');
176 # using the generated class directly
177 my $rs = $c->model('FilmDB::Actor');
179 In order to add methods to a DBIC resultset, you cannot simply add them to
180 the source (row, table) definition class; you must define a separate custom
181 resultset class. See L<DBIx::Class::Manual::Cookbook/"Predefined searches">
184 =head1 CONFIG PARAMETERS
190 This is the classname of your L<DBIx::Class::Schema> Schema. It needs
191 to be findable in C<@INC>, but it does not need to be inside the
192 C<Catalyst::Model::> namespace. This parameter is required.
196 This is an arrayref of connection parameters, which are specific to your
197 C<storage_type> (see your storage type documentation for more details).
198 If you only need one parameter (e.g. the DSN), you can just pass a string
199 instead of an arrayref.
201 This is not required if C<schema_class> already has connection information
202 defined inside itself (which isn't highly recommended, but can be done)
204 For L<DBIx::Class::Storage::DBI>, which is the only supported
205 C<storage_type> in L<DBIx::Class> at the time of this writing, the
206 parameters are your dsn, username, password, and connect options hashref.
208 See L<DBIx::Class::Storage::DBI/connect_info> for a detailed explanation
209 of the arguments supported.
213 connect_info => [ 'dbi:Pg:dbname=mypgdb', 'postgres', '' ],
216 'dbi:SQLite:dbname=foo.db',
219 'PRAGMA synchronous = OFF',
225 'dbi:Pg:dbname=mypgdb',
231 'some SQL statement',
232 'another SQL statement',
237 Or using L<Config::General>:
240 schema_class MyApp::Schema::FilmDB
241 connect_info dbi:Pg:dbname=mypgdb
242 connect_info postgres
246 on_connect_do some SQL statement
247 on_connect_do another SQL statement
254 schema_class MyApp::Schema::FilmDB
255 connect_info dbi:SQLite:dbname=foo.db
261 Allows the use of a different C<storage_type> than what is set in your
262 C<schema_class> (which in turn defaults to C<::DBI> if not set in current
263 L<DBIx::Class>). Completely optional, and probably unnecessary for most
264 people until other storage backends become available for L<DBIx::Class>.
274 Instantiates the Model based on the above-documented ->config parameters.
275 The only required parameter is C<schema_class>. C<connect_info> is
276 required in the case that C<schema_class> does not already have connection
277 information defined for it.
281 Accessor which returns the connected schema being used by the this model.
282 There are direct shortcuts on the model class itself for
283 schema->resultset, schema->source, and schema->class.
285 =item composed_schema
287 Accessor which returns the composed schema, which has no connection info,
288 which was used in constructing the C<schema> above. Useful for creating
289 new connections based on the same schema/model. There are direct shortcuts
290 from the model object for composed_schema->clone and composed_schema->connect
294 Shortcut for ->composed_schema->clone
298 Shortcut for ->composed_schema->connect
302 Shortcut for ->schema->source
306 Shortcut for ->schema->class
310 Shortcut for ->schema->resultset
314 Provides an accessor for the connected schema's storage object.
315 Used often for debugging and controlling transactions.
322 my $self = shift->next::method(@_);
324 my $class = ref($self);
325 my $model_name = $class;
326 $model_name =~ s/^[\w:]+::(?:Model|M):://;
328 croak "->config->{schema_class} must be defined for this model"
329 unless $self->{schema_class};
331 my $schema_class = $self->{schema_class};
333 $schema_class->require
334 or croak "Cannot load schema class '$schema_class': $@";
336 if( !$self->{connect_info} ) {
337 if($schema_class->storage && $schema_class->storage->connect_info) {
338 $self->{connect_info} = $schema_class->storage->connect_info;
341 croak "Either ->config->{connect_info} must be defined for $class"
342 . " or $schema_class must have connect info defined on it."
343 . " Here's what we got:\n"
348 $self->composed_schema($schema_class->compose_namespace($class));
349 $self->schema($self->composed_schema->clone);
351 $self->schema->storage_type($self->{storage_type})
352 if $self->{storage_type};
354 $self->schema->connection(
355 ref $self->{connect_info} eq 'ARRAY' ?
356 @{$self->{connect_info}} :
357 $self->{connect_info}
361 foreach my $moniker ($self->schema->sources) {
362 my $classname = "${class}::$moniker";
363 *{"${classname}::ACCEPT_CONTEXT"} = sub {
365 shift->model($model_name)->resultset($moniker);
372 sub clone { shift->composed_schema->clone(@_); }
374 sub connect { shift->composed_schema->connect(@_); }
376 sub storage { shift->schema->storage(@_); }
380 General Catalyst Stuff:
382 L<Catalyst::Manual>, L<Catalyst::Test>, L<Catalyst::Request>,
383 L<Catalyst::Response>, L<Catalyst::Helper>, L<Catalyst>,
385 Stuff related to DBIC and this Model style:
387 L<DBIx::Class>, L<DBIx::Class::Schema>,
388 L<DBIx::Class::Schema::Loader>, L<Catalyst::Helper::Model::DBIC::Schema>
392 Brandon L Black, C<blblack@gmail.com>
396 This program is free software, you can redistribute it and/or modify it
397 under the same terms as Perl itself.