Has_many :through scope on join attribute


#1

Hi

I have a has_many :through. It’s a basic mapping of

Project
id

User
id

TeamMembers
project_id
user_id
role

What I would like to do is have different roles so I can have in the
project
model

has_many :core_members, :through => :team_members, :source => :user

but I would like to limit this to only those with the “core” role in the
team members table for this project.

Any ideas?


#2

On 5/10/06, Daniel N removed_email_address@domain.invalid wrote:
[…]

What I would like to do is have different roles so I can have in the project
model

has_many :core_members, :through => :team_members, :source => :user

but I would like to limit this to only those with the “core” role in the
team members table for this project.

Any ideas?

You can specify :conditions in your has_many statement. So for example:

has_many :core_members, :through => :team_members, :source => :user,
:conditions => “team_members.role = ‘core’”

or similar.


Bosko M. removed_email_address@domain.invalid


#3

Thanx Bosko, That worked great.

I have one question for this tho…

How do I have a has_one for this situation where the role is leader?

ie each project only has_one :leader

but I can’t specify the through condition.

I don’t really want to put a leader_id field in the projects table. I
would
like to keep all team members regardless of their role in the
team_members
table.

Any ideas how I could do this? I have tried for quite a few hours now
and
the only way I have found to impelment it is to write my own leader and
leader= methods in the project model.


#4

Bosko M. wrote:

On 5/10/06, Daniel N removed_email_address@domain.invalid wrote:

What I would like to do is have different roles so I can have in the project
model

has_many :core_members, :through => :team_members, :source => :user

but I would like to limit this to only those with the “core” role in the
team members table for this project.

Any ideas?

You can specify :conditions in your has_many statement. So for example:

has_many :core_members, :through => :team_members, :source => :user,
:conditions => “team_members.role = ‘core’”

or similar.

That works just fine, but I like to do it with a special association in
the join model, then use that as the :source in the containing model.
That localizes the condition to the proper scope, allows potential
reuse, and best of all you don’t have to name the table in the
:conditions. I have a full example of that on my blog (and the :uniq
stuff might be useful in this situation as well):
http://blog.hasmanythrough.com/articles/2006/05/06/through_gets_uniq

By the way, Daniel, there is no has_one :through association.


Josh S.
http://blog.hasmanythrough.com


#5

Hi Josh,

Thanx for the eplaination. I’ve been to your blog. I have found it
very
useful. Thanx. I have read your article that you mentioned but it must
of
been too late or something because I just couldn’t quite get my head
around
the relationships that you had. Also I don’t have the uniq option. I’m
assuming that this is only available for those on the edge.


#6

Hi Josh,

I can decipher what you have done but I don’t think that I understand it
well enough to know when to use it yet. I’ll have a play with it.

Would there be a way to specify a validates_uniqueness_of :author

in your example to have only one author per book? Would something like

validates_uniqueness_of :author, :scope => ‘book_id’, :if Proc.new{
self.role = ‘author’ }

make it so that there could only be one author per book?


#7

Daniel ----- wrote:

I can decipher what you have done but I don’t think that I understand it
well enough to know when to use it yet. I’ll have a play with it.

Would there be a way to specify a validates_uniqueness_of :author
in your example to have only one author per book? Would something like

validates_uniqueness_of :author, :scope => ‘book_id’, :if Proc.new{
self.role = ‘author’ }

make it so that there could only be one author per book?

Yes, something like that validation should work, though you want == (not
=) in the proc, and I think you’ll need to change :author to user_id.
You might need to tweak something else, I haven’t built one of these
before.


Josh S.
http://blog.hasmanythrough.com


#8

Daniel ----- wrote:

Hi Josh,

Thanx for the eplaination. I’ve been to your blog. I have found it
very
useful. Thanx. I have read your article that you mentioned but it must
of
been too late or something because I just couldn’t quite get my head
around
the relationships that you had. Also I don’t have the uniq option. I’m
assuming that this is only available for those on the edge.

Right, :uniq is only on edge at the moment. However, for now you can
still use the DISTINCT keyword in your :select if you need to remove
duplicates.

Did you manage to grok what I was doing in those associations? I’m
moving the condition into the association in the join model, which from
an object-oriented perspective is the right place to put it. You know,
data-hiding and encapsulation and all that. If you’re curious what’s
going on you should look at the generated SQL in development.log.


Josh S.
http://blog.hasmanythrough.com