1DBIx::SearchBuilder::ReUcsoerrd(C3o)ntributed Perl DocumDeBnItxa:t:iSoenarchBuilder::Record(3)
2
3
4

NAME

6       DBIx::SearchBuilder::Record - Superclass for records loaded by
7       SearchBuilder
8

SYNOPSIS

10         package MyRecord;
11         use base qw/DBIx::SearchBuilder::Record/;
12
13         sub _Init {
14             my $self       = shift;
15             my $DBIxHandle = shift;  # A DBIx::SearchBuilder::Handle::foo object for your database
16
17             $self->_Handle($DBIxHandle);
18             $self->Table("Users");
19         }
20
21         # Tell Record what the primary keys are
22         sub _PrimaryKeys {
23             return ['id'];
24         }
25
26         # Preferred and most efficient way to specify fields attributes in a derived
27         # class, used by the autoloader to construct Attrib and SetAttrib methods.
28
29         # read: calling $Object->Foo will return the value of this record's Foo column
30         # write: calling $Object->SetFoo with a single value will set Foo's value in
31         #        both the loaded object and the database
32         sub _ClassAccessible {
33             {
34                 Tofu => { 'read' => 1, 'write' => 1 },
35                 Maz  => { 'auto' => 1, },
36                 Roo => { 'read' => 1, 'auto' => 1, 'public' => 1, },
37             };
38         }
39
40         # A subroutine to check a user's password without returning the current value
41         # For security purposes, we didn't expose the Password method above
42         sub IsPassword {
43             my $self = shift;
44             my $try  = shift;
45
46             # note two __s in __Value.  Subclasses may muck with _Value, but
47             # they should never touch __Value
48
49             if ( $try eq $self->__Value('Password') ) {
50                 return (1);
51             }
52             else {
53                 return (undef);
54             }
55         }
56
57         # Override DBIx::SearchBuilder::Create to do some checking on create
58         sub Create {
59             my $self   = shift;
60             my %fields = (
61                 UserId   => undef,
62                 Password => 'default',    #Set a default password
63                 @_
64             );
65
66             # Make sure a userid is specified
67             unless ( $fields{'UserId'} ) {
68                 die "No userid specified.";
69             }
70
71             # Get DBIx::SearchBuilder::Record->Create to do the real work
72             return (
73                 $self->SUPER::Create(
74                     UserId   => $fields{'UserId'},
75                     Password => $fields{'Password'},
76                     Created  => time
77                 )
78             );
79         }
80

DESCRIPTION

82       DBIx::SearchBuilder::Record is designed to work with
83       DBIx::SearchBuilder.
84
85   What is it trying to do.
86       DBIx::SearchBuilder::Record abstracts the agony of writing the common
87       and generally simple SQL statements needed to serialize and De-
88       serialize an object to the database.  In a traditional system, you
89       would define various methods on your object 'create', 'find', 'modify',
90       and 'delete' being the most common.  In each method you would have a
91       SQL statement like:
92
93         select * from table where value='blah';
94
95       If you wanted to control what data a user could modify, you would have
96       to do some special magic to make accessors do the right thing. Etc.
97       The problem with this approach is that in a majority of the cases, the
98       SQL is incredibly simple and the code from one method/object to the
99       next was basically the same.
100
101       <trumpets>
102
103       Enter, DBIx::SearchBuilder::Record.
104
105       With Record, you can in the simple case, remove all of that code and
106       replace it by defining two methods and inheriting some code.  It's
107       pretty simple, and incredibly powerful.  For more complex cases, you
108       can do more complicated things by overriding certain methods.  Let's
109       stick with the simple case for now.
110
111       The two methods in question are "_Init" and "_ClassAccessible". All
112       they really do are define some values and send you on your way.  As you
113       might have guessed the '_' means that these are private methods.  They
114       will get called by your record object's constructor.
115
116       '_Init'
117           Defines what table we are talking about, and set a variable to
118           store the database handle.
119
120       '_ClassAccessible
121           Defines what operations may be performed on various data selected
122           from the database.  For example you can define fields to be
123           mutable, or immutable, there are a few other options but I don't
124           understand what they do at this time.
125
126       And really, that's it.  So let's have some sample code.
127
128   An Annotated Example
129       The example code below makes the following assumptions:
130
131       •   The database is 'postgres',
132
133       •   The host is 'reason',
134
135       •   The login name is 'mhat',
136
137       •   The database is called 'example',
138
139       •   The table is called 'simple',
140
141       •   The table looks like so:
142
143                 id     integer     not NULL,   primary_key(id),
144                 foo    varchar(10),
145                 bar    varchar(10)
146
147       First, let's define our record class in a new module named "Simple.pm".
148
149         000: package Simple;
150         001: use DBIx::SearchBuilder::Record;
151         002: @ISA = (DBIx::SearchBuilder::Record);
152
153       This should be pretty obvious, name the package, import ::Record and
154       then define ourself as a subclass of ::Record.
155
156         003:
157         004: sub _Init {
158         005:   my $this   = shift;
159         006:   my $handle = shift;
160         007:
161         008:   $this->_Handle($handle);
162         009:   $this->Table("Simple");
163         010:
164         011:   return ($this);
165         012: }
166
167       Here we set our handle and table name. While it's not obvious so far,
168       we'll see later that $handle (line: 006) gets passed via
169       "::Record::new" when a new instance is created.  That's actually an
170       important concept: the DB handle is not bound to a single object but
171       rather, it is shared across objects.
172
173         013:
174         014: sub _ClassAccessible {
175         015:   {
176         016:     Foo => { 'read'  => 1 },
177         017:     Bar => { 'read'  => 1, 'write' => 1  },
178         018:     Id  => { 'read'  => 1 }
179         019:   };
180         020: }
181
182       What's happening might be obvious, but just in case this method is
183       going to return a reference to a hash. That hash is where our columns
184       are defined, as well as what type of operations are acceptable.
185
186         021:
187         022: 1;
188
189       Like all perl modules, this needs to end with a true value.
190
191       Now, on to the code that will actually *do* something with this object.
192       This code would be placed in your Perl script.
193
194         000: use DBIx::SearchBuilder::Handle;
195         001: use Simple;
196
197       Use two packages, the first is where I get the DB handle from, the
198       latter is the object I just created.
199
200         002:
201         003: my $handle = DBIx::SearchBuilder::Handle->new();
202         004:    $handle->Connect( 'Driver'   => 'Pg',
203         005:                    'Database' => 'test',
204         006:                    'Host'     => 'reason',
205         007:                    'User'     => 'mhat',
206         008:                    'Password' => '');
207
208       Creates a new DBIx::SearchBuilder::Handle, and then connects to the
209       database using that handle.  Pretty straight forward, the password ''
210       is what I use when there is no password.  I could probably leave it
211       blank, but I find it to be more clear to define it.
212
213         009:
214         010: my $s = Simple->new($handle);
215         011:
216         012: $s->LoadById(1);
217
218       LoadById is one of four 'LoadBy' methods,  as the name suggests it
219       searches for an row in the database that has id='0'.  ::SearchBuilder
220       has, what I think is a bug, in that it current requires there to be an
221       id field. More reasonably it also assumes that the id field is unique.
222       LoadById($id) will do undefined things if there is >1 row with the same
223       id.
224
225       In addition to LoadById, we also have:
226
227       LoadByCol
228           Takes two arguments, a column name and a value.  Again, it will do
229           undefined things if you use non-unique things.
230
231       LoadByCols
232           Takes a hash of columns=>values and returns the *first* to match.
233           First is probably lossy across databases vendors.
234
235       LoadFromHash
236           Populates this record with data from a DBIx::SearchBuilder.  I'm
237           currently assuming that DBIx::SearchBuilder is what we use in cases
238           where we expect > 1 record.  More on this later.
239
240       Now that we have a populated object, we should do something with it!
241       ::Record automagically generates accessos and mutators for us, so all
242       we need to do is call the methods.  Accessors are named <Field>(), and
243       Mutators are named Set<Field>($).  On to the example, just appending
244       this to the code from the last example.
245
246         013:
247         014: print "ID  : ", $s->Id(),  "\n";
248         015: print "Foo : ", $s->Foo(), "\n";
249         016: print "Bar : ", $s->Bar(), "\n";
250
251       That's all you have to to get the data. Now to change the data!
252
253         017:
254         018: $s->SetBar('NewBar');
255
256       Pretty simple! That's really all there is to it.  Set<Field>($) returns
257       a boolean and a string describing the problem.  Let's look at an
258       example of what will happen if we try to set a 'Id' which we previously
259       defined as read only.
260
261         019: my ($res, $str) = $s->SetId('2');
262         020: if (! $res) {
263         021:   ## Print the error!
264         022:   print "$str\n";
265         023: }
266
267       The output will be:
268
269         >> Immutable field
270
271       Currently Set<Field> updates the data in the database as soon as you
272       call it.  In the future I hope to extend ::Record to better support
273       transactional operations, such that updates will only happen when "you"
274       say so.
275
276       Finally, adding a removing records from the database.  ::Record
277       provides a Create method which simply takes a hash of key=>value pairs.
278       The keys exactly   map to database fields.
279
280         023: ## Get a new record object.
281         024: $s1 = Simple->new($handle);
282         025: $s1->Create('Id'  => 4,
283         026:             'Foo' => 'Foooooo',
284         027:             'Bar' => 'Barrrrr');
285
286       Poof! A new row in the database has been created!  Now let's delete the
287       object!
288
289         028:
290         029: $s1 = undef;
291         030: $s1 = Simple->new($handle);
292         031: $s1->LoadById(4);
293         032: $s1->Delete();
294
295       And it's gone.
296
297       For simple use, that's more or less all there is to it.  In the future,
298       we hope to expand this how-to to discuss using container classes,
299       overloading, etc.
300

METHOD NAMING

302       Each method has a lower case alias; '_' is used to separate words.  For
303       example, the method "_PrimaryKeys" has the alias "_primary_keys".
304

METHODS

306   new
307       Instantiate a new record object.
308
309   id
310       Returns this row's primary key.
311
312   primary_keys
313   PrimaryKeys
314       Return a hash of the values of our primary keys for this function.
315
316   _Accessible KEY MODE
317       Private method.
318
319       Returns undef unless "KEY" is accessible in "MODE" otherwise returns
320       "MODE" value
321
322   _PrimaryKeys
323       Return our primary keys. (Subclasses should override this, but our
324       default is that we have one primary key, named 'id'.)
325
326   _ClassAccessible
327       An older way to specify fields attributes in a derived class.  (The
328       current preferred method is by overriding "Schema"; if you do this and
329       don't override "_ClassAccessible", the module will generate an
330       appropriate "_ClassAccessible" based on your "Schema".)
331
332       Here's an example declaration:
333
334         sub _ClassAccessible {
335           {
336                Tofu  => { 'read'=>1, 'write'=>1 },
337                Maz   => { 'auto'=>1, },
338                Roo   => { 'read'=>1, 'auto'=>1, 'public'=>1, },
339           };
340         }
341
342   ReadableAttributes
343       Returns an array of the attributes of this class defined as "read" => 1
344       in this class' _ClassAccessible datastructure
345
346   WritableAttributes
347       Returns an array of the attributes of this class defined as "write" =>
348       1 in this class' _ClassAccessible datastructure
349
350   __Value
351       Takes a field name and returns that field's value. Subclasses should
352       never override __Value.
353
354   _Value
355       _Value takes a single column name and returns that column's value for
356       this row.  Subclasses can override _Value to insert custom access
357       control.
358
359   _Set
360       _Set takes a single column name and a single unquoted value.  It
361       updates both the in-memory value of this column and the in-database
362       copy.  Subclasses can override _Set to insert custom access control.
363
364   _Canonicalize PARAMHASH
365       This routine massages an input value (VALUE) for FIELD into something
366       that's going to be acceptable.
367
368       Takes
369
370       FIELD
371       VALUE
372       FUNCTION
373
374       Takes:
375
376       FIELD
377       VALUE
378       FUNCTION
379
380       Returns a replacement VALUE.
381
382   _Validate FIELD VALUE
383       Validate that VALUE will be an acceptable value for FIELD.
384
385       Currently, this routine does nothing whatsoever.
386
387       If it succeeds (which is always the case right now), returns true.
388       Otherwise returns false.
389
390   TruncateValue  KEY VALUE
391       Truncate a value that's about to be set so that it will fit inside the
392       database' s idea of how big the column is.
393
394       (Actually, it looks at SearchBuilder's concept of the database, not
395       directly into the db).
396
397   _Object
398       _Object takes a single column name and an array reference.  It creates
399       new object instance of class specified in _ClassAccessable structure
400       and calls LoadById on recently created object with the current column
401       value as argument. It uses the array reference as the object
402       constructor's arguments.  Subclasses can override _Object to insert
403       custom access control or define default constructor arguments.
404
405       Note that if you are using a "Schema" with a "REFERENCES" field, this
406       is unnecessary: the method to access the column's value will
407       automatically turn it into the appropriate object.
408
409   Load
410       Takes a single argument, $id. Calls LoadById to retrieve the row whose
411       primary key is $id
412
413   LoadByCol
414       Takes two arguments, a column and a value. The column can be any table
415       column which contains unique values.  Behavior when using a non-unique
416       value is undefined
417
418   LoadByCols
419       Takes a hash of columns and values. Loads the first record that matches
420       all keys.
421
422       The hash's keys are the columns to look at.
423
424       The hash's values are either: scalar values to look for OR has
425       references which contain 'operator' and 'value'
426
427   LoadById
428       Loads a record by its primary key. Your record class must define a
429       single primary key column.
430
431   LoadByPrimaryKeys
432       Like LoadById with basic support for compound primary keys.
433
434   LoadFromHash
435       Takes a hashref, such as created by DBIx::SearchBuilder and populates
436       this record's loaded values hash.
437
438   _LoadFromSQL QUERYSTRING @BIND_VALUES
439       Load a record as the result of an SQL statement
440
441   Create
442       Takes an array of key-value pairs and drops any keys that aren't known
443       as columns for this recordtype
444
445   Delete
446       Delete this record from the database. On failure return a
447       Class::ReturnValue with the error. On success, return 1;
448
449   Table
450       Returns or sets the name of the current Table
451
452   QuotedTableName
453       Returns the name of current Table, or the table provided as an
454       argument, including any quoting
455        based on yje Handle's QuoteTableNames flag and driver method.
456
457   _Handle
458       Returns or sets the current DBIx::SearchBuilder::Handle object
459
460
461
462perl v5.36.3                      2023-12-04    DBIx::SearchBuilder::Record(3)
Impressum