lib/pages_core/archive_finder.rb
# frozen_string_literal: true
module PagesCore
class ArchiveFinder
def initialize(relation, options = {})
@relation = relation
@options = options
end
def by_year(year)
filter_by_time(range_for_year(year))
end
def by_year_and_maybe_month(year, month = nil)
return by_year(year) unless month
by_year_and_month(year, month)
end
def by_year_and_month(year, month)
filter_by_time(range_for_year_and_month(year, month))
end
def latest_year
latest_year_and_month&.first
end
def latest_year_and_month
ordered_relation.first.try do |record|
[record[timestamp_attribute].year,
record[timestamp_attribute].month]
end
end
def months_in_year(year)
select_months(by_year(year)).map(&:to_i).sort
end
def months_in_year_with_count(year)
group_by_month(by_year(year))
.count
.to_a
.sort_by(&:first)
end
def timestamp_attribute
@options[:timestamp] || :created_at
end
def years
select_years(@relation).map(&:to_i).sort
end
def years_with_count
years.map { |year| [year, by_year(year).count] }
end
private
def group_by_month(relation)
relation.reorder("").group(Arel.sql(month_part))
end
def filter_by_time(range)
@relation.where(
"#{timestamp_attribute} >= ? AND #{timestamp_attribute} <= ?",
range.first,
range.last
)
end
def month_part
"date_part('month', #{timestamp_attribute})::integer"
end
def range_for_year(year)
start_time = Time.zone.local(year.to_i, 1, 1)
end_time = start_time.end_of_year
(start_time.in_time_zone)..(end_time.in_time_zone)
end
def range_for_year_and_month(year, month)
start_time = Time.zone.local(year.to_i, month, 1)
end_time = start_time.end_of_month
(start_time.in_time_zone)..(end_time.in_time_zone)
end
def select_months(relation)
relation.reorder("").pluck(Arel.sql("DISTINCT #{month_part}"))
end
def select_years(relation)
relation.reorder("").pluck(Arel.sql("DISTINCT #{year_part}"))
end
def ordered_relation
@relation.reorder("#{timestamp_attribute} DESC")
end
def year_part
"date_part('year', #{timestamp_attribute})"
end
end
end