|
Friday, October 23, 2009
Core JavaServer Faces, 2nd Edition
Searching Strings for Specific Endings/Beginnings
Searching Strings for Specific Endings/Beginnings
The endswith(suffix, [, start, [,end]]) and startswith(prefix, [, start, [,end]]) methods provide a simple and safe way to determine whether a string begins or ends with a specific prefix or suffix, respectively. The first argument is a string used to compare to the prefix or suffix of the string. The endswith and startswith methods are dynamic enough for you to limit the search to within a specific range of the string using the start and/or end arguments. Note The endswith and startswith methods are extremely useful when parsing file lists for extensions or filenames. import os end_str.py Python file: comp_str.py Output from end_str.py code |
Chapter 1: Introduction to Software Patterns
| ||||||||||
Chapter 1: Introduction to Software Patterns
Overview
Software patterns are reusable solutions to recurring problems that we encounter during software development. Because this book is all about software patterns, they are simply referred to as patterns throughout.
What makes a bright, experienced programmer much more productive than a bright, but inexperienced programmer? Experience. Experience gives programmers a wealth of wisdom. As programmers gain experience, they recognize the similarity of new problems to those they have solved in the past. With even more experience, they recognize that solutions to similar problems follow recurring patterns. With knowledge of these patterns, experienced programmers can recognize a problem to which specific patterns apply and immediately determine the solution without having to stop to analyze the problem first.
When a programmer discovers a pattern, it’s just an insight. In most cases, to go from an unverbalized insight to a well-thought-out idea that the programmer can clearly articulate is surprisingly difficult. It’s also an extremely valuable step. When we understand a pattern well enough to put it into words, we are able to intelligently combine it with other patterns. More important, once put into words, a pattern can be used in discussions among programmers who know the pattern. Such discussions allow programmers to more effectively collaborate and combine their wisdom. They can also help avoid the situation in which programmers argue over different solutions to a problem but find that they were actually thinking of the same solution, only expressing it in different ways.
Putting a pattern into words has an additional benefit for less experienced programmers who have not yet discovered the pattern. Once a pattern has been put into words, more experienced programmers can teach it to programmers who aren’t familiar with the pattern.
The intended value of this book is that it provide experienced programmers with a common vocabulary to discuss patterns. It should also allow programmers who have not yet discovered a pattern to learn about the pattern.
Although this book includes a substantial breadth of patterns, you may discover additional patterns yourself. Some patterns that you discover may be highly specialized and of interest only to a small number of people. Other patterns may be of broad interest and worthy of inclusion in a future volume of this book. If you wish to communicate such a pattern to this book’s author, you may send an email to mgrand@mindspring.com.
The patterns cataloged in this book convey constructive ways for organizing parts of the software development cycle. There are, however, nonconstructive patterns that can recur in programs. These are called AntiPatterns because they can cancel out the benefits of patterns. This book does not attempt to catalog AntiPatterns, for the subject is well covered in other books.
Patterns and AntiPatterns are similar but fundamentally different. The point of a pattern is to recognize when you have the opportunity to apply a good solution to a problem. The point of an AntiPattern is to recognize the nature of a bad situation and suggest solutions.
Section 11.3. BusyBox Operation
11.3. BusyBox OperationWhen you build BusyBox, you end up with a binary called, you guessed it, busybox. BusyBox can be invoked from the binary name itself, but it is more usually launched via a symlink. When BusyBox is invoked without command line parameters, it produces a list of the functions that were enabled via the configuration. Listing 11-3 shows such an output (it has been formatted slightly to fit the page width). Listing 11-3. BusyBox Usage
From Listing 11-3, you can see the list of functions that are enabled in this BusyBox build. They are listed in alphabetical order from ash (a shell optimized for small memory footprint) to zcat, a utility used to decompress the contents of a compressed file. This is the default set of utilities enabled in this particular BusyBox snapshot. To invoke a particular function, execute busybox with one of the defined functions passed on the command line. Thus, to display a listing of files in the current directory, execute this command: [root@coyote]# ./busybox lsAnother important message from the BusyBox usage message in Listing 11-3 is the short description of the program. It describes BusyBox as a multicall binary, combining many common utilities into a single executable. This is the purpose of the symlinks mentioned earlier. BusyBox was intended to be invoked by a symlink named for the function it will perform. This removes the burden of having to type a two-word command to invoke a given function, and it presents the user with a set of familiar commands for the similarly named utilities. Listings 11-4 and 11-5 should make this clear. Listing 11-4. BusyBox Symlink StructureTop Level
Listing 11-4 shows the target directory structure as built by the BusyBox package via the make install command. The executable busybox file is found in the /bin directory, and symlinks have been populated throughout the rest of the structure pointing back to /bin/busybox. Listing 11-5 expands on the directory structure of Listing 11-4. Listing 11-5. BusyBox Symlink StructureTree Detail
The output of Listing 11-5 has been significantly truncated for readability and to avoid a three-page listing. Each line containing an ellipsis (...) indicates that this listing has been pruned to show only the first few and last few entries of that given directory. In actuality, more than 100 symlinks can be populated in these directories, depending on what functionality you have enabled using the BusyBox configuration utility. Notice the busybox executable itself, the second entry from the /bin directory. Also in the /bin directory are symlinks pointing back to busybox for ash, cat, cp... all the way to zcat. Again, the entries between cp and zcat have been omitted from this listing for readability. With this symlink structure, the user simply enters the actual name of the utility to invoke its functionality. For example, to configure a network interface using the busybox ifconfig utility, the user might enter a command similar to this: $ ifconfig eth1 192.168.1.14This would invoke the busybox executable through the ifconfig symlink. BusyBox examines how it was calledthat is, it reads argv[0] to determine what functionality is executed. 11.3.1. BusyBox InitNotice the symlink in Listing 11-5 called init. In Chapter 6 "System Initialization," you learned about the init program and its role in system initialization. Recall that the kernel attempts to execute a program called /sbin/init as the last step in kernel initialization. There is no reason why BusyBox can't emulate the init functionality, and that's exactly how the system illustrated by Listing 11-5 is configured. BusyBox handles the init functionality. BusyBox handles system initialization differently from standard System V init. A Linux system using the System V (SysV) initialization as described in Chapter 6 requires an inittab file accessible in the /etc directory. BusyBox also reads an inittab file, but the syntax of the inittab file is different. In general, you should not need to use an inittab if you are using BusyBox. I agree with the BusyBox man page: If you need run levels, use System V initialization.[2]
Let's see what this looks like on an embedded system. We have created a small root file system based on BusyBox. We configured BusyBox for static linking, eliminating the need for any shared libraries. Listing 11-6 contains a tree listing of this root file system. We built this small file system using the steps outlined in Chapter 9, "File Systems," Section 9.10, "Building a Simple File System." We do not detail the procedure again here. The files in our simple file system are those shown in Listing 11-6. Listing 11-6. Minimal BusyBox Root File System
This BusyBox-based root file system occupies little more than the size needed for busybox itself. In this configuration, using static linking and supporting nearly 100 utilities, the BusyBox executable came in at less than 1MB: # ls -l /bin/busybox Now let's see how this system behaves. Listing 11-7 captures the console output on power-up on this BusyBox-based embedded system. Listing 11-7. BusyBox Default Startup
The example of Listing 11-7 was run on an embedded board configured for NFS root mount. We export a directory on our workstation that contains the simple file system image detailed in Listing 11-6. As oneof the final steps in the boot process, the Linux kernel on our target board mounts a root file system via NFS. When the kernel attempts to execute /sbin/init, it fails because there is no /sbin/init on our file system. However, as we have seen, the kernel also attempts to execute /bin/sh. In our BusyBox-configured target, this succeeds, and busybox is launched via the symlink /bin/sh on our root file system. The first thing BusyBox displays is the complaint that it can't find /etc/init.d/rcS. This is the default initialization script that BusyBox searches for. Instead of using inittab, this is the preferred method to initialize an embedded system based on BusyBox. When it has completed initialization, BusyBox displays a prompt asking the user to press Enter to activate a console. When it detects the Enter key, it executes an ash shell session waiting for user input. The final message about job control is a result of the fact that we are creating the system console on a serial terminal. The Linux kernel contains code to disable job control if it detects the console on a serial terminal. This example produced a working system, with nearly 100 Linux utilities available, including core utilities, file utilities, network support, and a reasonably capable shell. You can see that this simple package provides a powerful platform upon which to build your own system applications. Of course, it should be noted that without any support for libc and other system libraries, you would face a formidable task implementing your applications. You would have to provide support for all the usual system calls and other library functions that a typical C program relies on. Alternatively, you could statically link your applications against the libraries it depends on, but if you have more than a couple applications using this method, your applications will likely exceed the combined size of linking dynamically and having the shared libraries on your target. 11.3.2. Example rcS Initialization ScriptBefore BusyBox spawns an interactive shell, it tries to execute commands from a script called /etc/init.d/rcS, as shown in Listing 11-7. It is here where your applications come to life in a BusyBox system. A simple rcS initialization script is provided in Listing 11-8. Listing 11-8. Simple rcS BusyBox Startup Script
This simple script is mostly self-explanatory. First, it is important to mount the /proc file system on its reserved mount point, /proc. This is because many utilities get their information from the /proc file system. This is explained more fully in Chapter 9. Next we launch the system loggers as early as possible, to capture any startup problems. Following the system log daemons, we configure the local loopback interface for the system. Again, a number of traditional Linux facilities assume that a loopback interface is present, and if your system has support for sockets configured, you should enable this pseudo interface. The last thing we do before starting a shell is launch the Internet superserver xinetd. This program sits in the background listening for network requests on any configured network interfaces. For example, to initiate a telnet session to the board, xinetd intercepts the request for telnet connection and spawns a telnet server to handle the session. Instead of starting a shell, your own applications can be launched from this rcS initialization script. Listing 11-8 is a simple example of a Telnet-enabled target board running basic services such as system and kernel loggers. 11.3.3. BusyBox Target InstallationThe discussion of BusyBox installation can proceed only when you understand the use and purpose of symlinks. The BusyBox makefile contains a target called install. Executing make install creates a directory structure containing the busybox executable and a symlink tree. This environment needs to be migrated to your target embedded system's root directory, complete with the symlink tree. The symlink tree eliminates the need to type busybox command for each command. Instead, to see a listing of files in a given directory, the user need only type ls. The symlink executes busybox as described previously and invokes the ls functionality. Review Listing 11-4 and Listing 11-5 to see the symlink tree. Note that the BusyBox build system creates links only for the functionality that you have enabled via the configuration utility. The easiest way to populate your root file system with the necessary symlink farm is to let the BusyBox build system do it for you. Simply mount your root file system on your development workstation and pass a PREFIX to the BusyBox makefile. Listing 11-9 shows the procedure. Listing 11-9. Installing BusyBox on Root File System
First we mount the root file system binary image on our desired mount pointin this case, /mnt/remote, a favorite of mine. Then we invoke the BusyBox make install command, passing it a PREFIX specifying where we want the symlink tree and busybox executable file to be placed. As you can see from the listing, the makefile invokes a script called applets/install.sh to do the bulk of the work. The script walks through a file containing all the enabled BusyBox applets and creates a symlink for each one on the path we have specified using the PREFIX. The script is very chatty; it outputs a line for each symlink created. For brevity, only the first few and last few symlink announcements are displayed. The ellipsis in the listing represents those we have eliminated. The message about setuid is also displayed by the install script, to remind you that it might be necessary to make your busybox executable setuid root. This is to allow BusyBox functions that require root access to function properly even when invoked by a nonroot user. This is not strictly necessary, especially in an embedded Linux environment, where it is common to have only a root account on a system. If this is necessary for your installation, the required command (chmod +s) is shown in Listing 11-9. The result of this installation step is that the busybox binary and symlink tree are installed on our target root file system. The end result looks very similar to Listing 11-4. It is useful to note that BusyBox also has an option to enable creation of this symlink tree on the target system at runtime. This option is enabled in the BusyBox configuration and is invoked at runtime by executing busybox with the -install option. You must have the /proc file system mounted on your target system for this support to work. 11.3.4. BusyBox CommandsIn a recent BusyBox snapshot, 197 commands (also called applets) were documented in the man page. There is sufficient support for reasonably complex shell scripts, including support for Bash shell scripting. BusyBox has support for awk and sed, frequently found in Bash scripts. BusyBox supports network utilities such as ping, ifconfig, TRaceroute, and netstat. Some commands are specifically included for scripting support, including true, false, and yes. Spend a few moments perusing Appendix C, "BusyBox Commands," where you can find a summary of each BusyBox command. After you have done so, you will have a better appreciation for the capabilities of BusyBox and how it might be applicable to your own embedded Linux project. As mentioned at the beginning of this chapter, many of the BusyBox commands contain a limited subset of features and options compared to their full-featured counterparts. In general, you can get help on any given BusyBox command at runtime by invoking the command with the --help option. This produces a usage message with a brief description of each supported command option. The BusyBox gzip applet is a useful example of a BusyBox command that has support for a limited set of options. Listing 11-10 displays the output from gzip-help on a BusyBox target. Listing 11-10. BusyBox gzip Applet Usage
The BusyBox version of gzip supports just three command line options. Its full-featured counterpart contains support for more than 15 different command line options. For example, the full-featured gzip utility supports a --list option that produces compression statistics for each file on the command line. No such support exists for BusyBox gzip. This is usually not a significant limitation for embedded systems. We present this information so you can make an informed choice when deciding on BusyBox. When the full capabilities of a utility are needed, the solution is simple: Delete support for that particular utility in the BusyBox configuration and add the standard Linux utility to your target system. |
Part 1: Hibernate in a Hurry
Part 1: Hibernate in a Hurry
Our first goal is to get up to speed with Hibernate as quickly as
possible. Most of the chapters in this part are updated versions of
content from Hibernate: A Developer's Notebook
(O'Reilly), reflecting the major changes that came about with Hibernate 3.
The sample code now works with the latest versions of the tools we rely on
to provide an easy yet realistic environment for working with Hibernate.
There is also a new chapter covering the ability to use Java 5
annotations, rather than XML mapping files, to
configure Hibernate mappings.
NOTE
Of course, with any printed book about active open source
projects, things will get out of date quickly! See Appendix E for the
specific versions we discuss, and for ideas on how to cope with
changes.
Getting started and following along with the examples is even easier
in this new version of the book because we've adopted Maven to help
download many of the tools and libraries. As we hope you will see, there's
no excuse to avoid diving in and trying this stuff yourself!
Once you're comfortable with the fundamentals of Hibernate, Part 2 will demonstrate
how to tie Hibernate into some other environments to make each more
powerful than they are on their own.
All right, time to dive in….
Chapter 1. Installation and Setup
It continues to amaze me how many great, free, open source Java™ tools
are out there. When I needed a lightweight object/relational mapping service
for a JSP e-commerce project at the turn of the
millennium, I had to build my own. It evolved over the years, developed some
cool and unique features, and we've used it in a wide variety of different
contexts. But, once I discovered Hibernate, we used that for new development
instead of my own familiar system (toward which I'll cheerfully admit bias).
That should tell you how compelling it is!
If you're looking at this book, you're likely interested in a powerful
and convenient way to bridge the worlds of Java objects and relational
databases. Hibernate fills that role very nicely, without being so
complicated that learning it becomes a daunting challenge in itself. To
demonstrate that, this chapter guides you to the point where you can play
with Hibernate and see for yourself why it's so exciting.
Later chapters will look at using Hibernate as part of more complex
environments such as Spring and Stripes, as well as using it with other
databases. The goal of this first chapter is to show you how easy it is to
put together a basic, self-contained environment in which you can explore
Hibernate and do real things with it.
1.1. Getting an Ant Distribution
Although it might be surprising, the first few things you need
to get Hibernate running have nothing to do with Hibernate
itself. First, you must set up an environment in which the remaining
examples work. This will have the pleasant side effect of building a solid
foundation for any actual project you might be undertaking.
If you're not already using Ant to manage the building, testing,
running, and packaging of your Java projects, now is the time to start.
The examples in this book are Ant-driven, so you'll need a working Ant
installation to run them and experiment with variations on your own
system, which is the best way to learn.
First of all, get an Ant binary and install it.
1.1.1. Why do I care?
The examples use Apache Ant for several reasons. It's convenient
and powerful; it's one of the standard build tools for Java-based
development; it's free; and it's cross-platform. If you use Ant, the
examples will work equally well anywhere there's a Java environment,
which means readers of this book won't be frustrated or annoyed.
Fortunately, it also means we can do many more cool things with less
effort—especially since several Hibernate tools have explicit Ant
support, which I'll show you how to leverage. (I should note that these
days more complex Java projects often use Maven, which adds many other
project management capabilities. Since I had to pick one, in the spirit
of keeping things simple and true to what I find useful, I went with Ant
for these examples.)
If you are currently using Maven as a build tool, you will notice that we are using Maven's Ant Tasks to
manage dependencies from our Ant builds. Although Maven is gaining
momentum, Ant continues to be the most widely used build tool in Java
development. Every chapter's example code folder also has a Maven
pom.xml file and can be compiled
with Maven. In many cases, the Maven build file provides the same
functionality as the Ant build.xml
file by using the Maven Hibernate3 plug-in. In Chapter 12 you will find some
guidance for building and deploying Hibernate applications using
full-blown Maven, but the majority of the examples in this book focus on
Ant as a build tool, using the Maven Ant Tasks to relieve the tedium of
finding and downloading the various libraries we need, and the libraries
on which they, in turn, rely.
To take advantage of all these capabilities, you need to have Ant
installed and working on your system.
NOTE
I used to wonder why people bothered with Ant when they could
use Make. Now that I've seen how well Ant manages Java builds, I feel
lost without it.
1.1.2. How do I do that?
You can download a binary release of Ant from http://ant.apache.org/bindownload.cgi. Scroll down to
find the current release of Ant, and download the archive in a format
that's convenient for you to work with. Pick an appropriate place for it
to live, and expand the archive there. The directory into which you've
expanded the archive is referred to as ANT_HOME.
Let's say you've expanded the archive into the directory /usr/local/apache-ant-1.7.0; you may want to
create a symbolic link to make it easier to work with and to avoid the
need to change any environment configuration when you upgrade to a newer
version:
/usr/local % ln -s apache-ant-1.7.0 ant
Once Ant is situated, you need to do a couple of things to make it
work correctly. You need to add its bin directory in the distribution (in this
example, /usr/local/ant/bin) to
your command path. You also need to set the environment variable
ANT_HOME to the top-level directory you installed (in
this example, /usr/local/ant).
Details about how to perform these steps under different operating
systems can be found in the Ant manual (http://ant.apache.org/manual/) if you need
them.
Section 6.2. Defining a Persistent Enumerated Type
6.2. Defining a Persistent Enumerated Type
An enumerated type is a common and
useful programming abstraction allowing a value to be selected
from a fixed set of named choices. These were originally well represented
in Pascal, but C took such a minimal approach (essentially just letting
you assign symbolic names to interchangeable integer values) that early
Java releases reserved C's enum keyword but
declined to implement it. A better, object-oriented approach known as the
"typesafe enum pattern" evolved and was popularized in Joshua Bloch's
Effective Java. This approach required a fair
amount of boilerplate coding, but it lets you do all kinds of interesting
and powerful things. One of the many delightful innovations in the Java 5
specification was the ability to resuscitate the enum keyword as an easy way to get the power of
typesafe enumerations without all the tedious boilerplate coding, and it
provides other nifty benefits.
NOTE
C-style numeric "enumerations" still appear too often in Java.
Older parts of the Sun API contain many of
them.
Regardless of how you implement an enumerated type, you're sometimes
going to want to be able to persist such values to a database. And even
though there is now a standard way to do it in Java, Hibernate doesn't
offer any built-in support. So let's see how to implement a
UserType that can persist an enum for us.
Let's suppose we want to be able to specify whether our tracks came
from cassette tapes, vinyl, VHS tapes,
CDs, a broadcast, an Internet download site, or a
digital audio stream. (We could go really nuts and distinguish between
Internet streams and satellite radio services like Sirius or
XM, or radio versus television broadcast, but this is
plenty to demonstrate the important ideas.)
Without any consideration of persistence, our typesafe enumeration
class might look something like Example 6-1. (The JavaDoc has been compressed to take
less printed space, but the downloadable version is formatted
normally.)
Example 6-1. SourceMedia.java, our initial typesafe enumeration
Code View: package com.oreilly.hh; |
Of course, the beauty of working with Hibernate is that we don't
need to change our normal Java classes to add support for persistence.
Even though we've not thought about persistence in designing this enum, we will be able to use it as-is. Now that
we no longer have to consider using the deprecated PersistentEnum interface, defining a
persistent enumerated type is no different than defining any other
enumerated type.
NOTE
The PersistentEnum interface did require
you to change your enumerations for persistence. That was probably an
even bigger reason why it was deprecated than the fact that it did not
mesh well with the Effective Java persistent
enumeration pattern or the Java 5 enum
keyword.
So how do we teach Hibernate to persist values of our
enumeration?
Chapter 13. Databases and Persistence
Chapter 13. Databases and PersistenceWe all want to leave behind something that will outlast us, and Ruby processes are no exception. Every program you write leaves some record of its activity, even if it's just data written to standard output. Most larger programs take this one step further: they store data from one run in a structured file, so that on another run they can pick up where they left off. There are a number of ways to persist data, from simple to insanely complex. Simple persistence mechanisms like YAML let you write Ruby data structures to disk and load them back later. This is great for simple programs that don't handle much data. Your program can store its entire state in a disk file, and load the file on its next invocation to pick up where it left off. If you never keep more data than can fit into memory, the simplest way to make it permanent is to store it with YAML, Marshal, or Madeleine, and reload it later (see Recipes 13.1, 13.2, and 13.3). Madeleine also lets you revisit the prior states of your data. If your dataset won't fit in memory, you need a database: a way of storing data on disk (usually in an indexed binary format) and retrieving parts of it quickly. The Berkeley database is the simplest database we cover: it operates like a hash, albeit a hash potentially much bigger than any you could keep in memory (Recipe 13.6). But when most people think of a "database" they think of a relational database: MySQL, Postgres, Oracle, SQLite, or the like. A persistence mechanism stores data as Ruby data structures, and a Berkeley DB stores data as a hash of strings. But relational databases store data in the form of structured records with typed fields. Because the tables of a relational database can have a complex structure and contain gigabytes of data, their contents are not accessed like normal Ruby data structures. Instead they're queried with SQL, a special programming language based on relational algebra. Most of the development time that goes into Ruby database libraries is spent trying to hide this fact. Several libraries hide the details of communication between a Ruby program and a SQL database; the balance of this chapter is devoted to showing how to use them. Every relational database exposes a C API, and Ruby bindings to each API are available. We show you how to use the two most popular open source databases: MySQL (Recipe 13.9) and Postgres (Recipe 13.10).[1] But every database has different bindings, and speaks a slightly different variant of SQL. Fortunately, there are other libraries that hide these differences behind a layer of abstraction. Once you install the bindings, you can install abstraction layers atop them and rely on the abstraction layer to keep track of the differences between databases.
Ruby's simplest database abstraction library is DBI (it's modeled after Perl's DBI module). It does nothing more than provide a uniform interface to the different database bindings. You still have to write all the SQL yourself (and if you're serious about database neutrality, you must use the lowest common denominator of SQL), but you only have to learn a single binding API. The more popular database abstraction libraries are ActiveRecord (the library of choice for Rails applications) and Og. Not only do these libraries hide the differences between databases, they hide most of the actual SQL. The database tables are represented as Ruby classes, the rows in the database tables as instances of those classes. You can find, create, and modify database rows by manipulating normal-looking Ruby objects. Neither Og nor ActiveRecord can do everything that raw SQL can, so you may also need to use DBI or one of the database-specific bindings. One standard argument for database abstraction layers is that they make it easy to switch an application's underlying database without having to rewrite all the code. They certainly do make this easier, but it almost never happens.[2] The real advantage is that with abstraction layers, you don't have to learn all the different database bindings. Even if you never change databases for any given project, throughout your career you'll find yourself using different databases on different projects. Learning how to use a database abstraction layer can save you from having to learn multiple database-specific bindings.
Whether you use ActiveRecord, Og, DBI, or database-specific bindings, you'll need an actual database for your code to connect to. The recipes in this chapter assume you've got a database called cookbook and that you connect to it with the username "cookbook_user" and the password "password". Here's how to set up cookbook as a MySQL database:
Here's how to set cookbook up as a Postgres database (you'll probably need to run these commands as the postgres user):
To avoid showing you the database connection code in every single recipe, we've factored it out into a library. If you want to run the code in this chapter's recipes, you should put the following code in a file called cookbook_dbconnect.rb. Keep it in the directory where you keep the recipe code, or somewhere in your library include path, so that require 'cookbook_dbconnect' will work. This file defines database connection functions for DBI, ActiveRecord, and Og:
The with_db method gets a database connection through DBI and runs a code block in the context of that connection:
The activerecord_connect method only needs to be called once at the beginning of a program: after that, ActiveRecord will acquire database connections as needed.
For your reference, this table presents the ActiveRecord adapter names for various kinds of databases.
The og_connect also needs to be called only once. One caveat: you must call it after you've defined the classes for your Og data model.
This version of cookbook_dbconnect assumes you're running against a MySQL database. For a different database, you just need to change the database name so that DBI, ActiveRecord, and Og know which adapter they should use. Here are some resources for more information about databases in Ruby:
|