docbrown/app/labor/article_suggester.rb
rhymes c8abbe9d60 Pro: memberships (#3461)
* Add ProMembership model

* Implement ProMembershipsController#create

* Implement basic ProMembershipsController#show

* Add ProMembership to ledger

* Populate user history after pro subscription is created

* Add fields for expiration notifications

* Add ProMemberships::ExpirationNotifier to notify users of expiring memberships

* Add tasks for recurring jobs to notify users of expiration

* Add auto_recharge column to ProMembership

* Add ProMemberships::Biller (incomplete)

* Fix specs

* Add ProMembership to Administrate

* Fix spec

* Add has_enough_credits? to User and Organization

* Add Payments::Customer class

* Finish ProMembership::Biller functionality

* Fix ProMemberships::Creator check for credits

* Disable destroy actions for ProMembershipsController

* Correctly authenticate ProMembershipsController actions

* Make sure only pro user's history can be indexed

* Add ProMembershipsController#update action for auto recharge

* Use regular AR to save new credits and add touch to the purchaser

* Clarify Pro membership create policy

* Display information about an existing pro membership

* Add UI to show page

* Add system test for Pro membership creation

* Implement edit membership

* Make sure users with pro memberships can access history and dashboard pro

* Fix padding issue

* Show a different text for a user that has credits but not enough for Pro

* Move Pro Membership functionality inside settings

* Update Pro Membership link in email notifications

* Bust all relevant caches

* Add the Pro checkmark around the website

* Use Users::ResaveArticlesJob instead of delay

* Add/remove user from pro-members chat channel

* Use the appropriate Pro checkmark

* Remove unfinished pro elements

* Remove checkmark JS
2019-09-24 10:38:54 -07:00

51 lines
1.4 KiB
Ruby

class ArticleSuggester
def initialize(article)
@article = article
end
def articles(max: 4)
if article.tag_list.any?
# avoid loading more data if we don't need to
tagged_suggestions = suggestions_by_tag(max: max)
return tagged_suggestions if tagged_suggestions.size == max
# if there are not enough tagged articles, load other suggestions
# ignoring tagged articles that might be relevant twice, hence avoiding duplicates
num_remaining_needed = max - tagged_suggestions.size
other_articles = other_suggestions(
max: num_remaining_needed,
ids_to_ignore: tagged_suggestions.pluck(:id),
)
tagged_suggestions.union(other_articles)
else
other_suggestions(max: max)
end
end
private
attr_reader :article
def other_suggestions(max: 4, ids_to_ignore: [])
ids_to_ignore << article.id
Article.published.where(featured: true).
where.not(id: ids_to_ignore).
order("hotness_score DESC").
includes(user: [:pro_membership]).
offset(rand(0..offsets[1])).
first(max)
end
def suggestions_by_tag(max: 4)
Article.published.tagged_with(article.tag_list, any: true).
where.not(id: article.id).
order("hotness_score DESC").
includes(user: [:pro_membership]).
offset(rand(0..offsets[0])).
first(max)
end
def offsets
Rails.env.production? ? [10, 120] : [0, 0]
end
end