How should Ribs definitions look?


I am currently sitting with Ribs, trying to decide how the definitions for associations should look like. I’ve also decided that I don’t want to use the current scheme for properties either. I also have some interesting constraints. First, I do not want to evaluate the block using instance_eval, so introducing nice method_missing hooks in the block context is out (so I can’t do anything like “has n” as DataMapper). Also, all definitions need to be able to take additional parameters in a hash. So something like “rib.has * :Posts” won’t work either.

I have come up with something that I’m reasonably happy with. It’s quite terse but definitely readable. It doesn’t pollute any namespaces. And hopefully it will only be used when the model need to differ from the conventions. I’m thinking about taking conventions a step further with Ribs and automatically try to figure out associations based on naming and foreign keys – but I haven’t decided about that yet.

All of these examples are supposed to be executed inside the Ribs! block, with r being the Rib parameter. I’ve decided to allow the table name as a parameter to the Ribs! method call instead of being something you set inside.

First of all, setting which property/properties are a primary key, I’m thinking about one or more of these alternatives – where track_id is the property name:

r.track_id :primary_key
r.track_id :primary_key => true
r.track_id = :primary_key
r.track_id.primary_key!

I’m skittish about the track_id= alternative, but the others I think can coexist quite well.

The next thing is to handle the mapping from one property name into a different column name (if no column name is specified, the property name will be used, of course):

r.title :column => :track_title
r.title.column = :track_title

Nothing very extraordinary here. I would probably like to have both alternatives here.

The next one is more interesting. I haven’t yet decided how to handle specifying primitive types. This code is supposed to handle the case that in ActiveRecord are covered with has_one and belongs_to. I don’t really see why they have to be different, really, so I’m thinking about doing something like this:

r.blog :is_owner
r.blog :is => Blog

I’m skittish about :is_owner, but it also feels slightly icky to have to specify the type of all single associations. This is definitely an area I would like to have some good ideas about.

Finally we come to the one-to-many and many-to-many associations. What makes this different is that I can have both a Set and a List (and also Map) since Hibernate handles these for me:

r.comments :list_of => Comment
r.comments :set_of => Comment
r.comments :is_set
r.comments :is_list

Once again I’m not sure how to handle it in such a way that you don’t have to write the name of the other entity in all definitions.

Anyway, this is what I currently have. I would appreciate innovative ideas here – especially if they are innovative within the constraints I’ve set for myself.


3 Comments, Comment or Ping

  1. Just curious: are you going to create code to handle collection maintenance? I.e. if you have:

    Entry.comments :list_of Comment
    and
    Comment.entry :is => Entry

    Are you going to create code that sets comment.entry when adding a comment to entry.comments, and vice versa?

    I find it always pretty painful to have to do this stuff manually. When doing it automatically, you of course have to be careful not to create infinite recursions.

    September 10th, 2008

  2. I’m a little confused about the method_missing comment. Regarding “has n” in DM, #has and #n are both methods. “n” is just n = Infinity = 0/1.0.

    Also, I’m curious how Hibernate decides where the FK is on the belongs_to/has example you mention. Since you’re right, they mean the same thing on the object-side basically, but they’re mapped differently to the database and I don’t see where that mapping happens in your example.

    It’s been a good while since I looked at NHibernate tho’ (never used the original).

    I would love it if DM could eventually support HQL. Even if it just returns Structs. So if you ever feel like writing a Ruby HQL parser please keep that in mind. :-)

    September 10th, 2008

  3. Martin:

    Haven’t decided yet, but probably not. I would like to keep a clean separation between the model and the Ribs code – which means more or less an implementation of Repository and Data Mapper in the purest sense.

    Sam:

    The “has n” comment was actually about instance_eval, not method_missing. But not being able to use instance_eval rules out method_missing tricks too. Otherwise I would have been able to do away with the colons for symbols, for example.

    Well, In Hibernate you generally need to map it. But I was thinking about trying to find it by conventions – if for example there is a blog_id column in the current table, it’s quite clear how it should map. In the other case it’s a bit more complicated, of course – which is why I’m wondering about good alternatives to the syntax.

    HGL will definitely be supported by Ribs. But I will use Hibernate directly to do it so I won’t need a parser for it.

    September 10th, 2008

Reply to “How should Ribs definitions look?”