fix test failure in 05testapp.t when env var not set, release
[catagits/Catalyst-Model-DBIC-Schema.git] / lib / Catalyst / Model / DBIC / Schema.pm
CommitLineData
ad91060a 1package Catalyst::Model::DBIC::Schema;
2
87145c6c 3use 5.008_001;
0fbbc8d5 4use Moose;
0f3de2c4 5use mro 'c3';
0fbbc8d5 6extends 'Catalyst::Model';
fb691af9 7with 'CatalystX::Component::Traits';
0fbbc8d5 8
87145c6c 9our $VERSION = '0.33';
7dfd616a 10$VERSION = eval $VERSION;
f090a149 11
73f72d28 12use namespace::autoclean;
bd309c0c 13use Carp::Clan '^Catalyst::Model::DBIC::Schema';
bfcd6e3d 14use Data::Dumper;
2201c2e4 15use DBIx::Class ();
ad91060a 16
61ed82a5 17use Catalyst::Model::DBIC::Schema::Types
2fa0a1f1 18 qw/ConnectInfo LoadedClass SchemaClass/;
61ed82a5 19
41bcf32f 20use MooseX::Types::Moose qw/ArrayRef Str ClassName Undef/;
0fbbc8d5 21
ad91060a 22=head1 NAME
23
24Catalyst::Model::DBIC::Schema - DBIx::Class::Schema Model Class
25
26=head1 SYNOPSIS
27
cbe03ea7 28First, prepare your database schema using L<DBIx::Class>, see
29L<Catalyst::Helper::Model::DBIC::Schema> for how to generate a
30L<DBIx::Class::Schema> from your database using the Helper script, and
31L<DBIx::Class::Schema::Loader::Base>.
07edc53e 32
cbe03ea7 33A typical usage of the helper script would be:
aabc1d75 34
cbe03ea7 35 script/myapp_create.pl model FilmDB DBIC::Schema MyApp::Schema::FilmDB \
36 create=static dbi:mysql:filmdb dbusername dbpass \
37 quote_char='`' name_sep='.'
aabc1d75 38
cbe03ea7 39If you are unfamiliar with L<DBIx::Class>, see L<DBIx::Class::Manual::Intro>
40first.
aabc1d75 41
cbe03ea7 42These examples assume that you already have a schema called
43C<MyApp::Schema::FilmDB>, which defines some Result classes for tables in
44C<MyApp::Schema::FilmDB::Result::Actor> and
45C<MyApp::Schema::FilmDB::Result::Film>. Either created by the helper script (as
46shown above) or manually.
aabc1d75 47
cbe03ea7 48The helper also creates a Model in C<lib/MyApp/Model/FilmDB.pm>, if you already
49have a schema you can create just the Model using:
07edc53e 50
cbe03ea7 51 script/myapp_create.pl model FilmDB DBIC::Schema MyApp::Schema::FilmDB
52 dbi:mysql:filmdb dbusername dbpass
aabc1d75 53
cbe03ea7 54The connect_info is optional and will be hardcoded into the Model if provided.
55It's better to configure it in your L<Catalyst> config file, which will also
56override any hardcoded config, see L</connect_info> for examples.
aabc1d75 57
95b41ca8 58Now you have a working Model which accesses your separate DBIC Schema. This can
59be used/accessed in the normal Catalyst manner, via C<< $c->model() >>:
aabc1d75 60
95b41ca8 61 my $db_model = $c->model('FilmDB'); # a Catalyst::Model
62 my $dbic = $c->model('FilmDB')->schema; # the actual DBIC object
aabc1d75 63
cbe03ea7 64The Model proxies to the C<Schema> instance so you can do:
07edc53e 65
95b41ca8 66 my $rs = $db_model->resultset('Actor'); # ... or ...
67 my $rs = $dbic ->resultset('Actor'); # same!
07edc53e 68
95b41ca8 69There is also a shortcut, which returns a L<DBIx::Class::ResultSet> directly,
70instead of a L<Catalyst::Model>:
07edc53e 71
95b41ca8 72 my $rs = $c->model('FilmDB::Actor');
aabc1d75 73
cbe03ea7 74See L<DBIx::Class::ResultSet> to find out more about which methods can be
75called on ResultSets.
76
77You can also define your own ResultSet methods to encapsulate the
78database/business logic of your applications. These go into, for example,
79C<lib/MyApp/Schema/FilmDB/ResultSet/Actor.pm>. The class must inherit from
80L<DBIx::Class::ResultSet> and is automatically loaded.
81
82Then call your methods like any other L<DBIx::Class::ResultSet> method:
83
84 $c->model('FilmDB::Actor')->SAG_members
aabc1d75 85
95b41ca8 86=head2 Some examples:
aabc1d75 87
f1613faa 88 # to access schema methods directly:
89 $c->model('FilmDB')->schema->source(...);
90
91 # to access the source object, resultset, and class:
07edc53e 92 $c->model('FilmDB')->source(...);
93 $c->model('FilmDB')->resultset(...);
94 $c->model('FilmDB')->class(...);
c12b7310 95
07edc53e 96 # For resultsets, there's an even quicker shortcut:
97 $c->model('FilmDB::Actor')
98 # is the same as $c->model('FilmDB')->resultset('Actor')
ad91060a 99
f1613faa 100 # To get the composed schema for making new connections:
101 my $newconn = $c->model('FilmDB')->composed_schema->connect(...);
102
103 # Or the same thing via a convenience shortcut:
104 my $newconn = $c->model('FilmDB')->connect(...);
105
106 # or, if your schema works on different storage drivers:
107 my $newconn = $c->model('FilmDB')->composed_schema->clone();
108 $newconn->storage_type('::LDAP');
109 $newconn->connection(...);
110
111 # and again, a convenience shortcut
112 my $newconn = $c->model('FilmDB')->clone();
113 $newconn->storage_type('::LDAP');
114 $newconn->connection(...);
115
95b41ca8 116To set up authentication, see L</"Setting up DBIC authentication"> below.
117
ad91060a 118=head1 DESCRIPTION
119
7b39f3f0 120This is a Catalyst Model for L<DBIx::Class::Schema>-based Models. See
ef91bcf9 121the documentation for L<Catalyst::Helper::Model::DBIC::Schema> for
122information on generating these Models via Helper scripts.
ad91060a 123
cbe03ea7 124When your Catalyst app starts up, a thin Model layer is created as an interface
125to your DBIC Schema. It should be clearly noted that the model object returned
126by C<< $c->model('FilmDB') >> is NOT itself a DBIC schema or resultset object,
127but merely a wrapper proving L<methods|/METHODS> to access the underlying
128schema (but also proxies other methods to the underlying schema.)
d52bc376 129
130In addition to this model class, a shortcut class is generated for each
131source in the schema, allowing easy and direct access to a resultset of the
132corresponding type. These generated classes are even thinner than the model
133class, providing no public methods but simply hooking into Catalyst's
134model() accessor via the
135L<ACCEPT_CONTEXT|Catalyst::Component/ACCEPT_CONTEXT> mechanism. The complete
136contents of each generated class is roughly equivalent to the following:
137
138 package MyApp::Model::FilmDB::Actor
139 sub ACCEPT_CONTEXT {
140 my ($self, $c) = @_;
141 $c->model('FilmDB')->resultset('Actor');
142 }
143
144In short, there are three techniques available for obtaining a DBIC
145resultset object:
146
147 # the long way
148 my $rs = $c->model('FilmDB')->schema->resultset('Actor');
149
150 # using the shortcut method on the model object
151 my $rs = $c->model('FilmDB')->resultset('Actor');
152
153 # using the generated class directly
154 my $rs = $c->model('FilmDB::Actor');
155
c082639a 156In order to add methods to a DBIC resultset, you cannot simply add them to
157the source (row, table) definition class; you must define a separate custom
cbe03ea7 158resultset class. This is just a matter of making a
159C<lib/MyApp/Schema/ResultSet/Actor.pm> class that inherits from
160L<DBIx::Class::ResultSet>, if you are using
161L<DBIx::Class::Schema/load_namespaces>, the default for helper script generated
162schemas.
163
164See L<DBIx::Class::Manual::Cookbook/"Predefined searches">
165for information on definining your own L<DBIx::Class::ResultSet> classes for
166use with L<DBIx::Class::Schema/load_classes>, the old default.
c082639a 167
ad91060a 168=head1 CONFIG PARAMETERS
169
b9cc2f76 170Any options in your config not listed here are passed to your schema.
171
c4fee9b8 172=head2 schema_class
ad91060a 173
174This is the classname of your L<DBIx::Class::Schema> Schema. It needs
aabc1d75 175to be findable in C<@INC>, but it does not need to be inside the
176C<Catalyst::Model::> namespace. This parameter is required.
ad91060a 177
c4fee9b8 178=head2 connect_info
ad91060a 179
180This is an arrayref of connection parameters, which are specific to your
b9a72351 181C<storage_type> (see your storage type documentation for more details).
182If you only need one parameter (e.g. the DSN), you can just pass a string
183instead of an arrayref.
ad91060a 184
0f2fd2c0 185This is not required if C<schema_class> already has connection information
d89e6c8a 186defined inside itself (which isn't highly recommended, but can be done)
0f2fd2c0 187
7db6da78 188For L<DBIx::Class::Storage::DBI>, which is the only supported
189C<storage_type> in L<DBIx::Class> at the time of this writing, the
190parameters are your dsn, username, password, and connect options hashref.
191
018eb0e2 192See L<DBIx::Class::Storage::DBI/connect_info> for a detailed explanation
193of the arguments supported.
7db6da78 194
195Examples:
196
2201c2e4 197 connect_info => {
198 dsn => 'dbi:Pg:dbname=mypgdb',
199 user => 'postgres',
200 password => ''
201 }
07edc53e 202
2201c2e4 203 connect_info => {
204 dsn => 'dbi:SQLite:dbname=foo.db',
205 on_connect_do => [
206 'PRAGMA synchronous = OFF',
207 ]
208 }
07edc53e 209
2201c2e4 210 connect_info => {
211 dsn => 'dbi:Pg:dbname=mypgdb',
212 user => 'postgres',
213 password => '',
214 pg_enable_utf8 => 1,
215 on_connect_do => [
216 'some SQL statement',
217 'another SQL statement',
218 ],
219 }
7db6da78 220
8281c933 221Or using L<Config::General>:
222
223 <Model::FilmDB>
224 schema_class MyApp::Schema::FilmDB
c34bcab6 225 traits Caching
8281c933 226 <connect_info>
2201c2e4 227 dsn dbi:Pg:dbname=mypgdb
228 user postgres
42e14c31 229 password ""
2201c2e4 230 auto_savepoint 1
a75b6e58 231 quote_char """
8281c933 232 on_connect_do some SQL statement
233 on_connect_do another SQL statement
234 </connect_info>
b9cc2f76 235 user_defined_schema_accessor foo
8281c933 236 </Model::FilmDB>
237
238or
239
240 <Model::FilmDB>
241 schema_class MyApp::Schema::FilmDB
242 connect_info dbi:SQLite:dbname=foo.db
243 </Model::FilmDB>
244
2201c2e4 245Or using L<YAML>:
246
247 Model::MyDB:
248 schema_class: MyDB
b9cc2f76 249 traits: Caching
2201c2e4 250 connect_info:
251 dsn: dbi:Oracle:mydb
252 user: mtfnpy
253 password: mypass
254 LongReadLen: 1000000
255 LongTruncOk: 1
b9cc2f76 256 on_connect_call: 'datetime_setup'
a75b6e58 257 quote_char: '"'
2201c2e4 258
259The old arrayref style with hashrefs for L<DBI> then L<DBIx::Class> options is also
260supported:
261
262 connect_info => [
263 'dbi:Pg:dbname=mypgdb',
264 'postgres',
265 '',
266 {
267 pg_enable_utf8 => 1,
268 },
269 {
0fbbc8d5 270 auto_savepoint => 1,
2201c2e4 271 on_connect_do => [
272 'some SQL statement',
273 'another SQL statement',
274 ],
275 }
276 ]
277
c34bcab6 278=head2 traits
0fbbc8d5 279
41bcf32f 280Array of Traits to apply to the instance. Traits are L<Moose::Role>s.
281
fb691af9 282They are relative to the C<< MyApp::TraitFor::Model::DBIC::Schema:: >>, then the C<<
283Catalyst::TraitFor::Model::DBIC::Schema:: >> namespaces, unless prefixed with C<+>
41bcf32f 284in which case they are taken to be a fully qualified name. E.g.:
2201c2e4 285
c34bcab6 286 traits Caching
fb691af9 287 traits +MyApp::TraitFor::Model::Foo
2201c2e4 288
0fbbc8d5 289A new instance is created at application time, so any consumed required
290attributes, coercions and modifiers will work.
2201c2e4 291
fb691af9 292Traits are applied at L<Catalyst::Component/COMPONENT> time using
293L<CatalystX::Component::Traits>.
0fbbc8d5 294
41bcf32f 295C<ref $self> will be an anon class if any traits are applied, C<<
296$self->_original_class_name >> will be the original class.
f090a149 297
c7d7b849 298When writing a Trait, interesting points to modify are C<BUILD>, L</setup> and
299L</ACCEPT_CONTEXT>.
0fbbc8d5 300
c34bcab6 301Traits that come with the distribution:
0fbbc8d5 302
303=over 4
2201c2e4 304
fb691af9 305=item L<Catalyst::TraitFor::Model::DBIC::Schema::Caching>
0fbbc8d5 306
fb691af9 307=item L<Catalyst::TraitFor::Model::DBIC::Schema::Replicated>
c4fee9b8 308
0fbbc8d5 309=back
8281c933 310
c4fee9b8 311=head2 storage_type
ad91060a 312
313Allows the use of a different C<storage_type> than what is set in your
314C<schema_class> (which in turn defaults to C<::DBI> if not set in current
f1613faa 315L<DBIx::Class>). Completely optional, and probably unnecessary for most
316people until other storage backends become available for L<DBIx::Class>.
ad91060a 317
c7d7b849 318=head1 ATTRIBUTES
319
320The keys you pass in the model configuration are available as attributes.
321
322Other attributes available:
323
324=head2 connect_info
325
326Your connect_info args normalized to hashref form (with dsn/user/password.) See
327L<DBIx::Class::Storage::DBI/connect_info> for more info on the hashref form of
328L</connect_info>.
329
330=head2 model_name
331
332The model name L<Catalyst> uses to resolve this model, the part after
333C<::Model::> or C<::M::> in your class name. E.g. if your class name is
334C<MyApp::Model::DB> the L</model_name> will be C<DB>.
335
c7d7b849 336=head2 _default_cursor_class
337
6f6b9c2d 338What to reset your L<DBIx::Class::Storage::DBI/cursor_class> to if a custom one
c7d7b849 339doesn't work out. Defaults to L<DBIx::Class::Storage::DBI::Cursor>.
340
fb691af9 341=head1 ATTRIBUTES FROM L<MooseX::Traits::Pluggable>
342
343=head2 _original_class_name
344
345The class name of your model before any L</traits> are applied. E.g.
346C<MyApp::Model::DB>.
347
c7d7b849 348=head2 _traits
349
6f6b9c2d 350Unresolved arrayref of traits passed in the config.
c7d7b849 351
352=head2 _resolved_traits
353
354Traits you used resolved to full class names.
355
ad91060a 356=head1 METHODS
357
46a2eb0c 358Methods not listed here are delegated to the connected schema used by the model
359instance, so the following are equivalent:
360
361 $c->model('DB')->schema->my_accessor('foo');
362 # or
363 $c->model('DB')->my_accessor('foo');
364
365Methods on the model take precedence over schema methods.
366
c4fee9b8 367=head2 new
ad91060a 368
369Instantiates the Model based on the above-documented ->config parameters.
0f2fd2c0 370The only required parameter is C<schema_class>. C<connect_info> is
371required in the case that C<schema_class> does not already have connection
372information defined for it.
ad91060a 373
c4fee9b8 374=head2 schema
f1613faa 375
376Accessor which returns the connected schema being used by the this model.
377There are direct shortcuts on the model class itself for
378schema->resultset, schema->source, and schema->class.
379
c4fee9b8 380=head2 composed_schema
f1613faa 381
382Accessor which returns the composed schema, which has no connection info,
383which was used in constructing the C<schema> above. Useful for creating
384new connections based on the same schema/model. There are direct shortcuts
385from the model object for composed_schema->clone and composed_schema->connect
386
c4fee9b8 387=head2 clone
f1613faa 388
389Shortcut for ->composed_schema->clone
390
c4fee9b8 391=head2 connect
f1613faa 392
393Shortcut for ->composed_schema->connect
394
c4fee9b8 395=head2 source
c12b7310 396
f1613faa 397Shortcut for ->schema->source
398
c4fee9b8 399=head2 class
f1613faa 400
401Shortcut for ->schema->class
402
c4fee9b8 403=head2 resultset
f1613faa 404
405Shortcut for ->schema->resultset
406
c4fee9b8 407=head2 storage
f1613faa 408
409Provides an accessor for the connected schema's storage object.
410Used often for debugging and controlling transactions.
b8427e0b 411
ad91060a 412=cut
413
c34bcab6 414has schema_class => (
0fbbc8d5 415 is => 'ro',
2fa0a1f1 416 isa => SchemaClass,
0fbbc8d5 417 coerce => 1,
418 required => 1
419);
420
c34bcab6 421has storage_type => (is => 'rw', isa => Str);
0fbbc8d5 422
18b829f0 423has connect_info => (is => 'rw', isa => ConnectInfo, coerce => 1);
0fbbc8d5 424
c7d7b849 425has model_name => (
426 is => 'ro',
427 isa => Str,
428 required => 1,
429 lazy_build => 1,
430);
ad91060a 431
c34bcab6 432has _default_cursor_class => (
61ed82a5 433 is => 'ro',
7314403a 434 isa => LoadedClass,
61ed82a5 435 default => 'DBIx::Class::Storage::DBI::Cursor',
436 coerce => 1
437);
438
0fbbc8d5 439sub BUILD {
f27a05ea 440 my ($self, $args) = @_;
f2488839 441 my $class = $self->_original_class_name;
2201c2e4 442 my $schema_class = $self->schema_class;
ad91060a 443
2201c2e4 444 if( !$self->connect_info ) {
f1613faa 445 if($schema_class->storage && $schema_class->storage->connect_info) {
2201c2e4 446 $self->connect_info($schema_class->storage->connect_info);
f1613faa 447 }
448 else {
39f5f008 449 die "Either ->config->{connect_info} must be defined for $class"
460e3ac8 450 . " or $schema_class must have connect info defined on it."
451 . " Here's what we got:\n"
f1613faa 452 . Dumper($self);
453 }
7db6da78 454 }
455
0fbbc8d5 456 if (exists $self->connect_info->{cursor_class}) {
457 eval { Class::MOP::load_class($self->connect_info->{cursor_class}) }
458 or croak "invalid connect_info: Cannot load your cursor_class"
459 . " ".$self->connect_info->{cursor_class}.": $@";
460 }
461
0fbbc8d5 462 $self->setup;
463
f1613faa 464 $self->composed_schema($schema_class->compose_namespace($class));
2201c2e4 465
cbe03ea7 466 my $was_mutable = $self->meta->is_mutable;
467
7bd33abf 468 $self->meta->make_mutable;
46a2eb0c 469 $self->meta->add_attribute('schema',
470 is => 'rw',
180c1a1a 471 isa => 'DBIx::Class::Schema',
46a2eb0c 472 handles => $self->_delegates
473 );
cbe03ea7 474 $self->meta->make_immutable unless $was_mutable;
46a2eb0c 475
f1613faa 476 $self->schema($self->composed_schema->clone);
477
f27a05ea 478 $self->_pass_options_to_schema($args);
7bd33abf 479
2201c2e4 480 $self->schema->storage_type($self->storage_type)
481 if $self->storage_type;
7db6da78 482
2201c2e4 483 $self->schema->connection($self->connect_info);
484
485 $self->_install_rs_models;
2201c2e4 486}
487
488sub clone { shift->composed_schema->clone(@_); }
489
490sub connect { shift->composed_schema->connect(@_); }
491
c4fee9b8 492=head2 setup
2201c2e4 493
e203cd42 494Called at C<BUILD> time before configuration, but after L</connect_info> is
c7d7b849 495set. To do something after configuuration use C<< after BUILD => >>.
2201c2e4 496
497=cut
498
0fbbc8d5 499sub setup { 1 }
2201c2e4 500
c4fee9b8 501=head2 ACCEPT_CONTEXT
2201c2e4 502
73f72d28 503Point of extension for doing things at C<< $c->model >> time with context,
504returns the model instance, see L<Catalyst::Manual::Intro/ACCEPT_CONTEXT> for
505more information.
2201c2e4 506
0fbbc8d5 507=cut
2201c2e4 508
0fbbc8d5 509sub ACCEPT_CONTEXT { shift }
2201c2e4 510
511sub _install_rs_models {
512 my $self = shift;
7b1fe8c2 513 my $class = $self->_original_class_name;
2201c2e4 514
ad91060a 515 no strict 'refs';
39f5f008 516
517 my @sources = $self->schema->sources;
518
ca7cf6f0 519 unless (@sources) {
520 warn <<'EOF' unless $ENV{CMDS_NO_SOURCES};
521******************************* WARNING ***************************************
522* No sources found (did you forget to define your tables?) *
523* *
524* To turn off this warning, set the CMDS_NO_SOURCES environment variable. *
525*******************************************************************************
526EOF
527 }
39f5f008 528
529 foreach my $moniker (@sources) {
0b2a7108 530 my $classname = "${class}::$moniker";
7db6da78 531 *{"${classname}::ACCEPT_CONTEXT"} = sub {
ad91060a 532 shift;
2201c2e4 533 shift->model($self->model_name)->resultset($moniker);
ad91060a 534 }
535 }
2201c2e4 536}
ad91060a 537
61ed82a5 538sub _reset_cursor_class {
539 my $self = shift;
540
541 if ($self->storage->can('cursor_class')) {
542 $self->storage->cursor_class($self->_default_cursor_class)
543 if $self->storage->cursor_class ne $self->_default_cursor_class;
544 }
545}
546
50f488ec 547{
548 my %COMPOSED_CACHE;
549
550 sub composed_schema {
551 my $self = shift;
552 my $class = $self->_original_class_name;
553 my $store = \$COMPOSED_CACHE{$class}{$self->schema_class};
554
555 $$store = shift if @_;
556
557 return $$store
558 }
559}
560
c7d7b849 561sub _build_model_name {
562 my $self = shift;
563 my $class = $self->_original_class_name;
564 (my $model_name = $class) =~ s/^[\w:]+::(?:Model|M):://;
565
566 return $model_name;
41bcf32f 567}
568
180c1a1a 569sub _delegates {
46a2eb0c 570 my $self = shift;
571
b9cc2f76 572 my $schema_meta = Class::MOP::Class->initialize($self->schema_class);
573 my @schema_methods = $schema_meta->get_all_method_names;
46a2eb0c 574
180c1a1a 575# combine with any already added by other schemas
576 my @handles = eval {
577 @{ $self->meta->find_attribute_by_name('schema')->handles }
578 };
579
580# now kill the attribute, otherwise add_attribute in BUILD will not do the right
b9cc2f76 581# thing (it clears the handles for some reason.) May be a Moose bug.
180c1a1a 582 eval { $self->meta->remove_attribute('schema') };
583
584 my %schema_methods;
585 @schema_methods{ @schema_methods, @handles } = ();
586 @schema_methods = keys %schema_methods;
587
588 my @my_methods = $self->meta->get_all_method_names;
46a2eb0c 589 my %my_methods;
590 @my_methods{@my_methods} = ();
591
592 my @delegates;
593 for my $method (@schema_methods) {
594 push @delegates, $method unless exists $my_methods{$method};
595 }
596
597 return \@delegates;
598}
599
7bd33abf 600sub _pass_options_to_schema {
f27a05ea 601 my ($self, $args) = @_;
602
603 my @attributes = map {
604 $_->init_arg || ()
605 } $self->meta->get_all_attributes;
7bd33abf 606
7bd33abf 607 my %attributes;
608 @attributes{@attributes} = ();
609
f27a05ea 610 for my $opt (keys %$args) {
7bd33abf 611 if (not exists $attributes{$opt}) {
294245b0 612 next unless $self->schema->can($opt);
7bd33abf 613 $self->schema->$opt($self->{$opt});
614 }
615 }
616}
617
0fbbc8d5 618__PACKAGE__->meta->make_immutable;
2201c2e4 619
ca7cf6f0 620=head1 ENVIRONMENT
621
622=over 4
623
624=item CMDS_NO_SOURCES
625
cbe03ea7 626Set this variable if you will be using schemas with no sources (Result classes)
627to disable the warning. The warning is there because having no Result classes
628is usually a mistake.
ca7cf6f0 629
630=back
631
95b41ca8 632=head1 Setting up DBIC authentication
633
634You can set this up with
635L<Catalyst::Authentication::Store::DBIx::Class> in MyApp.pm:
636
637 package MyApp;
638
639 use Catalyst qw/... Authentication .../;
640
641 ...
642
10c73a30 643 __PACKAGE__->config('Plugin::Authentication' =>
644 {
95b41ca8 645 default_realm => 'members',
10c73a30 646 members => {
647 credential => {
648 class => 'Password',
649 password_field => 'password',
650 password_type => 'hashed'
651 password_hash_type => 'SHA-256'
652 },
653 store => {
654 class => 'DBIx::Class',
655 user_model => 'DB::User',
656 role_relation => 'roles',
657 role_field => 'rolename',
95b41ca8 658 }
659 }
10c73a30 660 });
95b41ca8 661
ad91060a 662=head1 SEE ALSO
663
7b39f3f0 664General Catalyst Stuff:
665
666L<Catalyst::Manual>, L<Catalyst::Test>, L<Catalyst::Request>,
667L<Catalyst::Response>, L<Catalyst::Helper>, L<Catalyst>,
668
669Stuff related to DBIC and this Model style:
670
671L<DBIx::Class>, L<DBIx::Class::Schema>,
f090a149 672L<DBIx::Class::Schema::Loader>, L<Catalyst::Helper::Model::DBIC::Schema>,
e203cd42 673L<CatalystX::Component::Traits>, L<MooseX::Traits::Pluggable>
ad91060a 674
c34bcab6 675Traits:
c4fee9b8 676
fb691af9 677L<Catalyst::TraitFor::Model::DBIC::Schema::Caching>,
cbe03ea7 678L<Catalyst::TraitFor::Model::DBIC::Schema::Replicated>,
679L<Catalyst::TraitFor::Model::DBIC::Schema::QueryLog>
c4fee9b8 680
ad91060a 681=head1 AUTHOR
682
e203cd42 683Brandon L Black C<blblack at gmail.com>
ad91060a 684
e203cd42 685=head1 CONTRIBUTORS
2ff00e2b 686
e203cd42 687caelum: Rafael Kitover C<rkitover at cpan.org>
2ff00e2b 688
4e251d1a 689dandv: Dan Dascalescu C<dandv at cpan.org>
6d9e2623 690
4e251d1a 691bluefeet: Aran Deltac C<bluefeet@cpan.org>
692
693t0m: Tomas Doran C<bobtfish@bobtfish.net>
694
695osfameron: C<osfameron@cpan.org>
49c75c04 696
cbe03ea7 697ozum: Ozum Eldogan C<ozum@ozum.net>
ce9e19dc 698
87145c6c 699Pavel I. Shaydo C<zwon@trinitum.org>
700
ad91060a 701=head1 COPYRIGHT
702
4e251d1a 703Copyright (c) 2006 - 2009
704the Catalyst::Model::DBIC::Schema L</AUTHOR> and L</CONTRIBUTORS>
705as listed above.
706
707=head1 LICENSE
708
6d9e2623 709This program is free software. You can redistribute it and/or modify it
ad91060a 710under the same terms as Perl itself.
711
712=cut
713
7141;
c7d7b849 715# vim:sts=4 sw=4 et: