ActiveRecord Query:使用范围链

时间:2017-11-17 17:03:58

标签: ruby-on-rails ruby activerecord

我在通过ActiveRecord查询创建类方法时遇到了困难:

我创建了一个名为popular_users的类方法,用于按照关注者的数量对用户进行排序,但它没有返回任何结果。问题在于friend_id: self我相信。如果我使用friend_id: User.first在rails控制台中测试它可以工作。 (friend_id是被跟踪者的身份)

class User < ApplicationRecord

  # received friend (ie a follower): other user sends a request which has been accepted by current user
  has_many :friendships
  has_many :received_friendships, class_name: "Friendship", foreign_key: "friend_id"
  has_many :received_friends, -> { where(friendships: { accepted: true}) }, through: :received_friendships, source: :user

  def self.popular_users
    self.joins(:friendships)
        .where(friendships: {accepted: true, friend_id: self})
        .group("users.id")
        .select("users.id, count(friendships) AS followers_count")
        .order("followers_count DESC")
  end

我尝试过以下方法,但会导致此错误:

  

ActiveRecord :: StatementInvalid:PG :: SyntaxError:ERROR:语法错误   在“SELECT”附近或附近

  def self.popular_users
    self.joins(:friendships)
        .group("users.id")
        .select("SELECT COUNT(friend_id) FROM friendships WHERE (user_id = :user_id AND accepted = 't')) AS followers_count")
        .order("followers_count DESC")
  end

架构:

  create_table "friendships", force: :cascade do |t|
    t.integer "user_id"
    t.integer "friend_id"
    t.boolean "accepted", default: false
  end

  create_table "users", force: :cascade do |t|
    t.string "email", default: "", null: false
    t.string "encrypted_password", default: "", null: false
    t.string "name"
  end

更新:这是我的回答

  def self.popular_users
    self.joins("RIGHT JOIN friendships ON friendships.friend_id = users.id AND friendships.accepted = 't'")
        .group("users.id")
        .select("users.id, count(users.id) AS followers_count")
        .order("followers_count DESC")
  end

例如在rails控制台中测试:

Friendship.create(user_id: 1, friend_id: 2, accepted: true)
Friendship.create(user_id: 4, friend_id: 2, accepted: true)
Friendship.create(user_id: 5, friend_id: 2, accepted: true)
Friendship.create(user_id: 1, friend_id: 3, accepted: true)
Friendship.create(user_id: 2, friend_id: 3, accepted: true)

在控制台中输入User.popular_users <{1}}后返回结果#<ActiveRecord::Relation [#<User id: 2, followers_count: 3>, #<User id: 3, followers_count: 2>]>

2 个答案:

答案 0 :(得分:0)

在类方法的上下文中,

var result = Rx.Observable.fromPromise(yourPromiseFunction()); result.subscribe(el => console.log(el)); 将是类对象本身。

self

您需要将所需的ID传递给您的类方法,例如:

class Test
  def self.test
    self
  end

  def test
    self
  end
end

Test.test
#=> Test

Test.new.test 
#=> #<Test:0x0000010f624bb0>

答案 1 :(得分:0)

假设两个不同的用户只能拥有一个友谊,请尝试以下方法:

class User < ApplicationRecord
  # . . .

  def self.popular_users
    self.joins(:friendships)
      .where( friendships: { accepted: true } )
      .group("users.id")
      .select("users.id, COUNT(users.id) AS followers_count")
      .order("COUNT(users.id) DESC")
  end

  # . . .
end

joinusers的{​​{1}}将为每个用户提取friendships的所有行(并且friendships将加入结果限制为仅接受你原来希望的友谊)。因此,where就足够了 - 这将计算每个用户在联接中出现的总行数(友谊)。

此外,大多数SQL变体不允许您像COUNT(users.id)那样命名别名,然后在followers_count子句中使用该别名,所以我更一般地写了我的答案,以防万一也可能是你问题的一部分。