Topic: Associations and find

Hi. I have the following models
class User < ActiveRecord::Base
  has_and_belongs_to_many :projects
end

class Project < ActiveRecord::Base
  has_many :castings, :dependent => :destroy
  has_many :candidates, :through => :castings
  has_and_belongs_to_many :users
end

class Candidate < ActiveRecord::Base
  has_many :castings, :dependent => :destroy
  has_many :projects, :through => :castings, :uniq => true
end

class Casting < ActiveRecord::Base
  belongs_to :project
  belongs_to :candidate
end

What I need is when I issue a Candidate.find that it will only return
candidates for which the user has access to (via the projects_users
habtm).

I also need a way to check if the user has access to a specific
candidate.

Thank you

Re: Associations and find

You can use eager loading to solve your first problem. Something like this:

@candidates = Candidate.find(:all, :include => { :projects => :users }, :conditions => ['users.id = ?', @user.id])

This will end up making a crazy long SQL query with lots of joins because the user and candidate models are very far from each other. I'm hoping this will work without any problems, but if it doesn't you may need to resort to a custom find_by_sql and do the joins and such on your own.

As for your second problem, try this:

# in User model
def can_access_candidate?(candidate)
  projects.map(&:candidates).include? candidate
end

This will fetch all of the candidates for all of the projects and check if the passed candidate falls in that array.

Hope that helps.

Railscasts - Free Ruby on Rails Screencasts

Re: Associations and find

It works! Thank you so much. It creates a monster query with three joins, but it works smile

I was looking at eager loading today, but couldn't get it to work. I can't find any reference to the ":projects => :users" definition in the rails api or the "agile" book.

Haven't tried the can_access_candidate method yet, but I'm not sure about loading all the candidates. Couldn't I just do a query like the first one (but for a specific candidate) and check for a RecordNotFound exception? I need to run it as part of a security check in a :before_filter

Re: Associations and find

najt wrote:

I was looking at eager loading today, but couldn't get it to work. I can't find any reference to the ":projects => :users" definition in the rails api or the "agile" book.

That technique is hardly known it seems. I've only seen it used a few places.


najt wrote:

Couldn't I just do a query like the first one (but for a specific candidate) and check for a RecordNotFound exception? I need to run it as part of a security check in a :before_filter

Yep. This will make sure to keep it all in one query as well. But you wouldn't check for RecordNotFound, instead check if the returned variable is nil.

Railscasts - Free Ruby on Rails Screencasts