Skip to content

Instantly share code, notes, and snippets.

@madx
Created December 17, 2009 16:26
Show Gist options
  • Save madx/258844 to your computer and use it in GitHub Desktop.
Save madx/258844 to your computer and use it in GitHub Desktop.
require 'time'
require 'pathname'
module Honk
extend self
attr_reader :posts, :tags
@posts = []
@tags = {}
def reload!
@posts = Dir['posts/*.txt'].map {|path| Post.open(path) }
@posts.map {|p| p.tags }.tap do |ts|
@tags = ts.flatten.uniq.inject({}) {|h,t|
h.merge({t => tags.count(t)})
}
end
end
class Post
attr_accessor :date, :slug, :title, :body, :tags
class << self
def open(path)
path = Pathname.new(path)
new.tap {|p|
p.date, p.slug = parse_path(path)
header, p.body = path.read.split(/^---+$/, 2)
p.title, p.tags = parse_header(header)
}
end
private
def parse_header(header)
title = header.gsub(/\{#.+\}/, '').gsub(/#(\w+)/, '\1').strip
tags = header.scan(/#(\w+)/).flatten.map {|t| t.downcase }.uniq
return [title, tags]
end
def parse_path(path)
date, slug = path.basename(path.extname).to_s.split('_', 2)
base, increment = date.split('+')
[Time.parse(base) + increment.to_i, slug]
end
private :new
end
end
class App
end
end
if __FILE__ == $0
require File.join(File.dirname(__FILE__), 'microtest')
class Object
def expose_private_methods!
class << self
@__priv = private_instance_methods
private_instance_methods.each {|meth| public meth.to_sym }
end
end
def hide_private_methods!
class << self
(@__priv || []).each {|meth| private meth.to_sym }
end
end
end
context 'A post' do
setup { @post = Honk::Post.open('posts/2009-12-17_my_first_post.txt') }
test do
assert('has a date') { @post.date == Time.parse('2009-12-17') }
assert('has a slug') { @post.slug == 'my_first_post' }
assert('has a title') { @post.title == 'My first post with Honk' }
assert('has a body') { @post.body =~ /Hello, world/ }
assert('has tags') {
%w(misc ruby honk).each {|t| @post.tags.member?(t) }
}
end
end
context 'Post private methods:' do
Honk::Post.expose_private_methods!
context '#parse_header()' do
setup {
@title, @tags = Honk::Post.parse_header('Hello #world {#world}')
}
test do
assert('returns unique tags') { @tags == ['world'] }
assert('strips tags from title') { @title == 'Hello world' }
end
end
context '#parse_path()' do
setup { @arr = Honk::Post.parse_path(Pathname.new('2009-01-01_slug.txt')) }
test do
assert('returns the id') {
@arr.first.is_a?(Time) && @arr.first == Time.parse('2009-01-01')
}
assert('returns the slug') { @arr.last == 'slug' }
assert('adds time to the id if needed') {
id = Honk::Post.parse_path(Pathname.new('2009-01-01+1_slug.txt')).first
id == Time.parse('2009-01-01') + 1
}
end
end
Honk::Post.hide_private_methods!
end
context "Honk" do
context "#reload!()" do
setup { Honk.reload! }
test do
assert('loads posts') { Honk.posts.size == 1 }
assert('stores tags') { Honk.tags.keys.size == 3 }
end
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment