Stop thinking it's too hard
8 min read
I finally got around and implemented the RSS feed. Wasn't as hard as I expected; piss easy, actually (check the end for the updated version):
get '/feed' do
posts = Dir['posts/*.md'].sort_by!{ |m| m.downcase }.reverse
rss = RSS::Maker.make('2.0') do |maker|
maker.channel.icon = "/public/favicon.ico"
maker.channel.logo = "/public/favicon.ico"
maker.channel.title = 'Roland Leth'
maker.channel.description = 'Roland Leth'
maker.channel.link = "/"
maker.channel.language = 'en'
hours = [0, 1, 2, 3, 20, 21, 22, 23]
maker.items.do_sort = false
posts.each do |post|
matches = post.match(/\/(\d{4})-(\d{2})-(\d{2})-([\w\s\.\}\{\[\]:"';!=\?\+\*\-\)\(]+)\.md$/)
i = maker.items.new_item
i.title = matches[4]
time_string = File.readlines(post)[1]
# in case I forget to fill the time, just create a random hour between 8 PM and 3 AM, that's when I work most of the time
if time_string.length == 8 or time_string.length == 9
time = Date._strptime("#{time_string} EEST","%H:%M %p %Z")
time[:leftover] = nil
else
min = rand(0..59)
time = Date._strptime("#{hours.sample}:#{min} EEST","%H:%M %Z")
end
# titles are written 'Like this', links need to be 'Like-this'
i.link = "http://rolandleth.com/#{matches[4].gsub("\s", "-")}".gsub(";", "")
content = _markdown(File.readlines(post)[3..-1].join())
i.description = content
i.date = DateTime.new(matches[1].to_i, matches[2].to_i, matches[3].to_i, time[:hour], time[:min], 0, time[:zone]).to_time
end
end
rss.to_s
endBut now I had another problem to fix: RSS Readers do not interpret my custom CSS, meaning the hack I did with the underline to show up as italic doesn't work with maker.
Well, I reached GitHub while searching for a solution and it turned out that Sam posted this 4 days ago. TL;DR: He hacked Redcarpet to parse ==text== as <mark>text</mark> and the guys merged his changes. How fortunate :)
get '/feed' do
posts = repository(:default).adapter.select('SELECT * FROM application_posts')
posts.map! { |struc| struc.to_h }
posts.sort! { |a, b| a[:datetime] <=> b[:datetime] }.reverse!
rss ||= RSS::Maker.make('atom') do |maker|
maker.channel.icon = '/public/favicon.ico'
maker.channel.logo = '/public/favicon.ico'
maker.channel.id = 'http://rolandleth.com'
maker.channel.link = 'http://rolandleth.com/feed'
maker.channel.title = 'Roland Leth'
maker.channel.description = 'Roland Leth'
maker.channel.author = 'Roland Leth'
maker.channel.language = 'en'
maker.channel.rights = "© #{Time.now.year} Roland Leth"
maker.channel.subtitle = 'iOS and Ruby development thoughts by Roland Leth.'
maker.items.do_sort = false
posts.each do |post|
i = maker.items.new_item
i.title = post[:title]
date_matches = post[:datetime].match(/(\d{4})-(\d{2})-(\d{2})-(\d{4})/)
time = Date._strptime("#{date_matches[4]} EEST", '%H%M %Z')
i.link = "http://rolandleth.com/#{post[:link]}"
i.content.content = _markdown_for_feed(post[:body].lines[2..-1].join())
i.content.type = 'html'
i.updated = DateTime.new(date_matches[1].to_i, date_matches[2].to_i, date_matches[3].to_i, time[:hour], time[:min], 0, time[:zone]).to_time
i.published = DateTime.new(date_matches[1].to_i, date_matches[2].to_i, date_matches[3].to_i, time[:hour], time[:min], 0, time[:zone]).to_time
# The RSS was last updated when the last post was posted (which is first in the array)
maker.channel.updated ||= DateTime.new(date_matches[1].to_i, date_matches[2].to_i, date_matches[3].to_i, time[:hour], time[:min], 0, time[:zone]).to_time
end
end
rss.link.rel = 'self'
rss.link.type = 'application/atom+xml'
rss.entries.each do |entry|
entry.content.lang = 'en'
entry.title.type = 'html'
end
rss.to_s
end