Migrating To Webby From Typo Using RSS

Jim Mulholland

When Wynn mentioned to me we were passed due our semi-annual blog rewrite / redesign, I wasn’t surprised. We’ve been through this rodeo more than a couple of times over the past couple of years in search of the holy grail of blogging applications.

  • Expression Engine — Left due to PHP and small community
  • WordPress — Left due to PHP (huge community, though) We do still use WordPress quite frequently for small company and family blogs, though.
  • Mephisto — Rails, but we didn’t care for Liquid templates
  • Blogee — An blogging tool build on Rails Engines we created in-house at Squeejee. Unfortunately, we had no interest in maintaining it.
  • Typo — Rails with ERB templates. Typo seemed to work fine, but it was apparently time for a move.

So the fact that we were migrating was not the big deal. The big deal was that we were migrating to Webby which:

  • Does not have a database backend
  • Has no documentation on importing blog articles into it
  • Has no documentation about what to do for comments
  • Happens to share the name with “Webby Awards” which highjacks any Google searche one may do to find information about how to do the prior two bullets.

Luckily for us, Webby’s API docs are well documented. With this at my disposal, I was able to slap together an RSS to Webby rake task.

To do the import, I created an “import_posts” task in Webby’s “tasks/blog.rake” file. This new task requires the very cool FeedTools gem to parse the RSS feed. Here is the code:

 1 require 'feed_tools'
 2         
 3 desc "Import Blog posts from RSS feed"
 4 task :import_posts do |t|
 5   # Updated the following url with your current blog rss feed
 6   blog_posts = FeedTools::Feed.open("http://feeds.feedburner.com/my_cool_blog")
 7   
 8   blog_posts.items.each do |post|
 9     ENV['created_at'] = post.time.to_s
10     
11     #####################################################################
12     ## This is a copy/paste of Webby::Apps:Main.capture_command_line_args
13     ## I wasn't able to get the call to the method to work.  I will come back to it later.
14     args = OpenStruct.new(:raw => [post.title])
15 
16     if args.raw.size > 1
17       ::Webby.deprecated "multiple arguments used for page title",
18                          "please quote the page title"
19     end
20 
21     dashed = args.raw.join('-').downcase
22     spaced = args.raw.join(' ')
23     dir = ::File.dirname(dashed)
24 
25     args.dir   = ('.' == dir ? '' : dir)
26     args.slug  = ::Webby::Resources.basename(dashed).to_url
27     args.title = ::Webby::Resources.basename(spaced).titlecase
28 
29     # page should be dir/slug without leading /
30     args.page  = ::File.join(args.dir, args.slug).gsub(/^\//, '')
31 
32     ext = ::File.extname(dashed)
33     args.page << ext unless ext.empty?
34 
35     ::Webby.site.args = args
36     
37     #####################################################################
38     
39     Rake::Task["blog:create_year_index"].execute
40     Rake::Task["blog:create_month_index"].execute
41     
42     page, title, dir = Webby::Builder.new_page_info
43 
44     # if no directory was given use the default blog directory (underneath
45     # the content directory)
46     dir = Webby.site.blog_dir if dir.empty?
47     dir = File.join(dir, ENV['created_at'].to_date.strftime('%Y/%m/%d'))
48 
49     page = File.join(dir, File.basename(page))
50     page = Webby::Builder.create(page, :from => "#{Webby.site.template_dir}/import_post.erb",
51                :locals => {:title => title, :directory => dir, :author => post.author.name, :description => post.description, :created_at => ENV['created_at'].to_time})
52     exec(::Webby.editor, page) unless ::Webby.editor.nil?
53   end
54 end

Also, the existing “create_month_index” and “create_year_index” tasks within the Webby rake file assume that you will be creating a new blog file today. Since we are importing old posts, this assumption is not correct.

Therefore, in the “create_year_index” task, I updated this

1 year = Time.now.strftime '%Y'

to this

1 if ENV['created_at']
2   year = ENV['created_at'].to_date.strftime '%Y'
3 else
4   year = Time.now.strftime '%Y'
5 end

And in the “create_month_index” task, I updated this

1 now = Time.now

to this

1 if ENV['created_at']
2   now = ENV['created_at'].to_date
3 else
4   now = Time.now
5 end

This code could probably use some tuning up, but it did the job for us for both our Squeejee and our Locomotivation blogs. It was nice to be able to do the entire import via RSS and not worry about database dumps, csv exports, or anything like that.

With the post import out of the way, I next had to figure out how to import all of our comments into Disqus. I will blog how we went about doing this with a Ruby script next week.