Forum OpenACS Q&A: Very confused about CR

Collapse
Posted by Sean Redmond on

These seem like FAQs, but I haven't been able to find clear answers in the forums or docs. It boils down to this: to use the Content Repository for a new package or not. I think the answer is yes, if only to make searching easier, but I'm still not quite sure. If the 'yes', then how?

Now for the specifics. I'm creating an exhibition management package for a museum. Exhibitions have titles, dates, curators, locations, credit lines, descriptions, etc. Not all of this needs versioning or searching -- let's say only titles and descriptions do.

Is an exhibition A) a content type? B) a content type containing other content types since title and description probably change independently? Or C) simply an object linked to various content types (exhibition title, exhibition description).

I've been reading the Content Repository documentation as well as Jade Rubick's notes and I think the answer is B) but I can't for the life of me figure out the relationship between the base table, cr_items, cr_revisions and the various attributes. For instance, in the press release example of the CR docs, you have a table cr_press_releases, for which you create an attribute, location, using content_type.create_attribute(). It sounds like the locations column would be added to cr_press_releases if it didn't already exist. Then what? There is no example of creating or updating a press release. What's the content of the content type (I think it's the text of the release, which through some API not illustrated in the docs, you would save to cr_revisions.content)? Can you just change the location in cr_press_releases? Does that create or require a new revision?

Here's what I think, but please tell me if I'm wrong:

  • a content type only has one versioned field, stored in cr_revisions.content (and/or possibly cr_revisions.lob, depending on whether it is text or binary?)
  • What you add via content_type.create_attribute() is just a matter of convenience since it becomes part of your cr_content_typex view. You could safely ignore this step, but you'd be on your own for accessing the data.
  • You have to write functions like your_content_type__new(), etc. to manage the creation of items and revisions

Therefore, in my case, an exhibition might be a content type though it doesn't have anything for cr_revisions.content (but it looks like this can be null) -- does that make it an item (in cr_items) with no revisions (in cr_revisions). It would merely serve as the parent of other content types (title, desciption, maybe images). Making the exhibition title a child content type is maybe a bad choice because it would then be harder just to get a sorted list of exhibitions for a particular year, say. select title from exhibitions where year='2003' order by title becomes some kind of join and function call which isn't even clear to me now. Though not making a content type out of exhibition titles loses an important supposed benefit: search

Whew! That's a lot of questions but they are typical of the confusion people seem have getting started with CR. Any help in steering me down the right path to repositing my content is greatly appreciated.

Collapse
2: Re: Very confused about CR (response to 1)
Posted by tammy m on
Well I think the following but I'm far from an authority on the subject;)

Exhibition is A) a content type.

Title and Description are attributes of the content type Exhibition.

To use the CR, you create your content_type which is basically the definition of your document and what fields/attributes it contains.

You create the content_type and all the attributes using pl/sql calls like so. Now this content_type serves as a outline/template from which you can create instances of your documents (in this case Exhibition documents).

All document instances have a single cr_item and at least one cr_revision associated with them. When you use content_item.set_live_revision( revision_id => :revision_id );, with a revision_id, you basically tell the CR which cr_revision of your cr_item you wish to receive whenever the live/published cr_item is requested. This cr_revision is usually going to be the latest_revision saved. (Though if you are editing the cr_item via a GUI, the live_revision may not be the latest_revision but an earlier revision until the edited changes are posted as the live_revision. Or you might even revert your cr_item an earlier cr_revision to if you decide some edits were not so nice.)

For instance, in the press release example of the CR docs, you have a table cr_press_releases, for which you create an attribute, location, using content_type.create_attribute(). It sounds like the locations column would be added to cr_press_releases if it didn't already exist.

Yes.

Then what? There is no example of creating or updating a press release.

Sure there is. You create a Press Release or you create Exhibition documents=items by using the content_item.new API. This creates a cr_item and a first cr_revision for your document (=item. e.g. Press Release or Exhibit). You update the document/Press Release/Exhibit by Creating Content Revisions of your new cr_item (=document).

What's the content of the content type (I think it's the text of the release, which through some API not illustrated in the docs, you would save to cr_revisions.content)?

The content attribute/field can be anything you want it to be! Usually, if you have a really simple document, the content may just be it's body and then that is all you have! Otherwise, you can use content to hold most of the meat of your document (for a given content_type) though one thing you get for free, is that the content attribute is automagically searchable via the default cr_revision FTS proc. So put something you want searchable in there. Or don't even use it all, make your own custom attributes (and optionally, your own FTS search procs for your content_type), you decide!

Can you just change the location in cr_press_releases? Does that create or require a new revision?

That does require a new revision. The CR creates a new revision any time anything in your document/cr_item is changed/updated. That's what revisions are for. Or, you can let the CR know to just update the live_revision in place and not ever create new revisions. You lose any auditing/tracking capabilities and the ability to revert to earlier revisions of your documents by doing this though.

a content type only has one versioned field, stored in cr_revisions.content (and/or possibly cr_revisions.lob, depending on whether it is text or binary?)

Kinda. By default a cr_revision gets a title, content and description. These are versioned. If you want to have more attributes for your custom content_type you must create them as generic storage or specific storage. I prefer specific storage because then I can create a table that holds the rest of the versioned fields for my content_type's cr_revisions.

What you add via content_type.create_attribute() is just a matter of convenience since it becomes part of your cr_content_typex view. You could safely ignore this step, but you'd be on your own for accessing the data.

Hmmm. If you ignore this step, you would not have any other attributes besides the default of content, title, description for your item and it's revisions. It becomes part of the view yes, because it's part of all revisions of your document/item then. There are views created for insert and viewing.

You have to write functions like your_content_type__new(), etc. to manage the creation of items and revisions

No. You can do it one of 3 ways. I like to do it the easiest way like this (straight from the docs):

insert into cr_revisionsx (
  item_id, revision_id, title
) values (
  18, 19, 'All About Revisions'
);
Because a special trigger is generated for each content type that includes insert statements for all inherited tables, revisions with extended attributes may be created in the same fashion:
insert into cr_imagesx (
  item_id, revision_id, title, height, width
) values (
  18, 19, 'A Nice Drawing', 300, 400
);

Notice you pass the revision_id so you can either overwrite an existing revision or make use of the versioning and get a new revision.

For what it's worth, here's a basic step by step of how a content_type gets created and then you create documents (cr_items) and revisions from it.

Steps:

1) Define a content_type for document.
    PERFORM content_type__create_type (
        ''your_exhibit'',            -- content_type
        ''content_revision'',           -- supertype
        ''Exhibit'',                -- pretty_name
        ''Exhibits'',               -- pretty_plural
        ''cr_your_exhibits'',        -- table_name
        ''cr_revision_id'',             -- id_column
        NULL                            -- name_method
    );
-- Uses inherited default content_revision__revision_name name_method if not specified.

-- When the content type is created, the CR creates a view called your_content_type_tablename_revisionsx (e.g. cr_orp_personal_adsx).
-- Note the x at the end of the name.
-- On postgres, a second view called your_content_type_revisionsi (e.g. orp_personal_adi) is also created.

-- The x view is created for selection, and the i view is created for inserts.
-- They join the acs_objects, cr_revisions, and your_content_type_items and your_content_type_revisions tables together.
-- Note that Personals pkg does not define a your_content_type_items table as all of the Personal Ads
-- columns/fields are version controlled and thus go in the cr_revisions and your_content_type_revisions tables.



2) Create a cr_item to create your first document/item of your new content_type

             select content_item__new (:name::varchar,
                                        :parent_id::int4,
                                        :item_id::int4,
                                        null,
                                        now(),
                                        :creation_user,
                                        null,
                                        :creation_ip,
                                        :content_item,
                                        :content_type,
                                        null,
                                        null,
                                        'text/plain',
                                        null,
                                        null,
                                        'text'::varchar)

3) Create a cr_revision for the cr_item/document/item

              select content_revision__new (:title,
                                            :description,
                                            now(), 
                                            null, 
                                            null,
                                            :data,
                                            :item_id,
                                            null,
                                            now(),
                                            :creation_user,
                                            :creation_ip)


4) Insert into the "x" view for the content_type. This adds any/all custom fields you defined for your content_type to the revision you specify. 

insert into cr_your_content_typex (
  item_id, revision_id, title, height, width
) values (
  18, 19, 'A Nice Drawing', 300, 400
);

BTW, I think the CMS docs are actually the best docs to look at for info on how the internals of the CR are designed to work. Then CR Dev Guide for more specifics on implementing once you have the understanding.

Collapse
3: Re: Very confused about CR (response to 1)
Posted by Randy O'Meara on
Tammy,

What a nice, clear writeup. Thanks.

Randy

Collapse
4: Re: Very confused about CR (response to 2)
Posted by Sean Redmond on

Tammy, thanks a lot. That helps immensely.

Collapse
5: Re: Very confused about CR (response to 1)
Posted by Jade Rubick on
Sean, if you want to write up anything you've learned here (and cull from Tammy's response) and incorporate it into my docs on rubick.com, I'd be happy to give you write access. Make sure you credit yourself and Tammy for the portions you write.
Collapse
6: Re: Very confused about CR (response to 5)
Posted by Sean Redmond on

Jade,

I'm using the content repository for a few different projects and I'd be happy to write up what I learn.

Collapse
7: Re: Very confused about CR (response to 6)
Posted by Jeff Davis on
It would be great if those of you who are having trouble with the CR could suggest how the existing CR documentation falls short of your needs.

Obviously it's somewhat out of date (and in particular is entirely oracle specific) but it seems like a reasonable starting point and I think is worth salvaging and improving.

Collapse
8: Re: Very confused about CR (response to 1)
Posted by Jun Yamog on
Collapse
9: Re: Very confused about CR (response to 1)
Posted by Randy Ferrer on
Jeff - I think that most of the documentation is fine and serves as a good starting point. What Jun is working on is really nice as well. What would be most helpful imho is good, annotated examples of the CR in use. Good code samples as well as conceptual documents explaining how the CR has been used to solve specific issues. Some write-ups by developers in the community who have used the CR extensively, I think would be a great contribution to get less experienced developers up to speed with the CR.
Collapse
Posted by Alfred Werner on
I think the documentation, other than being Oracle specific is quite good. Maybe I'm dense though :) but I never realized that content-repository was part of "CMS" .. see my post at https://openacs.org/forums/message-view?message_id=150880 ...
Collapse
Posted by Dave Bauer on
The content repository is not part of the CMS package or CMS, although it is a required service for the CMS package and the best tool to start designing a content management application.
Collapse
Posted by Alfred Werner on
I didn't mean to say that its part of the CMS package, but it is a critical service for Content Management in all its guises  and is used by a lot of OpenACS packages to provide content management features. Not all, but a repeatable core.