docbrown/app/services/users/suggest_recent.rb
Michael Kohl 1b87cc7626
Profile generalization cleanup phase 2 (#14555)
* Remove ignored profile columns

* Update test.rb

* Remove dev profile fields CSV

* Fix first round of specs

* Add additional .includes

* More spec fixes

* Preload user in more locations

* Fix typo

* Spec/preloading fixes

* Specy McSpecFace

* Update e2e seeds

* Update e2e sees with correct display area

* Remove unused eager loading

* Update test.rb

* Add another entry to Bullet.safe_list

* Fix e2e seeds
2021-08-27 09:17:26 +07:00

81 lines
2.6 KiB
Ruby

module Users
class SuggestRecent
def self.call(user, attributes_to_select: [])
new(user, attributes_to_select: attributes_to_select).suggest
end
def initialize(user, attributes_to_select: [])
@user = user
@cached_followed_tag_names = user.decorate.cached_followed_tag_names
@attributes_to_select = attributes_to_select
end
def suggest
if cached_followed_tag_names.any?
(recent_producers(3) - [user]).sample(50).uniq
else
(recent_commenters(4, 30) + recent_top_producers - [user]).uniq.sample(50)
end
end
private
attr_reader :user, :attributes_to_select, :cached_followed_tag_names
def tagged_article_user_ids(num_weeks = 1)
Article.published
.tagged_with(cached_followed_tag_names.sample(5), any: true)
.where(score: article_score_average.., published_at: num_weeks.weeks.ago..)
.pluck(:user_id)
.each_with_object(Hash.new(0)) { |value, counts| counts[value] += 1 }
.sort_by { |_key, value| value }
.map(&:first)
end
def recent_producers(num_weeks = 1)
relation_as_array(
user_relation.where(id: tagged_article_user_ids(num_weeks)),
limit: 80,
)
end
def recent_top_producers
relation = user_relation.where(
articles_count: established_user_article_count..,
comments_count: established_user_comment_count..,
)
relation_as_array(relation, limit: 50)
end
def recent_commenters(num_comments = 2, limit = 8)
relation_as_array(user_relation.where(comments_count: num_comments + 1..), limit: limit)
end
def relation_as_array(relation, limit:)
relation = relation.joins(:profile).select(attributes_to_select) if attributes_to_select.any?
relation.order(updated_at: :desc).limit(limit).to_a
end
def established_user_article_count
Rails.cache.fetch("established_user_article_count", expires_in: 1.day) do
user_relation.where(articles_count: 1..).average(:articles_count) || User.average(:articles_count)
end
end
def established_user_comment_count
Rails.cache.fetch("established_user_comment_count", expires_in: 1.day) do
user_relation.where(comments_count: 1..).average(:comments_count) || User.average(:comments_count)
end
end
def article_score_average
Rails.cache.fetch("article_score_average", expires_in: 1.day) do
Article.where(score: 0..).average(:score) || Article.average(:score)
end
end
def user_relation
User.includes(:profile)
end
end
end