Index: openacs-4/packages/acs-core-docs/www/objects.html =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/acs-core-docs/www/objects.html,v diff -u -N -r1.53 -r1.54 --- openacs-4/packages/acs-core-docs/www/objects.html 7 Aug 2017 23:47:51 -0000 1.53 +++ openacs-4/packages/acs-core-docs/www/objects.html 8 Nov 2017 09:42:11 -0000 1.54 @@ -1,16 +1,25 @@ -
+
By Pete Su
+</authorblurb> + +Developing data models in OpenACS 5.9.0 is much like developing data models for OpenACS 3, save for the implementation. As usual, you need to examine how to model the information that the application must store and manipulate, and define a suitable set of SQL tables. In our Notes application, we have to be able to keep track of who entered a particular note, when they did it, and the actual text of the notes that users have entered. A simple data model might look like this: -
+ + + ++ + +create table notes ( note_id integer primary key, owner_id integer references users(user_id), @@ -20,12 +29,21 @@ title varchar(255) not null, body varchar(1024) ) -+
We've omitted constraint names for the purpose of clarity. -
+
+ +Thinking further ahead, we can imagine doing any of the following things with Notes as well: -
Define access control policies on notes.
Attach user comments on notes.
Allow users to define custom fields to store on their notes.
Automatically generate input forms or output displays for notes.
Allow other applications to use notes in ways we don't know of yet.
+
+ +Define access control policies on notes.
Attach user comments on notes.
Allow users to define custom fields to store on their notes.
Automatically generate input forms or output displays for notes.
Allow other applications to use notes in ways we don't know of yet.
In OpenACS, the key to enabling these types of services on your application data is to take advantage of the Object System. The first question, then, is "Just what are objects, and what do @@ -37,7 +55,9 @@ table defines all the standard attributes that are stored on every object, including its system-wide unique ID, object type, and some generic auditing columns. -
+
+ +To make use of the object system, you as the application developer have to write your data model in a way that is slightly more complex than in the ACS 3.x days. What you get for this extra work includes: @@ -52,10 +72,18 @@ object and forget about it.
And most importantly, any future object-level service - from a general-comments replacement to personalized ranking - will become available to your application "for free."
-
Using ACS objects is straightforward: all that's required are a few extra steps in the design of your application data model. -
+
+ +
In order to hook our Notes application into the object system, we
make some calls to use our notes
table as the basis for a
new object type. Object types are analogous to classes in
@@ -64,7 +92,9 @@
that run code. In OpenACS, we use one or more database tables to store the
data attributes, and we define a stored procedure package to hold procedures to
define the programming interface to the data model.
-
+
+ +
The object type itself is described using data in the
acs_object_types
and
acs_attributes
tables, which play a role
@@ -75,13 +105,25 @@
keep everything consistent. Below you'll find the code needed to describe a
new object type called notes
in your
system.
-
+
+ +
Fire up your text editor and open the
ROOT/packages/notes/sql/oracle/notes-create.sql
(ROOT/packages/notes/sql/postgresql/notes-create.sql
for the PG version) file created
when we created the package. Then, do the following:
-
+
+ + + +
First, add an entry to the acs_object_types
table with the following PL/SQL call:
-
+ + ++ +begin acs_object_type.create_type ( supertype => 'acs_object', @@ -94,7 +136,9 @@ end; / show errors; -+
This PL/SQL call tells the system that we would like to use the table
NOTES
as the basis for a new object type called
note
. This type is a subtype of the
@@ -103,13 +147,17 @@
some work on our part to make this happen, since Oracle can't do it
automatically. In general, most basic applications will define types
that are simple subtypes of acs_object
.
-
+
+ +
Add entries to the acs_attributes
table to describe
the data attributes of the new type. This data can eventually be used
to do things like automatically generate user interfaces to manipulate
the notes
table, though that functionality isn't yet
available.
-
+ + ++ +declare attr_id acs_attributes.attribute_id%TYPE; begin @@ -131,28 +179,44 @@ end; / show errors; -+
We can stop here and not bother to register the usual OpenACS 3.x
attributes of creation_user
, creation_date
and last_modified
, since the object type
acs_object
already defines these attributes. Again,
because the new type note
is a subtype of
acs_object
, it will inherit these attributes, so there is
no need for us to define them.
-
The next thing we do is make a small modification to the data model to
reflect the fact that each row in the notes
table
represents something that is not only an object of type
note
, but also an acs_object
. The new table
definition looks like this:
-
+ + + ++ + +create table notes ( note_id integer references acs_objects(object_id) primary key, owner_id integer references users(user_id), title varchar(255) not null, body varchar(1024) ) -+
The usual creation_date
and
modified_date
columns are absent since they already exist
in acs_objects
. Also, note the constraint we have added
@@ -164,11 +228,21 @@
use the acs_objects
table to find objects will
transparently find any objects that are instances of any subtype of
acs_objects
.
-
The next step is to define a PL/SQL package for your new type, and write some basic procedures to create and delete objects. Here is a package definition for our new type: -
+ + + ++ + +create or replace package note as function new ( @@ -191,7 +265,10 @@ end note; / show errors -+
You might be wondering what all the extra parameters are to these
calls, since we haven't mentioned them before. These parameters are
needed to fill out information that will be stored about the object
@@ -202,7 +279,9 @@
self-explanatory and reflects attributes that existed in the earlier
OpenACS 3.x data models, with the exception of the context_id
attribute.
-
+
+ +
The context_id
attribute stores the ID of an object that
represents the default security domain to which the object belongs. It
is used by the permissions system in
@@ -212,15 +291,24 @@
object OBJ was "read only", then any other object that used OBJ as its
context would also be "read only" by default. We'll talk about this more
later.
-
The PL/SQL package body contains the implementations of the procedures
defined above. The only subtle thing going on here is that we must use
acs_object.new
to insert a row into
acs_objects
, before inserting a row into the
notes
. Similarly, when we delete a row from
note
, we have to be sure to delete the corresponding
acs_object
row.
-
+ + + ++ +create or replace package body note as @@ -271,17 +359,24 @@ end note; / show errors; -+
That's pretty much it! As long as you use the note.new
function to create notes, and the note.delete
function to
delete them, you'll be assured that the relationship each
note
has with its corresponding acs_object
is preserved.
-
+
+ +
The last thing to do is to make a file
ROOT/packages/notes/sql/notes-drop.sql
so it's easy to
drop the data model when, say, you're testing:
-
+ + + +begin acs_object_type.drop_type ('note'); end; @@ -290,31 +385,56 @@ drop package note; drop table notes; -
While it is hard to give general design advice without knowing anything about a particular application, you should follow the following rule of thumb when deciding when to hook part of your data model to the object system: -
+
+ +
Anything in your data model that needs to be available to general OpenACS
services such as user comments, permissions, and so on should be a
subtype of acs_object
. In addition, if you want your data
model to take advantage of attributes that exist in some object type
that is a subtype of acs_object
, then you should use the
object system.
-
+
+ +For example, for most applications, you will want to use objects to represent the data in your application that is user visible and thus requires access control. But other internal tables, views, mapping tables and so on probably don't need to be objects. As before, this kind of design decision is mostly made on an application-by-application basis, but this is a good baseline from which to start. -
In this section we cover some overall guidelines for designing data models that are meant to be integrated with the OpenACS object system. -
+
+ +There are two basic rules you should follow when designing OpenACS 5.9.0 data models: @@ -332,7 +452,9 @@ a very specific purpose by the permissions system, and using this field in any other way whatsoever is guaranteed to make your application act strangely. -
+
+ +
As we'll see later, the Notes example will point each note object's
context_id
to the package instance in which the note was
created. The idea will be that in a real site, the administrator would
@@ -353,11 +475,15 @@
semantics of the data model are no longer independent of the
application. This would make it impossible to build the generic tools
that the data model is trying to support.
-
+
+ +
Another less important reason for these two rules is to not introduce
any joins against the acs_objects
table in SQL queries in
your application that you do not absolutely need.
-
+
+ +
In the Notes example, the result of applying these rules is that we
are careful to define our own attribute for owner_id
rather than overloading creation_user
from the objects
@@ -369,7 +495,13 @@
when to use inherited attributes is fairly straightforward, but
requires a good amount of thought at design time even for simple
applications.
-
Hooking into the OpenACS 5.9.0 object system brings the application developer
numerous benefits, and doing it involves only four easy steps:
@@ -394,4 +526,12 @@
especially true for the context_id
field.
-
($Id$)
+ + + + + +