first pass at has_many(through, via)

0 views
Skip to first unread message

Jonathan LaCour

unread,
Aug 17, 2007, 4:00:00 PM8/17/07
to sqle...@googlegroups.com
So, after all that discussion about has_and_belongs_to_many and
has_many, I spent five minutes implementing a simple enhancement to
has_many that utilizes the association proxy extension to SQLAlchemy,
and committed it to trunk.

Here is a quick example:

class Person(Entity):
has_field('name', Unicode)
has_many(
'assignments',
of_kind='Assignment',
inverse='person'
)
has_many(
'projects',
through='assignments',
via='project'
)

class Project(Entity):
has_field('title', Unicode)
has_many(
'assignments',
of_kind='Assignment',
inverse='project'
)

class Assignment(Entity):
has_field('start_date', DateTime, default=datetime.now)
belongs_to('person',
of_kind='Person',
inverse='assignments'
)
belongs_to(
'project',
of_kind='Project',
inverse='assignments'
)

This is just a first pass using what was available in SQLAlchemy. Let
me know what you all think, and I'll be happy to roll it back if there
is uproar about it :)

--
Jonathan LaCour
http://cleverdevil.org

nerkles

unread,
Aug 17, 2007, 6:46:37 PM8/17/07
to SQLElixir
Aren't you supposed to be resting and getting better? :P


Jonathan LaCour

unread,
Aug 17, 2007, 7:07:20 PM8/17/07
to sqle...@googlegroups.com
nerkles wrote:

> Aren't you supposed to be resting and getting better? :P

Nothing makes me feel better than making users happy! ;)

Yeah, I finally got over my sickness, and am trying to knock out little,
easy things while I have the chance :) Besides, Mike Bayer never rests.
Its not really fair for me to...

Gaetan de Menten

unread,
Aug 20, 2007, 6:02:25 AM8/20/07
to sqle...@googlegroups.com
This is a nice first step, though it doesn't fit the bill entirely.

AssociationProxy can be used to create has_and_belongs_to_many
relationships (the one in your exampe, for instance), has_one and even
scalar fields. So I think we should have that functionality on
has_one, has_many (inherited from has_one), has_and_belongs_to_many
and even has_field.

Now I guess that providing a base class for all of those would be an
option to achieve that. Alternatively, (I think I prefer this option)
do it on has_field (probably using different keywords) and the
Relationship base class.

has_field('foo', through='child', field='foo')

And we could make the field kwarg optional (defaults to the name of
the "local" field)

A nice addition would also be to include some sanity checks: you can't
have an has_many over through two has_one, and such things, but I'm
not sure it's possible to do that.

If you agree with this, I'll have a go at it tomorrow.


--
Gaëtan de Menten
http://openhex.org

Jonathan LaCour

unread,
Aug 20, 2007, 8:35:09 AM8/20/07
to sqle...@googlegroups.com
Gaetan de Menten wrote:

> AssociationProxy can be used to create has_and_belongs_to_many
> relationships (the one in your exampe, for instance), has_one and
> even scalar fields. So I think we should have that functionality on
> has_one, has_many (inherited from has_one), has_and_belongs_to_many
> and even has_field.

Makes sense to me, and is a logical next step from my initial checkin.

> Now I guess that providing a base class for all of those would be
> an option to achieve that. Alternatively, (I think I prefer this
> option) do it on has_field (probably using different keywords) and the
> Relationship base class.
>
> has_field('foo', through='child', field='foo')
>
> And we could make the field kwarg optional (defaults to the name of
> the "local" field)

I don't like the 'field' kwarg name, but I am not really happy with the
'via' kwarg name either. Lets keep trying to think of something better.
But, yeah, this looks good otherwise, including the default name. We
could also make the kwarg optional and make the user specify the type
of object using 'of_kind' again, and inspect the target side of the
relationship to figure out what they are wanting. Just a thought :)

> A nice addition would also be to include some sanity checks: you can't
> have an has_many over through two has_one, and such things, but I'm
> not sure it's possible to do that.

Well, the more sanity checks the better. One of the most difficult
things about Elixir (and SQLAlchemy) is that many of the error messages
aren't entirely readable, and its hard to determine what you have done
wrong sometimes from a stack trace.

> If you agree with this, I'll have a go at it tomorrow.

Give it a shot! I also noticed that my has_many/through doesn't seem
to make the relation writable, which I thought AssociationProxy was
supposed to handle for you... any ideas?

Gaetan de Menten

unread,
Aug 20, 2007, 10:19:23 AM8/20/07
to sqle...@googlegroups.com
On 8/20/07, Jonathan LaCour <jonatha...@cleverdevil.org> wrote:
>
> Gaetan de Menten wrote:
>
> > AssociationProxy can be used to create has_and_belongs_to_many
> > relationships (the one in your exampe, for instance), has_one and
> > even scalar fields. So I think we should have that functionality on
> > has_one, has_many (inherited from has_one), has_and_belongs_to_many
> > and even has_field.
>
> Makes sense to me, and is a logical next step from my initial checkin.
>
> > Now I guess that providing a base class for all of those would be
> > an option to achieve that. Alternatively, (I think I prefer this
> > option) do it on has_field (probably using different keywords) and the
> > Relationship base class.
> >
> > has_field('foo', through='child', field='foo')
> >
> > And we could make the field kwarg optional (defaults to the name of
> > the "local" field)
>
> I don't like the 'field' kwarg name, but I am not really happy with the
> 'via' kwarg name either. Lets keep trying to think of something better.

What don't you like about the "field" kwarg? To end up with a
scalar/has_field value, your ending point *must* be some kind of
scalar thing. It can come from either a column or an aggregate
property. Would you prefer "column"? or "property"? or ?

> But, yeah, this looks good otherwise, including the default name. We
> could also make the kwarg optional and make the user specify the type
> of object using 'of_kind' again, and inspect the target side of the
> relationship to figure out what they are wanting. Just a thought :)

I'm +0 on this. Meaning, I won't code it, but if someone comes up with
a decent patch, I won't oppose the feature. Of course, it should raise
an (understandable) exception if more than one relation could be used.

> > A nice addition would also be to include some sanity checks: you can't
> > have an has_many over through two has_one, and such things, but I'm
> > not sure it's possible to do that.
>
> Well, the more sanity checks the better. One of the most difficult
> things about Elixir (and SQLAlchemy) is that many of the error messages
> aren't entirely readable, and its hard to determine what you have done
> wrong sometimes from a stack trace.

Sure.

> > If you agree with this, I'll have a go at it tomorrow.
>
> Give it a shot! I also noticed that my has_many/through doesn't seem
> to make the relation writable, which I thought AssociationProxy was
> supposed to handle for you... any ideas?

It's probably related to the missing "creator" kwarg. I'm not sure in
which cases it's required though.

Reply all
Reply to author
Forward
0 new messages