Paul Barry
2006-May-07 16:16 UTC
[Rails] Find records not in join with has_many_and_belongs_to
I have a User and Topic model. A user subscribes to a topic, so there is a
many-to-many relationship between User and Topic. So my User model object
is using has_many_and_belongs_to :topics and vice versa. I want to find all
the topics that a user has *not* subscribed to. This is what I''ve got:
@user = User.find(params[:id])
@topics = Topic.find(:all,
:conditions => ["id not in (select topic_id from topics_users
where
user_id = ?)", @user.id])
I''ve been told that this kind of NOT IN (SUBQUERY) is an inefficient
way of
getting the data, and that using a outer join with an "is null"
criteria is
the way to go. So now I''ve got this:
@user = User.find(params[:id])
@topics = Topic.find(:all,
:joins => "LEFT OUTER JOIN topics_users ON topics.id
topics_users.topic_id "+
"AND topics_users.user_id = #{@user.id}",
:conditions => ["topics_users.topic_id is null"])
Is there a cleaner way of doing this? First of all, the biggest ugliness of
it is the fact that you have to embed the user.id in join string. It
doesn''t open up a SQL injection vunerability in this case, but it would
be
nice to be able to do this:
@user = User.find(params[:id])
@topics = Topic.find(:all,
:joins => ["LEFT OUTER JOIN topics_users ON topics.id
topics_users.topic_id "+
"AND topics_users.user_id = ?", @user.id],
:conditions => ["topics_users.topic_id is null"])
This would be nice too, to get rid of some of the SQL and be able to
specific a table to outer join and then send it some conditions:
@user = User.find(params[:id])
@topics = Topic.find(:all,
:outer_joins => ["topic_users", ["user_id = ?",
@user.id]],
:conditions => ["topics_users.topic_id is null"])
-------------- next part --------------
An HTML attachment was scrubbed...
URL:
http://wrath.rubyonrails.org/pipermail/rails/attachments/20060507/dccd922f/attachment.html
Josh Susser
2006-May-07 17:31 UTC
[Rails] Re: Find records not in join with has_many_and_belongs_to
Paul Barry wrote:> I have a User and Topic model. A user subscribes to a topic, so there > is a many-to-many relationship between User and Topic. So my User model > object is using has_many_and_belongs_to :topics and vice versa. I want to find > all the topics that a user has *not* subscribed to.Unless you have like a kajillion topics and there are performance problems, it''s far easier to do this in Ruby code. non_topics = Topic.find(:all) - user.topics -- Josh Susser http://blog.hasmanythrough.com -- Posted via http://www.ruby-forum.com/.