In a previous post I created a simple blog containing two business objects, BlogPost and BlogComment. I implemented persistence for that blog in the simplest manner possible, I put an OrderedCollection of BlogPosts in an accessor called repository on the BlogPost class...

Allowing the class itself to serve as the database for all its instances. This is great for development speed, and gives you the ability to play and try out many different things until your object model settles down and you figure out what your model is really going to look like. Using the image as an object database allows you to remain nimble as you learn more about the problem and change your mind as you gain new insight into the domain model. Put off transactional persistence as long as you can, it's likely you can build almost your entire program without actually leaving the image or thinking about a database.

Let's assume the we're at that point now, and we're going to map BlogPost and BlogComment into a real relational database as if this were a production app. I'm going to use PostgreSQL and Glorp, my first time using either, and see what it takes. I'm not claiming anything I do here is best practice, only sharing my experiences as I learn.

For the record, Alan Knight, the author of Glorp, has a working implementation of ActiveRecord, somewhat like Ruby on Rails, that would allow me to avoid all this meta-data, but as far as I know, it hasn't been ported to Squeak yet, and is still in Alpha; I hope he's done soon.

Until ActiveRecord is available, I'll have to write the meta-data the old fashioned way. After reading the Glorp Tutorial, I see I need to subclass DescriptorSystem and create a class containing all the meta data for classes, tables, and the mappings between them. I call it SBGlorpDescriptions.

It seems I need to override two methods to tell Glorp about the tables and classes...

I also need to write methods for the class model which gives me a chance to control how Glorp loads the classes. For example, I may want to force Glorp to use accessors rather than direct instance variable access. Here I simply tell Glorp that a Post has a collection of Comments.

I'm not using the real power of Glorp here, because my models mostly match, however, were I programming against an existing legacy schema, I might start to appreciate all this meta-data a bit more, knowing I could map any shape class to any shape table. This is where Glorp truly shines over Rail's ActiveRecord, which is an extremely simple and not so flexible object mapping system. Everything I'm doing here, Rails could do easily, but Glorp is much more powerful and can be used against legacy schemas that look nothing like the class model.

Rails does one thing, one way, very well, with inferred meta-data and virtually no configuration. Glorp can do anything, any way you like it, but requires explicit meta-data, with a bit of configuration. Alan's about to give us the best of both worlds, by inferring the basic meta-data like Rails does, but allowing you to mix and match it with custom meta-data for more complex mappings, I can't wait, and I'm glad Rails has pushed Alan in this direction. Glorp will be much easier to use for greenfield applications if it infers the meta-data with reasonable defaults, and Rails has proven how popular this approach is with developers.

OK, now that all the meta-data and mappings are created, I need to have Glorp create the schema for me. I fire up a Workspace and create a Glorp session using my new SBGlorpDescriptions class...

And that's it, the sample blog now works against PostgreSQL. In all honesty, it was a bit of work, more than I expected, but given Glorp's capabilities, I understand the need for so much meta-data. I'll sure be glad when Alan finishes his ActiveRecord implementation because most of the time, that's all I need.

In the mean time, I'll have to write up a quick code generator to generate most of this meta-data for me directly from the classes using reflection. I've got a bigger project coming up where I plan to use Glorp, and there's no way I'm writing all this by hand again.

Related Posts

Comments (automatically disabled after 1 year)

Martial 4064 days ago

Hi,

Your tutorial is a pretty good work. It's exactly what I was looking for. But I don't understand the last part. I mean it looks like there is no definition of the database message for the session. I guess it must reach aPostgreSQLPlatform object but I don't know how to do this. I'm blocked at the line 'So far so good...' and after that I am a bit lost. I made a new WASession subclass and I added the following methods but it doesn't work...

OK, I added the missing methods for session. I left them out because I'm not sure I want to keep one Glorp session per one Seaside session, I have to do a bit of testing before I decide what's best practice there.

Martial 4063 days ago

Thanks! It works now. I agree there must be a better way. I thought about create a BlogDatabase class to manage the session connection because aWASession object is only seen from the BlogView thus I guess it's not a pure MVC architecture. In such a class, I copy the methods you create for the session and so, I can use the message addCondition:labelled used by BlogPost class>>descriptionTitle as you show it in your previous video tutorial.
I write this as follows:

Actually, the session is available from anywhere as a singleton, so BlogDatabase database would be the same as saying WACurrentSession value database.

However, as I said, I'm still working on how I'd like to do it. As for the persistentId, I'll be removing that, Glorp supports pseudo variables and doesn't really require it. I'd also implement that rule with a database constraint rather than a query, so I wouldn't use it anyway.

I'm currently busy creating my own version of ActiveRecord that creates all the mappings automatically from the meta data contained within the Magritte descriptions. I have it working and have the blog mapped to PostgreSQL with zero configuration. I'll figure out how I want to handle the session along with this and open source the code shortly after I do some more testing and feel it's stable enough.

Martial 4063 days ago

Oops! I have more to learn about seaside and the session...
An ActiveRecord should be far better. If you need help for testing your classes, tell me!

It's sort of like ActiveRecord, except the database is never read, only written, I consider the Smalltalk objects the real schema and the database as totally subservient to them.

Valy 4019 days ago

Hi,

I am trying to get started with Seaside ( I am new to Squeak and Smalltalk ), and I am getting stuck at several points.

One is the access to Postgresql ( which I will need for a new project ). My confusion begins with the versions and VM images, 3.9 for example lists Glorp in the packages list but fails installation ( not supported ), the link for the Squeak port found here http://www.glorp.org/versions.html is dead.

Is there any website/blog with an image that includes the necessary 'components' (Glorp, script.aculo.us, Seaside,etc) ?

Oh I like that! Nice post.
This place is alright...I'll be back for sure.

And 3788 days ago

I wrote a small app with Seaside using Squeak just to get the "feel" of it, but I am new to Smalltalk and there are two things that prevents me to begin using it for "real" projects at my work and it will be very helpful to get some clarifications and/or advice:

Understanding how to use Glorp sessions from Seaside.
At this moment I just created a singleton to get the session, is that the right way? I mean I have no idea how multiple requests are handled by Seaside and if that approach works for multiple queries from different users,etc.

Deployment
My web applications are used internally and for some clients, there is no need for huge scaling, a few dozen concurrent users tops. Will only one Squeak instance be sufficient? If not, should I follow the posts made about the deployment architecture used in DabbleDB and used that kind of setup with Apache,etc?

See my MagritteGlorp package on SqueakSource, it has the necessary code to integrate Seaside with Glorp including a custom seaside session class, a connection pool, and a few other things. You don't actually need to use Magritte, you can write your Glorp descriptor normally and use the Seaside Glorp integration.

For that small a load, a single squeak image will probably work just fine.

And 3788 days ago

Thanks! I will study that code and try to 'get it'.

I downloaded your image...wow! What a difference from the default Squeak image, fantastic!

I have a much better one now, a great new UI package was released that really cleans Squeak up. I'll update my image here soon so anyone can download it. Email me or leave a comment here if you have any questions about the package.

Yeah, this is a very very cool blog. ;-)
I just added you to my favorites.

Thanx,
Mikey

Carlos 3637 days ago

Ramon, very nice post. I found a demo in the Cincom site that illustrates this article in VW steb by step. Seems that there is some UI code, maybe built by UIPainter. I am interested in how a glorp-based model i editable-viewable with a classic GUI. Regards, Carlos