Rails 3 Finding and Grouping over multiple tables with at least one matching parameter
I have a database of Users. Users have Skills and Interests which relate to the same Tags table. I need to create a search query that takes an array of Tags and finds all users with at least one of those tags as a Skill, ordered by largest number found.
From the little bit of SQL I know, I'm thinking:
- join the users table with the skills (tags) table
- filter by tags that are within the provided array
- then group by user id
- add a having > 0 on the count
and returning that result. The problem is I can't figure out how to do that with Rails.
So if someone could say whether this is the correct method or not, and how to do so in Rails, I'd much appreciate it.
#User Model class User < ActiveRecord::Base has_and_belongs_to_many :skills, :class_name => "Tag", :join_table => "skills_users" has_and_belongs_to_many :interests, :class_name => "Tag", :join_table => "interests_users" end #Tag Model class Tag < ActiveRecord::Base has_and_belongs_to_many :skilled_users, :class_name => "User", :join_table => "skills_users" has_and_belongs_to_many :interested_users, :class_name => "User", :join_table => "interests_users" end
Update
I did find this, which would work but I feel like its a hack around method for solving this. Rails finding all posts with certain tags without using acts_as_taggable
Update 2
User.find(:all, :joins => :skills, :conditions => { :tags => { :id => [1,2,3] }})
I was able to get a list of all users who had any of the skills passed in. This mean duplicate rows. Unfortunately when I grouped by user id, they didn't group because the Tag information was attached to the row. I also haven't figure out how to count the tags.
Answers
I'll answer my own question just in case others come looking for the same type of problem.
users = User.find(:all, :include => :skills, :conditions => { :tags => { :id => [1, 2, 3] } } )
This loads only the users with skills in the id range, and only those skills. Now I can sort by the size of their skills and return.
sorted = users.sort {|a,b| b.skills.size <=> a.skills.size}