3 DBIx::Class::Manual::Cookbook - Miscellaneous recipes
11 When you expect a large number of results, you can ask L<DBIx::Class> for a
12 paged resultset, which will fetch only a small number of records at a time:
14 my $rs = $schema->resultset('Artist')->search(
17 page => 1, # page to return (defaults to 1)
18 rows => 10, # number of results per page
22 return $rs->all(); # all records for page 1
24 The C<page> attribute does not have to be specified in your search:
26 my $rs = $schema->resultset('Artist')->search(
33 return $rs->page(1); # DBIx::Class::ResultSet containing first 10 records
35 In either of the above cases, you can return a L<Data::Page> object for the
36 resultset (suitable for use in e.g. a template) using the C<pager> method:
40 =head3 Complex WHERE clauses
42 Sometimes you need to formulate a query using specific operators:
44 my @albums = $schema->resultset('Album')->search({
45 artist => { 'like', '%Lamb%' },
46 title => { 'like', '%Fear of Fours%' },
49 This results in something like the following C<WHERE> clause:
51 WHERE artist LIKE '%Lamb%' AND title LIKE '%Fear of Fours%'
53 Other queries might require slightly more complex logic:
55 my @albums = $schema->resultset('Album')->search({
58 artist => { 'like', '%Smashing Pumpkins%' },
59 title => 'Siamese Dream',
61 artist => 'Starchildren',
65 This results in the following C<WHERE> clause:
67 WHERE ( artist LIKE '%Smashing Pumpkins%' AND title = 'Siamese Dream' )
68 OR artist = 'Starchildren'
70 For more information on generating complex queries, see
71 L<SQL::Abstract/WHERE CLAUSES>.
73 =head3 Using specific columns
75 When you only want selected columns from a table, you can use C<cols> to
76 specify which ones you need:
78 my $rs = $schema->resultset('Artist')->search(
81 columns => [qw/ name /]
86 # SELECT artist.name FROM artist
88 =head3 Using database functions or stored procedures
90 The combination of C<select> and C<as> can be used to return the result of a
91 database function or stored procedure as a column value. You use C<select> to
92 specify the source for your column value (e.g. a column name, function, or
93 stored procedure name). You then use C<as> to set the column name you will use
94 to access the returned value:
96 my $rs = $schema->resultset('Artist')->search(
99 select => [ 'name', { LENGTH => 'name' } ],
100 as => [qw/ name name_length /],
105 # SELECT name name, LENGTH( name ) name_length
108 If your alias exists as a column in your base class (i.e. it was added with
109 C<add_columns>), you just access it as normal. Our C<Artist> class has a C<name>
110 column, so we just use the C<name> accessor:
112 my $artist = $rs->first();
113 my $name = $artist->name();
115 If on the other hand the alias does not correspond to an existing column, you
116 can get the value using the C<get_column> accessor:
118 my $name_length = $artist->get_column('name_length');
120 If you don't like using C<get_column>, you can always create an accessor for
121 any of your aliases using either of these:
123 # Define accessor manually:
124 sub name_length { shift->get_column('name_length'); }
126 # Or use DBIx::Class::AccessorGroup:
127 __PACKAGE__->mk_group_accessors('column' => 'name_length');
129 =head3 SELECT DISTINCT with multiple columns
131 my $rs = $schema->resultset('Foo')->search(
135 { distinct => [ $source->columns ] }
137 as => [ $source->columns ]
141 my $count = $rs->next->get_column('count');
143 =head3 SELECT COUNT(DISTINCT colname)
145 my $rs = $schema->resultset('Foo')->search(
149 { count => { distinct => 'colname' } }
155 =head3 Grouping results
157 L<DBIx::Class> supports C<GROUP BY> as follows:
159 my $rs = $schema->resultset('Artist')->search(
163 select => [ 'name', { count => 'cds.cdid' } ],
164 as => [qw/ name cd_count /],
165 group_by => [qw/ name /]
170 # SELECT name, COUNT( cds.cdid ) FROM artist me
171 # LEFT JOIN cd cds ON ( cds.artist = me.artistid )
174 =head3 Predefined searches
176 You can write your own DBIx::Class::ResultSet class by inheriting from it
177 and define often used searches as methods:
179 package My::DBIC::ResultSet::CD;
182 use base 'DBIx::Class::ResultSet';
184 sub search_cds_ordered {
187 return $self->search(
189 { order_by => 'name DESC' },
195 To use your resultset, first tell DBIx::Class to create an instance of it
196 for you, in your My::DBIC::Schema::CD class:
198 __PACKAGE__->resultset_class('My::DBIC::ResultSet::CD');
200 Then call your new method in your code:
202 my $ordered_cds = $schema->resultset('CD')->search_cds_ordered();
205 =head3 Predefined searches without writing a ResultSet class
207 Alternatively you can automatically generate a DBIx::Class::ResultSet
208 class by using the ResultSetManager component and tagging your method
211 __PACKAGE__->load_components(qw/ ResultSetManager Core /);
213 sub search_cds_ordered : ResultSet {
215 return $self->search(
217 { order_by => 'name DESC' },
221 Then call your method in the same way from your code:
223 my $ordered_cds = $schema->resultset('CD')->search_cds_ordered();
225 =head2 Using joins and prefetch
227 You can use the C<join> attribute to allow searching on, or sorting your
228 results by, one or more columns in a related table. To return all CDs matching
229 a particular artist name:
231 my $rs = $schema->resultset('CD')->search(
233 'artist.name' => 'Bob Marley'
236 join => [qw/artist/], # join the artist table
241 # SELECT cd.* FROM cd
242 # JOIN artist ON cd.artist = artist.id
243 # WHERE artist.name = 'Bob Marley'
245 If required, you can now sort on any column in the related tables by including
246 it in your C<order_by> attribute:
248 my $rs = $schema->resultset('CD')->search(
250 'artist.name' => 'Bob Marley'
253 join => [qw/ artist /],
254 order_by => [qw/ artist.name /]
259 # SELECT cd.* FROM cd
260 # JOIN artist ON cd.artist = artist.id
261 # WHERE artist.name = 'Bob Marley'
262 # ORDER BY artist.name
264 Note that the C<join> attribute should only be used when you need to search or
265 sort using columns in a related table. Joining related tables when you only
266 need columns from the main table will make performance worse!
268 Now let's say you want to display a list of CDs, each with the name of the
269 artist. The following will work fine:
271 while (my $cd = $rs->next) {
272 print "CD: " . $cd->title . ", Artist: " . $cd->artist->name;
275 There is a problem however. We have searched both the C<cd> and C<artist> tables
276 in our main query, but we have only returned data from the C<cd> table. To get
277 the artist name for any of the CD objects returned, L<DBIx::Class> will go back
280 SELECT artist.* FROM artist WHERE artist.id = ?
282 A statement like the one above will run for each and every CD returned by our
283 main query. Five CDs, five extra queries. A hundred CDs, one hundred extra
286 Thankfully, L<DBIx::Class> has a C<prefetch> attribute to solve this problem.
287 This allows you to fetch results from related tables in advance:
289 my $rs = $schema->resultset('CD')->search(
291 'artist.name' => 'Bob Marley'
294 join => [qw/ artist /],
295 order_by => [qw/ artist.name /],
296 prefetch => [qw/ artist /] # return artist data too!
300 # Equivalent SQL (note SELECT from both "cd" and "artist"):
301 # SELECT cd.*, artist.* FROM cd
302 # JOIN artist ON cd.artist = artist.id
303 # WHERE artist.name = 'Bob Marley'
304 # ORDER BY artist.name
306 The code to print the CD list remains the same:
308 while (my $cd = $rs->next) {
309 print "CD: " . $cd->title . ", Artist: " . $cd->artist->name;
312 L<DBIx::Class> has now prefetched all matching data from the C<artist> table,
313 so no additional SQL statements are executed. You now have a much more
316 Note that as of L<DBIx::Class> 0.05999_01, C<prefetch> I<can> be used with
317 C<has_many> relationships.
319 Also note that C<prefetch> should only be used when you know you will
320 definitely use data from a related table. Pre-fetching related tables when you
321 only need columns from the main table will make performance worse!
323 =head3 Multi-step joins
325 Sometimes you want to join more than one relationship deep. In this example,
326 we want to find all C<Artist> objects who have C<CD>s whose C<LinerNotes>
327 contain a specific string:
329 # Relationships defined elsewhere:
330 # Artist->has_many('cds' => 'CD', 'artist');
331 # CD->has_one('liner_notes' => 'LinerNotes', 'cd');
333 my $rs = $schema->resultset('Artist')->search(
335 'liner_notes.notes' => { 'like', '%some text%' },
339 'cds' => 'liner_notes'
345 # SELECT artist.* FROM artist
346 # JOIN ( cd ON artist.id = cd.artist )
347 # JOIN ( liner_notes ON cd.id = liner_notes.cd )
348 # WHERE liner_notes.notes LIKE '%some text%'
350 Joins can be nested to an arbitrary level. So if we decide later that we
351 want to reduce the number of Artists returned based on who wrote the liner
354 # Relationship defined elsewhere:
355 # LinerNotes->belongs_to('author' => 'Person');
357 my $rs = $schema->resultset('Artist')->search(
359 'liner_notes.notes' => { 'like', '%some text%' },
360 'author.name' => 'A. Writer'
365 'liner_notes' => 'author'
372 # SELECT artist.* FROM artist
373 # JOIN ( cd ON artist.id = cd.artist )
374 # JOIN ( liner_notes ON cd.id = liner_notes.cd )
375 # JOIN ( author ON author.id = liner_notes.author )
376 # WHERE liner_notes.notes LIKE '%some text%'
377 # AND author.name = 'A. Writer'
379 =head2 Multi-step prefetch
381 From 0.04999_05 onwards, C<prefetch> can be nested more than one relationship
382 deep using the same syntax as a multi-step join:
384 my $rs = $schema->resultset('Tag')->search(
394 # SELECT tag.*, cd.*, artist.* FROM tag
395 # JOIN cd ON tag.cd = cd.cdid
396 # JOIN artist ON cd.artist = artist.artistid
398 Now accessing our C<cd> and C<artist> relationships does not need additional
401 my $tag = $rs->first;
402 print $tag->cd->artist->name;
404 =head2 Using relationships
406 =head3 Create a new row in a related table
408 my $book->create_related('author', { name => 'Fred'});
410 =head3 Search in a related table
412 Only searches for books named 'Titanic' by the author in $author.
414 my $author->search_related('books', { name => 'Titanic' });
416 =head3 Delete data in a related table
418 Deletes only the book named Titanic by the author in $author.
420 my $author->delete_related('books', { name => 'Titanic' });
422 =head3 Ordering a relationship result set
424 If you always want a relation to be ordered, you can specify this when you
425 create the relationship.
427 To order C<< $book->pages >> by descending page_number.
429 Book->has_many('pages' => 'Page', 'book', { order_by => \'page_number DESC'} );
435 As of version 0.04001, there is improved transaction support in
436 L<DBIx::Class::Storage> and L<DBIx::Class::Schema>. Here is an
437 example of the recommended way to use it:
439 my $genus = $schema->resultset('Genus')->find(12);
447 $genus->add_to_species({ name => 'troglodyte' });
450 $schema->txn_do($coderef2); # Can have a nested transaction
451 return $genus->species;
456 $rs = $schema->txn_do($coderef1);
459 if ($@) { # Transaction failed
460 die "the sky is falling!" #
461 if ($@ =~ /Rollback failed/); # Rollback failed
463 deal_with_failed_transaction();
466 Nested transactions will work as expected. That is, only the outermost
467 transaction will actually issue a commit to the $dbh, and a rollback
468 at any level of any transaction will cause the entire nested
469 transaction to fail. Support for savepoints and for true nested
470 transactions (for databases that support them) will hopefully be added
473 =head2 Many-to-many relationships
475 This is straightforward using L<DBIx::Class::Relationship::ManyToMany>:
478 # ... set up connection ...
482 __PACKAGE__->table('user');
483 __PACKAGE__->add_columns(qw/id name/);
484 __PACKAGE__->set_primary_key('id');
485 __PACKAGE__->has_many('user_address' => 'My::UserAddress', 'user');
486 __PACKAGE__->many_to_many('addresses' => 'user_address', 'address');
488 package My::UserAddress;
490 __PACKAGE__->table('user_address');
491 __PACKAGE__->add_columns(qw/user address/);
492 __PACKAGE__->set_primary_key(qw/user address/);
493 __PACKAGE__->belongs_to('user' => 'My::User');
494 __PACKAGE__->belongs_to('address' => 'My::Address');
498 __PACKAGE__->table('address');
499 __PACKAGE__->add_columns(qw/id street town area_code country/);
500 __PACKAGE__->set_primary_key('id');
501 __PACKAGE__->has_many('user_address' => 'My::UserAddress', 'address');
502 __PACKAGE__->many_to_many('users' => 'user_address', 'user');
504 $rs = $user->addresses(); # get all addresses for a user
505 $rs = $address->users(); # get all users for an address
507 =head2 Setting default values for a row
509 It's as simple as overriding the C<new> method. Note the use of
513 my ( $class, $attrs ) = @_;
515 $attrs->{foo} = 'bar' unless defined $attrs->{foo};
517 $class->next::method($attrs);
520 For more information about C<next::method>, look in the L<Class::C3>
521 documentation. See also L<DBIx::Class::Manual::Component> for more
522 ways to write your own base classes to do this.
524 People looking for ways to do "triggers" with DBIx::Class are probably
525 just looking for this.
527 =head2 Stringification
529 Employ the standard stringification technique by using the C<overload>
532 To make an object stringify itself as a single column, use something
533 like this (replace C<foo> with the column/method of your choice):
535 use overload '""' => 'foo', fallback => 1;
537 For more complex stringification, you can use an anonymous subroutine:
539 use overload '""' => sub { $_[0]->name . ", " .
540 $_[0]->address }, fallback => 1;
542 =head3 Stringifcation Example
544 Suppose we have two tables: C<Product> and C<Category>. The table
547 Product(id, Description, category)
548 Category(id, Description)
550 C<category> is a foreign key into the Category table.
552 If you have a Product object C<$obj> and write something like
556 things will not work as expected.
558 To obtain, for example, the category description, you should add this
559 method to the class defining the Category table:
561 use overload "" => sub {
564 return $self->Description;
567 =head2 Disconnecting cleanly
569 If you find yourself quitting an app with Control-C a lot during
570 development, you might like to put the following signal handler in
571 your main database class to make sure it disconnects cleanly:
574 __PACKAGE__->storage->disconnect;
577 =head2 Schema import/export
579 This functionality requires you to have L<SQL::Translator> (also known as
580 "SQL Fairy") installed.
582 To create a DBIx::Class schema from an existing database:
585 --to DBIx::Class::File
586 --prefix "MySchema" > MySchema.pm
588 To create a MySQL database from an existing L<DBIx::Class> schema, convert the
589 schema to MySQL's dialect of SQL:
591 sqlt --from SQL::Translator::Parser::DBIx::Class
593 --DBIx::Class "MySchema.pm" > Schema1.sql
595 And import using the mysql client:
597 mysql -h "host" -D "database" -u "user" -p < Schema1.sql
599 =head2 Easy migration from class-based to schema-based setup
601 You want to start using the schema-based approach to L<DBIx::Class>
602 (see L<SchemaIntro.pod>), but have an established class-based setup with lots
603 of existing classes that you don't want to move by hand. Try this nifty script
609 my $schema = MyDB->schema_instance;
611 my $translator = SQL::Translator->new(
612 debug => $debug || 0,
613 trace => $trace || 0,
614 no_comments => $no_comments || 0,
615 show_warnings => $show_warnings || 0,
616 add_drop_table => $add_drop_table || 0,
617 validate => $validate || 0,
619 'DBIx::Schema' => $schema,
622 'prefix' => 'My::Schema',
626 $translator->parser('SQL::Translator::Parser::DBIx::Class');
627 $translator->producer('SQL::Translator::Producer::DBIx::Class::File');
629 my $output = $translator->translate(@args) or die
630 "Error: " . $translator->error;
634 You could use L<Module::Find> to search for all subclasses in the MyDB::*
635 namespace, which is currently left as an exercise for the reader.
637 =head2 Schema versioning
639 The following example shows simplistically how you might use DBIx::Class to
640 deploy versioned schemas to your customers. The basic process is as follows:
646 Create a DBIx::Class schema
658 Modify schema to change functionality
662 Deploy update to customers
666 =head3 Create a DBIx::Class schema
668 This can either be done manually, or generated from an existing database as
669 described under C<Schema import/export>.
671 =head3 Save the schema
673 Use C<sqlt> to transform your schema into an SQL script suitable for your
674 customer's database. E.g. for MySQL:
676 sqlt --from SQL::Translator::Parser::DBIx::Class
678 --DBIx::Class "MySchema.pm" > Schema1.mysql.sql
680 If you need to target databases from multiple vendors, just generate an SQL
681 script suitable for each. To support PostgreSQL too:
683 sqlt --from SQL::Translator::DBIx::Class
685 --DBIx::Class "MySchema.pm" > Schema1.pgsql.sql
687 =head3 Deploy to customers
689 There are several ways you could deploy your schema. These are probably
690 beyond the scope of this recipe, but might include:
696 Require customer to apply manually using their RDBMS.
700 Package along with your app, making database dump/schema update/tests
701 all part of your install.
705 =head3 Modify the schema to change functionality
707 As your application evolves, it may be necessary to modify your schema to
708 change functionality. Once the changes are made to your schema in DBIx::Class,
709 export the modified schema as before, taking care not to overwrite the original:
711 sqlt --from SQL::Translator::DBIx::Class
713 --DBIx::Class "Anything.pm" > Schema2.mysql.sql
715 Next, use sqlt-diff to create an SQL script that will update the customer's
718 sqlt-diff --to MySQL Schema1=MySQL Schema2=MySQL > SchemaUpdate.mysql.sql
720 =head3 Deploy update to customers
722 The schema update can be deployed to customers using the same method as before.
724 =head2 Setting limit dialect for SQL::Abstract::Limit
726 In some cases, SQL::Abstract::Limit cannot determine the dialect of the remote
727 SQL-server by looking at the database-handle. This is a common problem when
728 using the DBD::JDBC, since the DBD-driver only know that in has a Java-driver
729 available, not which JDBC-driver the Java component has loaded.
730 This specifically sets the limit_dialect to Microsoft SQL-server (Se more names
731 in SQL::Abstract::Limit -documentation.
733 __PACKAGE__->storage->sql_maker->limit_dialect('mssql');
735 The JDBC-bridge is one way of getting access to a MSSQL-server from a platform
736 that Microsoft doesn't deliver native client libraries for. (e.g. Linux)
738 =head2 Setting quotes for the generated SQL.
740 If the database contains columnames with spaces and/or reserved words, the
741 SQL-query needs to be quoted. This is done using:
743 __PACKAGE__->storage->sql_maker->quote_char([ qw/[ ]/] );
744 __PACKAGE__->storage->sql_maker->name_sep('.');
746 The first sets the quotesymbols. If the quote i "symmetric" as " or '
748 __PACKAGE__->storage->sql_maker->quote_char('"');
750 is enough. If the left quote differs form the right quote, the first
751 notation should be used. name_sep needs to be set to allow the
752 SQL generator to put the quotes the correct place.
754 =head2 Overloading methods
756 L<DBIx::Class> uses the L<Class::C3> package, which provides for redispatch of
757 method calls. You have to use calls to C<next::method> to overload methods.
758 More information on using L<Class::C3> with L<DBIx::Class> can be found in
759 L<DBIx::Class::Manual::Component>.
761 =head3 Changing one field whenever another changes
763 For example, say that you have three columns, C<id>, C<number>, and
764 C<squared>. You would like to make changes to C<number> and have
765 C<squared> be automagically set to the value of C<number> squared.
766 You can accomplish this by overriding C<store_column>:
769 my ( $self, $name, $value ) = @_;
770 if ($name eq 'number') {
771 $self->squared($value * $value);
773 $self->next::method($name, $value);
776 Note that the hard work is done by the call to C<next::method>, which
777 redispatches your call to store_column to the superclass(es).
779 =head3 Automatically creating related objects
781 You might have a class C<Artist> which has many C<CD>s. Further, you
782 want to create a C<CD> object every time you insert an C<Artist> object.
783 You can accomplish this by overriding C<insert> on your objects:
786 my ( $self, @args ) = @_;
787 $self->next::method(@args);
788 $self->cds->new({})->fill_from_artist($self)->insert;
792 where C<fill_from_artist> is a method you specify in C<CD> which sets
793 values in C<CD> based on the data in the C<Artist> object you pass in.
795 =head2 Debugging DBIx::Class objects with Data::Dumper
797 L<Data::Dumper> can be a very useful tool for debugging, but sometimes it can
798 be hard to find the pertinent data in all the data it can generate.
799 Specifically, if one naively tries to use it like so,
803 my $cd = $schema->resultset('CD')->find(1);
806 several pages worth of data from the CD object's schema and result source will
807 be dumped to the screen. Since usually one is only interested in a few column
808 values of the object, this is not very helpful.
810 Luckily, it is possible to modify the data before L<Data::Dumper> outputs
811 it. Simply define a hook that L<Data::Dumper> will call on the object before
812 dumping it. For example,
819 result_source => undef,
827 local $Data::Dumper::Freezer = '_dumper_hook';
829 my $cd = $schema->resultset('CD')->find(1);
831 # dumps $cd without its ResultSource
833 If the structure of your schema is such that there is a common base class for
834 all your table classes, simply put a method similar to C<_dumper_hook> in the
835 base class and set C<$Data::Dumper::Freezer> to its name and L<Data::Dumper>
836 will automagically clean up your data before printing it. See
837 L<Data::Dumper/EXAMPLES> for more information.
839 =head2 Retrieving a row object's Schema
841 It is possible to get a Schema object from a row object like so,
843 my $schema = $cd->result_source->schema;
844 my $artist_rs = $schema->resultset('Artist');
847 This can be useful when you don't want to pass around a Schema object to every
852 When you enable L<DBIx::Class::Storage>'s debugging it prints the SQL
853 executed as well as notifications of query completion and transaction
854 begin/commit. If you'd like to profile the SQL you can subclass the
855 L<DBIx::Class::Storage::Statistics> class and write your own profiling
858 package My::Profiler;
861 use base 'DBIx::Class::Storage::Statistics';
863 use Time::HiRes qw(time);
872 print "Executing $sql: ".join(', ', @params)."\n";
881 printf("Execution took %0.4f seconds.\n", time() - $start);
887 You can then install that class as the debugging object:
889 __PACKAGE__->storage()->debugobj(new My::Profiler());
890 __PACKAGE__->storage()->debug(1);
892 A more complicated example might involve storing each execution of SQL in an
900 my $elapsed = time() - $start;
901 push(@{ $calls{$sql} }, {
907 You could then create average, high and low execution times for an SQL
908 statement and dig down to see if certain parameters cause aberrant behavior.
910 =head2 Getting the value of the primary key for the last database insert
912 AKA getting last_insert_id
914 If you are using PK::Auto, this is straightforward:
916 my $foo = $rs->create(\%blah);
918 my $id = $foo->id; # foo->my_primary_key_field will also work.
920 If you are not using autoincrementing primary keys, this will probably
921 not work, but then you already know the value of the last primary key anyway.
923 =head2 Dynamic Sub-classing DBIx::Class proxy classes
924 (AKA multi-class object inflation from one table)
926 L<DBIx::Class> classes are proxy classes, therefore some different techniques
927 need to be employed for more than basic subclassing. In this example we have
928 a single user table that carries a boolean bit for admin. We would like
929 like to give the admin users objects(L<DBIx::Class::Row>) the same methods as
930 a regular user but also special admin only methods. It doesn't make sense to
931 create two seperate proxy-class files for this. We would be copying all the
932 user methods into the Admin class. There is a cleaner way to accomplish this.
934 Overriding the C<inflate_results()> method within the User proxy-class gives
935 us the effect we want. This method is called by L<DBIx::Class::ResultSet> when
936 inflating a result from storage. So we grab the object being returned, inspect
937 the values we are looking for, bless it if it's an admin object, and then
938 return it. Running the test file below will confirm this works.
944 use base qw/DBIx::Class::Schema/;
946 __PACKAGE__->load_classes(qw/User/);
949 B<Proxy-Class definitions>
951 package DB::Schema::User;
955 use base qw/DBIx::Class/;
957 ### Defined what our admin class is for ensure_class_loaded
958 my $admin_class = __PACKAGE__ . '::Admin';
960 __PACKAGE__->load_components(qw/PK::Auto Core/);
962 __PACKAGE__->table('users');
964 __PACKAGE__->add_columns(qw/user_id email password
965 firstname lastname active
968 __PACKAGE__->set_primary_key('user_id');
972 my $ret = $self->next::method(@_);
973 if( $ret->admin ) {### If this is an admin rebless for extra functions
974 $self->ensure_class_loaded( $admin_class );
975 bless $ret, $admin_class;
981 print "I am a regular user.\n";
986 package DB::Schema::User::Admin;
990 use base qw/DB::Schema::User/;
994 print "I am an admin.\n";
1000 print "I am doing admin stuff\n";
1004 B<Test File> test.pl
1010 my $user_data = { email => 'someguy@place.com',
1011 password => 'pass1',
1014 my $admin_data = { email => 'someadmin@adminplace.com',
1015 password => 'pass2',
1018 my $schema = DB::Schema->connection('dbi:Pg:dbname=test');
1020 $schema->resultset('User')->create( $user_data );
1021 $schema->resultset('User')->create( $admin_data );
1023 ### Now we search for them
1024 my $user = $schema->resultset('User')->single( $user_data );
1025 my $admin = $schema->resultset('User')->single( $admin_data );
1027 print ref $user, "\n";
1028 print ref $admin, "\n";
1030 print $user->password , "\n"; # pass1
1031 print $admin->password , "\n";# pass2; inherited from User
1032 print $user->hello , "\n";# I am a regular user.
1033 print $admin->hello, "\n";# I am an admin.
1035 ### The statement below will NOT print
1036 print "I can do admin stuff\n" if $user->can('do_admin_stuff');
1037 ### The statement below will print
1038 print "I can do admin stuff\n" if $admin->can('do_admin_stuff');