我有一个用户模型,其中用户评价其他用户。他们通过与称为评级的表的多对多关联来实现这一点,该表具有与user_id(用户上的多对多自联接)对应的rater_id和ratee_id字段。模型是:
# app/models/user.rb
has_many :ratings_as_rater, class_name: "Rating", foreign_key: "rater_id"
has_many :ratings_as_ratee, class_name: "Rating", foreign_key: "ratee_id"
# app/models/rating.rb
belongs_to :rater, class_name: "User"
belongs_to :ratee, class_name: "User"
评级表上有一个复合索引:
# db/schema.rb
create_table "ratings", force: :cascade do |t|
t.integer "rater_id"
t.integer "ratee_id"
t.integer "rate" # Users rated on scale 1-4
t.index ["ratee_id"], name: "index_ratings_on_ratee_id"
t.index ["rater_id"], name: "index_ratings_on_rater_id"
t.index ["rater_id", "ratee_id"], name: "index_ratings_on_rater_id_and_ratee_id", unique: true
end
在用户索引页面上,我只想显示current_user尚未评级的用户。所以在users_controller而不是:
def index
@users = User.all
end
我如何只显示current_user尚未评级的用户? Current_user id存储在会话cookie中。
答案 0 :(得分:1)
如果您设置了间接关联,那么它很直接:
class User < ApplicationRecord
has_many :ratings_as_rater, class_name: "Rating", foreign_key: "rater_id"
has_many :ratings_as_ratee, class_name: "Rating", foreign_key: "ratee_id"
has_many :raters, through: :ratings_as_ratee,
source: :rater
has_many :rated_users, through: :ratings_as_rater,
source: :ratee
# class level scope to fetch users with no rating
def self.unrated_users
left_outer_joins(:ratings_as_rater).where(ratings: { id: nil })
end
# users not rated by this user
def unrated_users
self.class.where.not(id: self.rated_users)
end
end
一个重要的性能方面是User.where.not(id: self.rated_users)
而非User.where.not(id: self.rated_users.ids)
。这使得ActiveRecord可以构造一个子选择,而不是将数据库中的id拉出到Ruby中,然后将它们放回到一个巨大的长查询中。