I have the following models for my user:
class User < ActiveRecord::Base
has_many :facebook_friendships
has_many :facebook_friends, :through => :facebook_friendships, :source => :friend
def mutual_facebook_friends_with(user)
User.find_by_sql ["SELECT users.* FROM facebook_friendships AS a
INNER JOIN facebook_friendships AS b
ON a.user_id = ? AND b.user_id = ? AND a.friend_id = b.friend_id
INNER JOIN users ON users.id = a.friend_id", self.id, user.id]
end
end
class FacebookFriendship < ActiveRecord::Base
belongs_to :user
belongs_to :friend, :class_name => 'User'
end
If user with id 53 and user with id 97 are friends with each other, then you would have rows [53, 97] and [97, 53] in the facebook_friendships table in the database. Here is the raw sql query that I have come up with to calculate mutual friends:
SELECT users.* FROM facebook_friendships AS a
INNER JOIN facebook_friendships AS b
ON a.user_id = :user_a AND b.user_id = :user_b AND a.friend_id = b.friend_id
INNER JOIN users ON users.id = a.friend_id
I would mutual_friends_with to return a relation instead of an Array. This way, I could chain the result with other conditions such as where(college: 'NYU') and get all of that ActiveRecord goodness. Is there a good way to do this?
Have you tried #find_by_sql
?
http://guides.rubyonrails.org/active_record_querying.html#finding-by-sql
If you'd like to use your own SQL to find records in a table you can use find_by_sql. The find_by_sql method will return an array of objects even if the underlying query returns just a single record. For example you could run this query:
Client.find_by_sql("SELECT * FROM clients INNER JOIN orders ON clients.id = orders.client_id ORDER clients.created_at desc")
find_by_sql provides you with a simple way of making custom calls to the database and retrieving instantiated objects.
This is what I use to get mutual friends.
has_many :company_friendships, autosave: true
has_many :company_friends, through: :company_friendships, autosave: true
has_many :inverse_company_friendships, class_name: "CompanyFriendship", foreign_key: "company_friend_id", autosave: true
has_many :inverse_company_friends, through: :inverse_company_friendships, source: :company, autosave: true
def mutual_company_friends
Company.where(id: (company_friends | inverse_company_friends).map(&:id))
end
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.