如何使用activerecord获取朋友的朋友?

时间:2014-12-27 17:05:14

标签: ruby-on-rails ruby activerecord

我使用与http://railscasts.com/episodes/163-self-referential-association中相同的程序实现了朋友关系。我想从同一个城市找朋友的朋友,但我无法弄清楚如何结交朋友和来自同一个城市的朋友。

我试着打电话:

User.find_by(first_name: user_name).friendships.friendships(:f_of_f).cities.where(name: "london").pluck(:f)

它没有用。

我的代码如下:

class User < ActiveRecord::Base
  has_many :friendships
  has_many :friends, through: :friendships
  has_many :inverse_friendships, class_name: 'Friendship', foreign_key: 'friend_id'
  has_many :inverse_friends, through: :inverse_friendships, source: :user
  has_many :cities, through: :user_cities
  has_many :user_cities
  belongs_to :company
  has_many :comments, dependent: :delete_all
  has_many :reviews, dependent: :delete_all
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :trackable, :validatable

  def self.friends_reviews_on_company(user_id, city_id)
    User.find_by(first_name: user_name).friendships.friendships(:f_of_f).cities.where(name: "london").pluck(:f)
  end
end

和城市:

class City < ActiveRecord::Base
  has_many :user_cities
  has_many :users, through: :user_cities
end

和user_city:

class UserCity < ActiveRecord::Base
  belongs_to :city
  belongs_to :user
end

和友谊:

class Friendship < ActiveRecord::Base
  belongs_to :user
  belongs_to :friend, class_name: 'User'
end

错误我尝试了解决方案:

PG::UndefinedTable: ERROR:  missing FROM-clause entry for table "friends_friends_of_friends_join"
LINE 1: ...ndships" "friendships_friends_of_friends_join" ON "friends_f...
                                                             ^
: SELECT  "users".* FROM "users" INNER JOIN "user_cities" ON "user_cities"."user_id" = "users"."id" INNER JOIN "cities" ON "cities"."id" = "user_cities"."city_id" INNER JOIN "friendships" ON "users"."id" = "friendships"."friend_id" INNER JOIN "friendships" "friendships_friends_of_friends_join" ON "friends_friends_of_friends_join"."id" = "friendships_friends_of_friends_join"."friend_id" WHERE "friendships"."user_id" = $1 AND "friendships_friends_of_friends_join"."user_id" = $2 AND "cities"."name" = 'London' LIMIT 1 OFFSET 0
  Rendered search/index.html.erb within layouts/application (8.4ms)
Completed 500 Internal Server Error in 27ms

ActionView::Template::Error (PG::UndefinedTable: ERROR:  missing FROM-clause entry for table "friends_friends_of_friends_join"
LINE 1: ...ndships" "friendships_friends_of_friends_join" ON "friends_f...
                                                             ^
: SELECT  "users".* FROM "users" INNER JOIN "user_cities" ON "user_cities"."user_id" = "users"."id" INNER JOIN "cities" ON "cities"."id" = "user_cities"."city_id" INNER JOIN "friendships" ON "users"."id" = "friendships"."friend_id" INNER JOIN "friendships" "friendships_friends_of_friends_join" ON "friends_friends_of_friends_join"."id" = "friendships_friends_of_friends_join"."friend_id" WHERE "friendships"."user_id" = $1 AND "friendships_friends_of_friends_join"."user_id" = $2 AND "cities"."name" = 'London' LIMIT 1 OFFSET 0):

1 个答案:

答案 0 :(得分:1)

ActiveRecord不是neo4j的宝石,而且你正在遇到ActiveRecord更难的一个重要原因。

我认为这是关于你在没有编写SQL的情况下获得的最有效率:

# Getting a query for multiple friends, even if we're only expecting one so that we can use `includes` method
friend_user_ids = User.where(first_name: user_name).includes(:friendships).map(&:friendships).flatten.map(&:friend_id)

fof_user_ids = Friendship.find(user_id: friend_user_ids).pluck(:friend_id)

city = City.find(name: 'london')
result = User.find(UserCity.where(user_id: fof_user_ids).where(city_id: city.id).pluck(:user_id))

或者你也可以这样做:

city = City.find(name: 'london')   
result_ids = User.where(first_name: user_name)
  .joins('LEFT JOIN friendships ON users.id=friendships.user_id LEFT JOIN friendships AS friendships2 ON friendships.friend_id=friendships2.user_id LEFT JOIN users_cities ON friendships2.friend_id=users_cities.user_id')
  .where('users_cities.city_id = ?', city.id)
  .pluck('friendships2.friend_id')

result = User.find(result_ids)