【问题标题】:Mutual friends as an ActiveRecord Arel Relation共同朋友作为 ActiveRecord Arel 关系
【发布时间】:2012-05-11 14:46:02
【问题描述】:

我的用户有以下型号:

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

如果 id 为 53 的用户和 id 为 97 的用户是彼此的朋友,那么您在数据库的 facebook_friendships 表中将有 [53, 97] 和 [97, 53] 行。这是我用来计算共同朋友的原始 sql 查询:

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

我会mutual_friends_with 返回一个关系而不是一个数组。这样,我可以将结果与 where(college: 'NYU') 等其他条件链接起来,并获得 ActiveRecord 的所有优点。有什么好办法吗?

【问题讨论】:

  • 看看 dispora 应用程序 - github.com/diaspora/diaspora。它是一个社交网络应用程序......他们一定已经为您的问题找到了一个不错的解决方案:)。提示:可能你必须在 FacebookFriendship 上添加一些 has_many 关系到 FacebookFriendship

标签: ruby-on-rails activerecord relational-algebra


【解决方案1】:

你试过#find_by_sql吗?

http://guides.rubyonrails.org/active_record_querying.html#finding-by-sql

如果您想使用自己的 SQL 在表中查找记录,您可以 使用 find_by_sql。 find_by_sql 方法将返回一个数组 即使底层查询只返回一条记录,对象也是如此。为了 例如,您可以运行此查询:

 Client.find_by_sql("SELECT * FROM clients 
                     INNER JOIN orders ON clients.id = orders.client_id   
                     ORDER clients.created_at desc")

find_by_sql 为您提供了一种自定义调用的简单方法 数据库并检索实例化对象。

【讨论】:

  • 我已经在使用 find_by_sql。我想要一个 Arel 关系,因为它允许我在顶部链接其他条件。
【解决方案2】:

这是我用来结交共同朋友的方法。

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-02-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多