discourse/app/models/category_user.rb

194 lines
5.5 KiB
Ruby
Raw Normal View History

# frozen_string_literal: true
require_dependency 'notification_levels'
class CategoryUser < ActiveRecord::Base
belongs_to :category
belongs_to :user
def self.lookup(user, level)
self.where(user: user, notification_level: notification_levels[level])
end
2014-04-17 17:17:39 +08:00
def self.lookup_by_category(user, category)
self.where(user: user, category: category)
end
def self.notification_levels
NotificationLevels.all
2016-07-06 03:16:32 +08:00
end
def self.watching_levels
[notification_levels[:watching], notification_levels[:watching_first_post]]
end
def self.batch_set(user, level, category_ids)
records = CategoryUser.where(user: user, notification_level: notification_levels[level])
old_ids = records.pluck(:category_id)
changed = false
category_ids = Category.where('id in (?)', category_ids).pluck(:id)
remove = (old_ids - category_ids)
if remove.present?
records.where('category_id in (?)', remove).destroy_all
changed = true
end
(category_ids - old_ids).each do |id|
CategoryUser.create!(user: user, category_id: id, notification_level: notification_levels[level])
changed = true
end
if changed
auto_watch(user_id: user.id)
auto_track(user_id: user.id)
end
changed
end
2014-04-17 17:17:39 +08:00
def self.set_notification_level_for_category(user, level, category_id)
record = CategoryUser.where(user: user, category_id: category_id).first
return if record && record.notification_level == level
2014-04-17 17:17:39 +08:00
if record.present?
record.notification_level = level
record.save!
else
begin
CategoryUser.create!(user: user, category_id: category_id, notification_level: level)
rescue ActiveRecord::RecordNotUnique
# does not matter
end
2014-04-17 17:17:39 +08:00
end
auto_watch(user_id: user.id)
auto_track(user_id: user.id)
2014-04-17 17:17:39 +08:00
end
2017-07-28 09:20:09 +08:00
def self.auto_track(opts = {})
builder = DB.build <<~SQL
UPDATE topic_users tu
SET notification_level = :tracking,
notifications_reason_id = :auto_track_category
FROM topics t, category_users cu
/*where*/
SQL
builder.where("tu.topic_id = t.id AND
cu.category_id = t.category_id AND
cu.user_id = tu.user_id AND
cu.notification_level = :tracking AND
tu.notification_level = :regular")
if category_id = opts[:category_id]
builder.where("t.category_id = :category_id", category_id: category_id)
end
if topic_id = opts[:topic_id]
builder.where("tu.topic_id = :topic_id", topic_id: topic_id)
end
if user_id = opts[:user_id]
builder.where("tu.user_id = :user_id", user_id: user_id)
end
builder.exec(
tracking: notification_levels[:tracking],
regular: notification_levels[:regular],
2018-12-04 17:48:16 +08:00
auto_track_category: TopicUser.notification_reasons[:auto_track_category]
)
end
2017-07-28 09:20:09 +08:00
def self.auto_watch(opts = {})
builder = DB.build <<~SQL
UPDATE topic_users tu
SET notification_level =
CASE WHEN should_track THEN :tracking
WHEN should_watch THEN :watching
ELSE notification_level
END,
notifications_reason_id =
CASE WHEN should_track THEN null
WHEN should_watch THEN :auto_watch_category
ELSE notifications_reason_id
END
FROM (
SELECT tu1.topic_id,
tu1.user_id,
CASE WHEN
cu.user_id IS NULL AND tu1.notification_level = :watching AND tu1.notifications_reason_id = :auto_watch_category THEN true
ELSE false
END should_track,
CASE WHEN
cu.user_id IS NOT NULL AND tu1.notification_level in (:regular, :tracking) THEN true
ELSE false
END should_watch
FROM topic_users tu1
JOIN topics t ON t.id = tu1.topic_id
LEFT JOIN category_users cu ON cu.category_id = t.category_id AND cu.user_id = tu1.user_id AND cu.notification_level = :watching
/*where2*/
) as X
/*where*/
SQL
builder.where("X.topic_id = tu.topic_id AND X.user_id = tu.user_id")
builder.where("should_watch OR should_track")
if category_id = opts[:category_id]
builder.where2("t.category_id = :category_id", category_id: category_id)
end
if topic_id = opts[:topic_id]
builder.where("tu.topic_id = :topic_id", topic_id: topic_id)
builder.where2("tu1.topic_id = :topic_id", topic_id: topic_id)
end
if user_id = opts[:user_id]
builder.where("tu.user_id = :user_id", user_id: user_id)
builder.where2("tu1.user_id = :user_id", user_id: user_id)
end
builder.exec(
watching: notification_levels[:watching],
tracking: notification_levels[:tracking],
regular: notification_levels[:regular],
2018-12-04 17:48:16 +08:00
auto_watch_category: TopicUser.notification_reasons[:auto_watch_category]
)
end
2015-09-03 04:02:31 +08:00
def self.ensure_consistency!
DB.exec <<~SQL
DELETE FROM category_users
WHERE user_id IN (
SELECT cu.user_id FROM category_users cu
LEFT JOIN users u ON u.id = cu.user_id
WHERE u.id IS NULL
)
SQL
2015-09-03 04:02:31 +08:00
end
end
2014-02-07 08:07:36 +08:00
# == Schema Information
#
# Table name: category_users
#
# id :integer not null, primary key
# category_id :integer not null
# user_id :integer not null
# notification_level :integer not null
#
2016-01-11 14:30:56 +08:00
# Indexes
#
# idx_category_users_u1 (user_id,category_id,notification_level) UNIQUE
# idx_category_users_u2 (category_id,user_id,notification_level) UNIQUE
#