Hendrik Mans

ATOM Feeds, yay!

Crankypants now serves ATOM feeds! Here’s mine.

This was a slightly larger project than anticipated, mostly because the Crankypants code base was in need of some cleanup, and I had to take some (small) steps towards a unified interface for run-time settings first.

I couldn’t find any Crystal library for generating ATOM feeds, so I ended up creating my own ATOM module heavily inspired by ActionView’s AtomFeedHelper. Once it’s had some more time to mature, I will happily extract it into its own shard.

This is how I currently use it in Crankypants:

get "posts.atom" do
  uri = URI.parse("http://#{request.host_with_port}/")
  posts = Data.load_posts(limit: 15)

  feed = ATOM.build do |feed|
    feed.title   Crankypants.settings.site_title
    feed.link    URI.join(uri, "/").to_s
    feed.id      URI.join(uri, "/").to_s
    feed.updated posts.map { |p| p.updated_at.not_nil! }.max

    feed.author do |author|
      author.name Crankypants.settings.site_title
      author.uri  URI.join(uri, "/").to_s

    posts.each do |post|
      feed.entry do |entry|
        entry.id      URI.join(uri, post.url).to_s
        entry.title   post.title.presence || "Post from #{post.created_at}"
        entry.link    URI.join(uri, post.url).to_s
        entry.updated post.updated_at || Time.now
        entry.content post.body_html || ""

  render xml: feed

Please ignore the way I’m messing around with URI; I do want to add something soon that will make generating links more convenient, but I’m still trying to figure out the interface.