Create Atom feed per tag/category in Middleman
I use Middleman as static page genarator for this website. One question I often get is how to build separate Atom feed for every category/tag that I use on this site. Here is solution that I end up using almost a year ago.
Code that I placed at the end of config.rb
file:
def get_tags(resource)
if resource.data.tags.is_a? String
resource.data.tags.split(',').map(&:strip)
else
resource.data.tags
end
end
def group_lookup(resource, sum)
results = Array(get_tags(resource)).map(&:to_s).map(&:to_sym)
results.each do |k|
sum[k] ||= []
sum[k] << resource
end
end
tags_for_feed = resources.select { |resource| resource.data.tags }.each_with_object({}, &method(:group_lookup))
require 'middleman-blog/uri_templates'
class Middleman::CoreExtensions::Collections::StepContext
include Middleman::Blog::UriTemplates
end
tags_for_feed.each do |tag, articles|
proxy "/articles/tags/#{safe_parameterize(tag)}/feed.xml", '/tag_feed.xml',
layout: false, locals: { tagname: tag, articles: articles }
end
ignore '/tag_feed.xml'
And my sourcs/tag_feed.xml
looks like this:
xml.instruct!
xml.feed "xmlns" => "http://www.w3.org/2005/Atom" do
site_url = data.site.url
xml.title "Simplify - Articles tagged with #{tagname}"
xml.subtitle data.site.description
xml.id URI.join(site_url, tag_path(tagname))
xml.link "href" => URI.join(site_url, tag_path(tagname))
xml.link "href" => URI.join(site_url, current_page.path), "rel" => "self"
xml.updated(blog.articles.first.date.to_time.iso8601) unless blog.articles.empty?
xml.author { xml.name data.site.author }
articles.sort_by {|a| a.date }.reverse.each do |article|
xml.entry do
xml.title article.title
xml.link "rel" => "alternate", "href" => URI.join(site_url, article.url)
xml.id URI.join(site_url, article.url)
xml.published article.date.to_time.iso8601
xml.updated File.mtime(article.source_file).iso8601
xml.author { xml.name data.site.author }
xml.content article.body, "type" => "html"
end
end
end