module Plate # Post collection is an enumerable wrapper for the posts in a site. class PostCollection include Enumerable attr_accessor :categories, :tags, :archives def initialize @posts = [] @categories = {} @tags = {} @archives = {} end # Add a post to the collection def <<(post) add(post) end # Add a post to the collection, then add its meta data to the summary. def add(post) return nil unless Post === post @posts << post process_post_meta(post) end # A hash of all categories in this collection with the number of posts using each. def category_counts return @category_counts if @category_counts result = {} categories.keys.each do |key| result[key] = categories[key].size end @category_counts = result end # A sorted array of all categories in this collection. def category_list @category_list ||= categories.keys.sort end # Loop through each Post def each @posts.each { |post| yield post } end # Returns the last post in the collection. # # Or, pass in a number to return in descending order that number of posts def last(*args) result = @posts.last(*args) if Array === result result.reverse! end result end # Any methods called on the collection can be passed through to the Array def method_missing(method, *args, &block) @posts.send(method, *args, &block) end # Size of the posts collection def size @posts.size end # A hash of all tags in this collection with the number of posts using that tag. def tag_counts return @tag_counts if @tag_counts result = {} tags.keys.each do |key| result[key] = tags[key].size end @tag_counts = result end # A sorted array of all tag names in this collection. def tag_list @tag_list ||= tags.keys.sort end def to_a @posts end def years @years ||= archives.keys.sort end protected def process_post_meta(post) # load up tags post.tags.each do |tag| @tags[tag] ||= [] @tags[tag] << post end # load up category @categories[post.category] ||= [] @categories[post.category] << post # load up yearly, monthly, and daily archives @archives[post.year] ||= {} @archives[post.year][post.month] ||= {} @archives[post.year][post.month][post.day] ||= [] @archives[post.year][post.month][post.day] << post post end end end