Class: CategoryFeaturedTopic

Inherits:
ActiveRecord::Base
  • Object
show all
Defined in:
app/models/category_featured_topic.rb

Constant Summary collapse

NEXT_CATEGORY_ID_KEY =
"category-featured-topic:next-category-id"
DEFAULT_BATCH_SIZE =
100

Class Method Summary collapse

Class Method Details

.clear_batch!Object



42
43
44
# File 'app/models/category_featured_topic.rb', line 42

def self.clear_batch!
  Discourse.redis.del(NEXT_CATEGORY_ID_KEY)
end

.feature_topics(batched: false, batch_size: nil) ⇒ Object

Populates the category featured topics.



11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
# File 'app/models/category_featured_topic.rb', line 11

def self.feature_topics(batched: false, batch_size: nil)
  current = {}
  CategoryFeaturedTopic
    .select(:topic_id, :category_id)
    .order(:rank)
    .each { |f| (current[f.category_id] ||= []) << f.topic_id }

  batch_size ||= DEFAULT_BATCH_SIZE

  next_category_id = batched ? Discourse.redis.get(NEXT_CATEGORY_ID_KEY).to_i : 0

  categories =
    Category
      .select(:id, :topic_id, :num_featured_topics)
      .where("id >= ?", next_category_id)
      .order("id ASC")
      .limit(batch_size)
      .to_a

  if batched
    if categories.length == batch_size
      next_id = Category.where("id > ?", categories.last.id).order(:id).pick(:id)
      next_id ? Discourse.redis.setex(NEXT_CATEGORY_ID_KEY, 1.day, next_id) : clear_batch!
    else
      clear_batch!
    end
  end

  categories.each { |c| CategoryFeaturedTopic.feature_topics_for(c, current[c.id] || []) }
end

.feature_topics_for(c, existing = nil) ⇒ Object



46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
# File 'app/models/category_featured_topic.rb', line 46

def self.feature_topics_for(c, existing = nil)
  return if c.blank?

  query_opts = {
    per_page: c.num_featured_topics,
    except_topic_ids: [c.topic_id],
    visible: true,
    no_definitions: true,
  }

  # It may seem a bit odd that we are running 2 queries here, when admin
  # can clearly pull out all the topics needed.
  # We do so, so anonymous will ALWAYS get some topics
  # If we only fetched as admin we may have a situation where anon can see
  # no featured topics (all the previous 2x topics are only visible to admins)

  # Add topics, even if they're in secured categories or invisible
  query = TopicQuery.new(Discourse.system_user, query_opts)
  results = query.list_category_topic_ids(c)

  # Add some topics that are visible to everyone:
  anon_query = TopicQuery.new(nil, query_opts.merge(except_topic_ids: [c.topic_id] + results))
  results += anon_query.list_category_topic_ids(c)

  results.uniq!
  return if results == existing

  CategoryFeaturedTopic.transaction do
    CategoryFeaturedTopic.where(category_id: c.id).delete_all
    results.each_with_index do |topic_id, idx|
      c.category_featured_topics.create(topic_id: topic_id, rank: idx)
    end
  end
end