Good discussion. I might add that while associations can be reasonably assigned to attributes mentally, it's harder to do something like that for acts_* and other meta-programming wrap-ups in Rails. So for example:
class Story < ActiveRecord::Base belongs_to :iteration acts_as_taggable acts_as_list :scope => :iteration end
If I were to do these in SQLObject (and someone else has started some of these), I'd do:class Tag(SQLObject): name = StringCol(alternateID=True) # Assuming joins.PolyMorphic is a signifier to take the place of a class name: items = joins.ManyToMany(joins.Polymorphic) class Story(SQLObject): iteration = ForeignKeyCol('Iteration') sort = IntCol() tags = joins.ManyToMany('Tag', polymorphic=True) class Iteration(SQLObject): stories = OneToMany('Story', mutableOrderBy='sort') i = Iteration.get(1) i.stories.moveUp(1) # or maybe... i.stories.swap(0, 1) s = Story.get(1) fiction = Tag.byName('fiction') s.tags.add(fiction)
Joins in SQLObject (unlike Django, I think) are defined on both sides of the relation. I'm okay with that for a few reasons:
- Each class is a fairly complete description, and nothing magically appears because of something else in the system.
- belongs_to or has_many? There's no reason to use one over the other. I dislike forcing people to make arbitrary decisions.
- Each side of the join has certain options which aren't symmetrical tied to the other end. Cascading makes sense on the ForeignKey. Ordering makes sense on the target of the key. You'd have to duplicate all these options to both ends for both ways of expressing the relation, but possibly with subtely different language.
- Less name generation means less rules. Rails pluralization rules certainly don't seem appealing. I get the impression from what I've heard from you and others that a lot of time has been spent on that feature and probably even more time on discussion of that feature. So (to me) it's just as well that the code includes both iterations and 'Iteration', and both stories and 'Story'.
Generally speaking, I'd like to see functionality like the acts_* functions in SQLObject, but for each case having the functions grouped under a single attribute. So where acts_as_nested_set adds a handful of methods, in SQLObject all those methods would live under a single attribute.# Ian Bicking
During that part of the presentation, I was quite curious what the database generated underneath looks like for those polymorphic relationships. From the example in the presentation, how does it represent "Taggings"? Does it actually create:Person Message | | PersonTaggings MessageTaggings (person_id, tag_id) (message_id, tag_id) \ / Tag
And then Tag.taggings.collect knows all the intermediate tables to combine?
Guess I have to dig into the ActiveRecord code.