- Clean up indentation in Manual
[dbsrgits/DBIx-Class.git] / lib / DBIx / Class / Manual / Cookbook.pod
1 =head1 NAME 
2
3 DBIx::Class::Manual::Cookbook - Miscellaneous recipes
4
5 =head1 RECIPES
6
7 =head2 Complex searches
8
9 Sometimes you need to formulate a query using specific operators:
10
11     my @albums = MyApp::DB::Album->search({
12         artist => { 'like', '%Lamb%' },
13         title  => { 'like', '%Fear of Fours%' },
14     });
15
16 This results in something like the following C<WHERE> clause:
17
18     WHERE artist LIKE '%Lamb%' AND title LIKE '%Fear of Fours%'
19
20 Other queries might require slightly more complex logic:
21
22     my @albums = MyApp::DB::Album->search({
23         -or => [
24             -and => [
25                 artist => { 'like', '%Smashing Pumpkins%' },
26                 title  => 'Siamese Dream',
27             ],
28             artist => 'Starchildren',
29         ],
30     });
31
32 This results in the following C<WHERE> clause:
33
34     WHERE ( artist LIKE '%Smashing Pumpkins%' AND title = 'Siamese Dream' )
35           OR artist = 'Starchildren'
36
37 For more information on generating complex queries, see
38 L<SQL::Abstract/WHERE CLAUSES>.
39
40 =head2 Disconnecting cleanly
41
42 If you find yourself quitting an app with Control-C a lot during
43 development, you might like to put the following signal handler in
44 your main database class to make sure it disconnects cleanly:
45
46     $SIG{INT} = sub {
47         __PACKAGE__->storage->dbh->disconnect;
48     };
49
50 =head2 Using joins and prefetch
51
52 See L<DBIx::Class::ResultSet/ATTRIBUTES>.
53
54 =head2 Transactions
55
56 As of version 0.04001, there is improved transaction support in
57 L<DBIx::Class::Storage::DBI>. Here is an example of the recommended
58 way to use it:
59
60     my $genus = Genus->find(12);
61     eval {
62         MyDB->txn_begin;
63         $genus->add_to_species({ name => 'troglodyte' });
64         $genus->wings(2);
65         $genus->update;
66         cromulate($genus); # Can have a nested transation
67         MyDB->txn_commit;
68     };
69     if ($@) {
70         # Rollback might fail, too
71         eval {
72             MyDB->txn_rollback
73         };
74     }
75
76 Currently, a nested commit will do nothing and a nested rollback will
77 die. The code at each level must be sure to call rollback in the case
78 of an error, to ensure that the rollback will propagate to the top
79 level and be issued. Support for savepoints and for true nested
80 transactions (for databases that support them) will hopefully be added
81 in the future.
82
83 =head2 Many-to-many relationships
84
85 This is not as easy as it could be, but it's possible. Here's an
86 example to illustrate:
87
88     # Set up inherited connection information
89     package MyApp::DBIC; 
90     use base qw/DBIx::Class/;
91
92     __PACKAGE__->load_components(qw/PK::Auto::SQLite Core DB/);
93     __PACKAGE__->connection(...);
94
95     # Set up a class for the 'authors' table
96     package MyApp::DBIC::Author;
97     use base qw/MyApp::DBIC/;
98
99     __PACKAGE__->table('authors');
100     __PACKAGE__->add_columns(qw/authID first_name last_name/);
101     __PACKAGE__->set_primary_key(qw/authID/);
102
103     # Define relationship to the link table
104     __PACKAGE__->has_many('b2a' => 'MyApp::DBIC::Book2Author', 'authID');
105
106     # Create the accessor for books from the Author class
107     sub books {
108       my ($self) = @_;
109       return MyApp::DBIC::Book->search(
110         { 'b2a.authID' => $self->authID }, # WHERE clause
111         { join => 'b2a' } # join condition (part of search attrs)
112         # 'b2a' refers to the relationship named earlier in the Author class.
113         # 'b2a.authID' refers to the authID column of the b2a relationship,
114         # which becomes accessible in the search by being joined.  
115       );
116     }
117
118     # Define the link table class
119     package MyApp::DBIC::Book2Author;
120     use base qw/MyApp::DBIC/;
121
122     __PACKAGE__->table('book2author');
123     __PACKAGE__->add_columns(qw/bookID authID/);
124     __PACKAGE__->set_primary_key(qw/bookID authID/);
125
126     __PACKAGE__->belongs_to('authID' => 'MyApp::DBIC::Author');
127     __PACKAGE__->belongs_to('bookID' => 'MyApp::DBIC::Book');
128
129     package MyApp::DBIC::Book;
130     use base qw/MyApp::DBIC/;
131
132     __PACKAGE__->table('books');
133     __PACKAGE__->add_columns(qw/bookID title edition isbn publisher year/);
134     __PACKAGE__->set_primary_key(qw/bookID/);
135     
136     __PACKAGE__->has_many('b2a' => 'MyApp::DBIC::Book2Author', 'bookID');
137
138
139     # Returns an author record where the bookID field of the
140     # book2author table equals the bookID of the books (using the
141     # bookID relationship table)
142     sub authors {
143         my ($self) = @_;
144         return MyApp::DBIC::Author->search(
145             { 'b2a.bookID' => $self->bookID }, # WHERE clause
146             { join => 'b2a' } # JOIN condition
147         ); 
148     }
149
150 =head2 Setting default values
151
152 It's as simple as overriding the C<new> method. Note the use of
153 C<next::method>.
154
155     sub new {
156         my ( $class, $attrs ) = @_;
157
158         $attrs->{foo} = 'bar' unless defined $attrs->{foo};
159
160         $class->next::method($attrs);
161     }
162
163 =head2 Stringification
164
165 Employ the standard stringification technique by using the C<overload>
166 module. Replace C<foo> with the column/method of your choice.
167
168     use overload '""' => 'foo', fallback => 1;
169
170 =cut