docbrown/app/services/search/reading_list.rb
dependabot[bot] 29dcea3750
Bump rubocop-performance from 1.10.2 to 1.11.0 (#13471)
* Bump rubocop-performance from 1.10.2 to 1.11.0

Bumps [rubocop-performance](https://github.com/rubocop/rubocop-performance) from 1.10.2 to 1.11.0.
- [Release notes](https://github.com/rubocop/rubocop-performance/releases)
- [Changelog](https://github.com/rubocop/rubocop-performance/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rubocop/rubocop-performance/compare/v1.10.2...v1.11.0)

Signed-off-by: dependabot[bot] <support@github.com>

* Enable new cops and fix violations

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: rhymes <rhymes@hey.com>
2021-04-22 09:31:25 -05:00

78 lines
2.8 KiB
Ruby

module Search
# This class does not inherit from Search::Base like our other search classes bc it
# is using the FeedContent index to search for ReadingList reaction articles rather than its
# own separate index. The primary function of this class is to help combine and parse reaction
# data with article Elasticsearch data to populate the Reading List view.
class ReadingList
DEFAULT_PAGE = 0
DEFAULT_PER_PAGE = 60
DEFAULT_STATUS = %w[valid confirmed].freeze
# Using a class method here to follow the pattern of the other Search classes
def self.search_documents(params:, user:)
new(params: params, user: user).reading_list_reactions
end
def initialize(params:, user:)
self.status = params.delete(:status) || DEFAULT_STATUS
self.view_page = params.delete(:page) || DEFAULT_PAGE
self.view_per_page = params.delete(:per_page) || DEFAULT_PER_PAGE
self.user = user
self.search_params = params
end
def reading_list_reactions
ordered_articles = parse_and_order_articles(article_docs)
{ "reactions" => paginate_articles(ordered_articles), "total" => total }
end
private
attr_accessor :search_params, :user, :status, :view_page, :view_per_page, :total
def paginate_articles(ordered_articles)
start = view_per_page * view_page
ordered_articles[start, view_per_page] || []
end
def article_docs
return @article_docs if @article_docs
# Gather articles from Elasticsearch based on search criteria containing
# tags, text search, status, and the list of IDs of all articles in a user's
# reading list
docs = FeedContent.search_documents(
params: search_params.merge(
id: search_ids,
class_name: "Article",
page: 0,
per_page: reading_list_article_ids.count,
),
)
self.total = docs.count
@article_docs = docs.index_by { |doc| doc["id"] }
end
def reading_list_article_ids
# Collect all reading list IDs and article IDs for a user
@reading_list_article_ids ||= user.reactions.readinglist.where(status: status).order(id: :desc).pluck(
:reactable_id, :id
).to_h
end
def search_ids
reading_list_article_ids.keys.map { |id| "article_#{id}" }
end
def parse_and_order_articles(articles)
# Combines reaction and article data to create hashes that contain the fields
# the reading list view needs. Ensures articles are returned in order of reaction ID
reading_list_article_ids.filter_map do |article_id, reaction_id|
found_article_doc = articles[article_id]
next unless found_article_doc
{ "id" => reaction_id, "user_id" => user.id, "reactable" => articles[article_id] }
end
end
end
end