Has_many with :finder_sql question


#1

hi all,

I have a Class, Client, which has_many projects (Project class). the
projects depend on a session_id variable, however. So the question
is, how can I do the following:

has_many :projects,
:finder_sql => “SELECT p.* FROM projects p INNER JOIN
projects_users pu ON pu.project_id = p.id WHERE pu.user_id =
#{session[:user_id]}”

The problem is that I need to filter a client’s projects using a
session variable, and the :finder_sql produces the error:

“undefined local variable or method `session’ for Client:Class”

I thought that I could be sure the variable existed be creating a
default one in the initialize definition in the Client class, but that
doesn’t work either.

Thanks!

rich


#2

Rich B. wrote:

session variable, and the :finder_sql produces the error:

“undefined local variable or method `session’ for Client:Class”

I thought that I could be sure the variable existed be creating a
default one in the initialize definition in the Client class, but that
doesn’t work either.

In general, Models shouldn’t be aware of sessions. The session accessor
is a controller method.

I’m having trouble relating your SQL to your description - is it User or
Client that has the Projects, and is it has_many (which wouldn’t require
a join table) or has_and_belongs_to_many (which would)?

Suppose a User has_many Projects, and you have the user id in the
session under the key :user_id.

If all you need to do is get the current user’s projects, you should be
able to do something like this (untested) in a controller action:

@user = User.find(session[:user_id])
@projects = @user.projects

You don’t need to specify the SQL in the model.

If you are worried about making two queries rather than one, you can use
the :include option to tell the find to include projects.

If this has to happen in many different actions, consider putting it in
a before filter in the controller.

Another point that may be useful - in the current version of Rails you
can also use find methods on collections, e.g.

@project = @user.projects.find(proj_id)

This ensures that a user only sees his/her own projects, even if they
tamper with the id being passed back from the browser.

regards

Justin