Active Record: Rails Model Support
In general, we’ll want our web applications to keep their information in a
relational database. Order entry systems will store orders, line items, and
customer details in database tables. Even applications that normally use
unstructured text, such as weblogs and news sites, often use databases
as their backend data store.
Although it might not be immediately apparent from the SQL you use to
access them, relational databases are actually designed around mathematical
set theory. While this is good from a conceptual point of view,
it makes it difficult to combine relational databases with object-oriented
programming languages. Objects are all about data and operations, and
databases are all about sets of values. Things that are easy to express
in relational terms are sometimes difficult to code in an OO system. The
reverse is also true.
Over time, folks have worked out ways of reconciling the relational and
OO views of their corporate data. Let’s look at two different approaches.
One organizes your program around the database; the other organizes the
database around your program.
Database-centric Programming
The first folks who coded against relational databases programmed in procedural
languages such as C and COBOL. These folks typically embedded
SQL2 directly into their code, either as strings or by using a preprocessor
that converted SQL in their source into lower-level calls to the database
engine.
The integration meant that it became natural to intertwine the database
logic with the overall application logic. A developer who wanted to scan
through orders and update the sales tax in each order might write something
exceedingly ugly, such as
EXEC SQL BEGIN DECLARE SECTION;
int id;
float amount;
EXEC SQL END DECLARE SECTION;
EXEC SQL DECLARE c1 AS CURSOR FOR
select id, amount from orders;
while (1) {
float tax;
EXEC SQL WHENEVER NOT FOUND DO break;
EXEC SQL FETCH c1 INTO :id, :amount;
tax = calc_sales_tax(amount)
EXEC SQL UPDATE orders set tax = :tax where id = :id;
}
EXEC SQL CLOSE c1;
EXEC SQL COMMIT WORK;
Scary stuff, eh? Don’t worry. We won’t be doing any of this, even though
this style of programming is common in scripting languages such as Perl
and PHP. It’s also available in Ruby. For example, we could use Ruby’s
DBI library to produce similar-looking code. (This example, like the last,
has no error checking.)
def update_sales_tax
update = @db.prepare("update orders set tax=? where id=?")
@db.select_all("select id, amount from orders") do |id, amount|
tax = calc_sales_tax(amount)
update.execute(tax, id)
end
end
This approach is concise and straightforward and indeed is widely used.
It seems like an ideal solution for small applications. However, there is
a problem. Intermixing business logic and database access like this can
make it hard to maintain and extend the applications in the future. And
you still need to know SQL just to get started on your application.
No comments:
Post a Comment