From: Kirk Haines Date: 2005-10-29T07:55:36+09:00 Subject: Re: The "perfect" ORM? On Friday 28 October 2005 3:47 pm, rubyhacker@gmail.com wrote: > Yes, but that's just giving different names to the same things, isn't > it? Well, yeah. :) > As far as I can see, all that's really needed is: > 1. Let each class map to a table > 2. Let each table have a known unique primary key > > Then we don't need all this "relationship" stuff, do we? In some cases, you can't do without it. ORM can be approached from two basic directions. It can be database driven, in that the structure of the database dictates the language structures, or one can have the language structures dictate the database structure. For instance, if you have a database that you need to write an application to interact with, that database structure is going to dictate your Ruby language structures, and your use of those structures should not change the structure of the database. In a case like that, depending on what database you are using, the database structure might explicitly describe the relationship between tables for you, or it may not. If it does, IMHO, the ideal for an ORM, and where I am going with Kansas, is for the ORM to be able to understand that and act on it, so that one automatically gets Ruby classes and methods that simply make that database structure accessible with no effort on the part of the programmer. It's automatic. On the other hand, if the database does not provide this information, or the code is being written so that it can be used on multiple dbs, and one of the potential targets does not provide this information, then if one wants to make use of relationships, one must provide this information. There's no way around it. And the reason why relationships are useful beyond having a simple mapping of class to table is because they make the code convenient. In the MSDS application that my examples come from, one can select a single chemical and view information on it. One thing that can be done at that point is to see other chemicals manufactured by the same manufacturer that the chemical being viewed comes from. So, if that chemical's record is in @chemical: @chemical.manufacturer.chemicals And you have your list. The relationship information provided the necessary string to tie those together without the programmer having to explicity write the code. It is a tremendous timesaver. Now, the other direction that an ORM can go is to let the language structures dictate the database structures. So, for instance, you declare a class: class Foo attr_accessor :a, :b end And somehow, that class is mapped to the database, creating or altering the table definition as necessary. When doing this, if a field is going to store objects of another class that is also mapped to a table in the database, you have to tell the ORM about that so that it knows how the tables should look in order to store your data. Regardless of the direction that one is approaching the ORM task from, the annotation still serves the same purpose -- it makes sure that the ORM is doing what you want it to in cases where interpretation is ambiguous or even impossible. > As for a "has-many" relationship (in objects, not in DBs) -- isn't that > > just what we call an "array"? The difference being that Ruby arrays are > > heterogeneous whereas rows of a table all represent the same type? Yep. > I want to do as little specification as possible to store my objects. > That's where I'm coming from. I want the persistence framework to be as > smart as possible and make as many reasonable assumptions as possible. > > I want to spend as little time coding the metadata portion as I can, > and > I want it all stuck in the same place in my code, in as few lines as > possible. Those are all my goals, too. :) Let's say that you have two classes: class Manufacturers attr_accessor :idx, :name, :address end class Chemicals attr_accessor :idx, :name, :manufacturer end Consider the manufacturer field in the Chemicals class. An ORM can not look at this and know that you intend to store Manufacturers objects in it. And that information is important to determine the structure of the database. What if you have a Manufacturers object, and you want to know all of the chemicals that have that manufacturer? You could write a method manually to do that: class Manufacturers def chemicals #query the db and retrieve an array of Chemicals records where # manufacturer == self.idx end end But if all of that typing can be reduced to simply telling the ORM about the relationship, using some syntax or other, isn't that a win? class Manufacturers relates_to Chemicals.manufacturer end Thanks, Kirk Haines