hackety_sling 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +5 -0
- data/Gemfile +4 -0
- data/Rakefile +7 -0
- data/hackety_sling.gemspec +23 -0
- data/lib/sinatra/hackety_sling/post.rb +26 -0
- data/lib/sinatra/hackety_sling/version.rb +5 -0
- data/lib/sinatra/hackety_sling.rb +79 -0
- data/test/hackety_sling_test.rb +142 -0
- data/test/post_test.rb +19 -0
- data/test/test_app.rb +6 -0
- data/test/test_posts/2010-08-09-test-post-1.textile +8 -0
- data/test/test_posts/2010-08-10-test-post-2.textile +7 -0
- data/test/test_posts/2010-11-13-test-post-3.textile +8 -0
- data/test/test_posts/2011-02-28-test-post-4.textile +7 -0
- data/views/index.erubis +4 -0
- data/views/post.erubis +2 -0
- data/views/post_list.erubis +3 -0
- data/views/posts.erubis +4 -0
- metadata +125 -0
data/Gemfile
ADDED
data/Rakefile
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path('../lib', __FILE__)
|
3
|
+
require 'sinatra/hackety_sling/version'
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = 'hackety_sling'
|
7
|
+
s.version = Sinatra::HacketySling::VERSION
|
8
|
+
s.authors = ['Ralph von der Heyden']
|
9
|
+
s.email = ['ralph@rvdh.de']
|
10
|
+
s.homepage = 'http://rvdh.de'
|
11
|
+
s.summary = %q{A simple blog engine based on Sinatra and document_mapper}
|
12
|
+
s.description = %q{A simple blog engine based on Sinatra and document_mapper}
|
13
|
+
|
14
|
+
s.files = `git ls-files`.split("\n")
|
15
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
16
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
17
|
+
s.require_paths = ['lib']
|
18
|
+
s.add_dependency 'document_mapper'
|
19
|
+
s.add_dependency 'erubis'
|
20
|
+
s.add_dependency 'sinatra'
|
21
|
+
s.add_dependency 'ratom'
|
22
|
+
s.add_development_dependency 'rack-test'
|
23
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'document_mapper'
|
2
|
+
|
3
|
+
module Sinatra
|
4
|
+
module HacketySling
|
5
|
+
class Post
|
6
|
+
include DocumentMapper::Document
|
7
|
+
|
8
|
+
self.directory = File.expand_path('../../../../test/test_posts', __FILE__)
|
9
|
+
|
10
|
+
def permalink
|
11
|
+
[
|
12
|
+
self.date_permalink,
|
13
|
+
self.file_name_without_extension.sub(/^\d{4}-\d{2}-\d{2}-/, '')
|
14
|
+
].join('') + '/'
|
15
|
+
end
|
16
|
+
|
17
|
+
def date_permalink
|
18
|
+
'/' + ([
|
19
|
+
sprintf("%04d", self.date.year),
|
20
|
+
sprintf("%02d", self.date.month),
|
21
|
+
sprintf("%02d", self.date.day)
|
22
|
+
].join '/') + '/'
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,79 @@
|
|
1
|
+
require 'bundler/setup'
|
2
|
+
require 'sinatra/base'
|
3
|
+
require 'sinatra/hackety_sling/post'
|
4
|
+
require 'atom'
|
5
|
+
|
6
|
+
module Sinatra
|
7
|
+
module HacketySling
|
8
|
+
def self.registered(app)
|
9
|
+
app.set :hackety_sling_posts_on_index, 2
|
10
|
+
app.set :hackety_sling_title, nil
|
11
|
+
app.set :hackety_sling_author, nil
|
12
|
+
|
13
|
+
app.get '/' do
|
14
|
+
limit = app.hackety_sling_posts_on_index
|
15
|
+
@posts = Post.order_by(:date => :desc).limit(limit).all
|
16
|
+
erubis :index
|
17
|
+
end
|
18
|
+
|
19
|
+
app.get '/archive/' do
|
20
|
+
@posts = Post.order_by(:date => :asc).all
|
21
|
+
erubis :post_list
|
22
|
+
end
|
23
|
+
|
24
|
+
%w(tags author).each do |attribute|
|
25
|
+
app.get "/#{attribute}/:value/" do |value|
|
26
|
+
@posts = Post.order_by(:date => :desc)
|
27
|
+
@posts = @posts.where(attribute.to_sym.include => value).all
|
28
|
+
erubis :posts
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
Post.all.each do |post|
|
33
|
+
app.get post.permalink do
|
34
|
+
@post = post
|
35
|
+
erubis :post
|
36
|
+
end
|
37
|
+
base_name = post.file_name_without_extension.sub(/^\d{4}-\d{2}-\d{2}-/, '')
|
38
|
+
app.get "/#{base_name}/" do
|
39
|
+
redirect post.permalink, 301
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
ymd = [:year, :month, :day]
|
44
|
+
app.get %r{^/(\d{4}/)(\d{2}/)?(\d{2}/)?$} do
|
45
|
+
selector_hash = {}
|
46
|
+
params[:captures].each_with_index do |date_part, index|
|
47
|
+
selector_hash[ymd[index]] = date_part.to_i unless date_part.nil?
|
48
|
+
end
|
49
|
+
@posts = Post.order_by(:date => :desc).where(selector_hash).all
|
50
|
+
erubis :posts
|
51
|
+
end
|
52
|
+
|
53
|
+
app.get '/atom.xml' do
|
54
|
+
feed = Atom::Feed.new do |f|
|
55
|
+
f.title = app.hackety_sling_title ||= 'HacketySling Blog'
|
56
|
+
blog_url = request.url.sub(request.fullpath, '/')
|
57
|
+
f.links << Atom::Link.new(:href => blog_url)
|
58
|
+
f.links << Atom::Link.new(:rel => 'self', :href => request.url)
|
59
|
+
f.updated = Post.last.date.xmlschema + 'T00:00:00+00:00'
|
60
|
+
author = app.hackety_sling_author ||= app.hackety_sling_title
|
61
|
+
f.authors << Atom::Person.new(:name => author)
|
62
|
+
f.id = blog_url
|
63
|
+
Post.order_by(:date => :desc).all.each do |post|
|
64
|
+
f.entries << Atom::Entry.new do |e|
|
65
|
+
e.title = post.title
|
66
|
+
e.links << Atom::Link.new(:href => blog_url + post.permalink)
|
67
|
+
e.id = blog_url + post.permalink
|
68
|
+
e.summary = post.title
|
69
|
+
e.updated = post.date.xmlschema + 'T00:00:00+00:00'
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
feed.to_xml
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
register HacketySling
|
79
|
+
end
|
@@ -0,0 +1,142 @@
|
|
1
|
+
$:.push File.expand_path('../../lib', __FILE__)
|
2
|
+
|
3
|
+
require 'bundler/setup'
|
4
|
+
require 'sinatra/hackety_sling'
|
5
|
+
require 'minitest/spec'
|
6
|
+
require 'minitest/mock'
|
7
|
+
require 'rack/test'
|
8
|
+
MiniTest::Unit.autorun
|
9
|
+
|
10
|
+
require File.expand_path('../test_app', __FILE__)
|
11
|
+
|
12
|
+
ENV['RACK_ENV'] = 'test'
|
13
|
+
|
14
|
+
describe TestApp do
|
15
|
+
include Rack::Test::Methods
|
16
|
+
|
17
|
+
def app
|
18
|
+
TestApp
|
19
|
+
end
|
20
|
+
|
21
|
+
before do
|
22
|
+
@post_titles = Sinatra::HacketySling::Post.all.map(&:title)
|
23
|
+
end
|
24
|
+
|
25
|
+
describe 'when requesting the index path' do
|
26
|
+
it 'should request the 2 most current posts by default' do
|
27
|
+
get '/'
|
28
|
+
assert last_response.ok?
|
29
|
+
refute last_response.body.include? @post_titles[0]
|
30
|
+
refute last_response.body.include? @post_titles[1]
|
31
|
+
assert last_response.body.include? @post_titles[2]
|
32
|
+
assert last_response.body.include? @post_titles[3]
|
33
|
+
end
|
34
|
+
|
35
|
+
it 'the number of posts should be configurable' do
|
36
|
+
app.set :hackety_sling_posts_on_index, 3
|
37
|
+
get '/'
|
38
|
+
assert last_response.ok?
|
39
|
+
refute last_response.body.include? @post_titles[0]
|
40
|
+
assert last_response.body.include? @post_titles[1]
|
41
|
+
assert last_response.body.include? @post_titles[2]
|
42
|
+
assert last_response.body.include? @post_titles[3]
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
describe 'when requesting posts by time' do
|
47
|
+
it 'should show all posts of one year' do
|
48
|
+
get '/2010/'
|
49
|
+
assert last_response.ok?
|
50
|
+
assert last_response.body.include? @post_titles[0]
|
51
|
+
assert last_response.body.include? @post_titles[1]
|
52
|
+
assert last_response.body.include? @post_titles[2]
|
53
|
+
refute last_response.body.include? @post_titles[3]
|
54
|
+
end
|
55
|
+
|
56
|
+
it 'should show all posts of one month' do
|
57
|
+
get '/2010/11/'
|
58
|
+
assert last_response.ok?
|
59
|
+
refute last_response.body.include? @post_titles[0]
|
60
|
+
refute last_response.body.include? @post_titles[1]
|
61
|
+
assert last_response.body.include? @post_titles[2]
|
62
|
+
refute last_response.body.include? @post_titles[3]
|
63
|
+
end
|
64
|
+
|
65
|
+
it 'should show all posts of one day' do
|
66
|
+
get '/2010/08/10/'
|
67
|
+
assert last_response.ok?
|
68
|
+
refute last_response.body.include? @post_titles[0]
|
69
|
+
assert last_response.body.include? @post_titles[1]
|
70
|
+
refute last_response.body.include? @post_titles[2]
|
71
|
+
refute last_response.body.include? @post_titles[3]
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
describe 'when requesting a certain blog post' do
|
76
|
+
it 'should show the blog post' do
|
77
|
+
get '/2010/11/13/test-post-3/'
|
78
|
+
assert last_response.ok?
|
79
|
+
refute last_response.body.include? @post_titles[0]
|
80
|
+
refute last_response.body.include? @post_titles[1]
|
81
|
+
assert last_response.body.include? @post_titles[2]
|
82
|
+
refute last_response.body.include? @post_titles[3]
|
83
|
+
end
|
84
|
+
|
85
|
+
it 'should redirect to the url with date if only the slug was given' do
|
86
|
+
get '/test-post-2/'
|
87
|
+
assert_redirected_to '/2010/08/10/test-post-2/', 301
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
describe 'when requesting posts by tag' do
|
92
|
+
it 'should show all posts with a certain tag' do
|
93
|
+
get '/tags/ruby/'
|
94
|
+
assert last_response.ok?
|
95
|
+
assert last_response.body.include? @post_titles[0]
|
96
|
+
assert last_response.body.include? @post_titles[1]
|
97
|
+
refute last_response.body.include? @post_titles[2]
|
98
|
+
refute last_response.body.include? @post_titles[3]
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
describe 'when requesting posts by author' do
|
103
|
+
it 'should show all posts with a certain author' do
|
104
|
+
get '/author/ralph/'
|
105
|
+
assert last_response.ok?
|
106
|
+
refute last_response.body.include? @post_titles[0]
|
107
|
+
refute last_response.body.include? @post_titles[1]
|
108
|
+
assert last_response.body.include? @post_titles[2]
|
109
|
+
refute last_response.body.include? @post_titles[3]
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
describe 'when requesting the archive page' do
|
114
|
+
it 'should respond to the archive path' do
|
115
|
+
get '/archive/'
|
116
|
+
assert last_response.ok?
|
117
|
+
@post_titles.each do |post_title|
|
118
|
+
assert last_response.body.include? post_title
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
describe 'the atom feed' do
|
124
|
+
it 'should be generated ok' do
|
125
|
+
get '/atom.xml'
|
126
|
+
assert last_response.ok?
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
def url(path)
|
131
|
+
"http://example.org#{path}"
|
132
|
+
end
|
133
|
+
|
134
|
+
def assert_redirected_to(path, status = 301)
|
135
|
+
redirect_url = last_response.headers['Location']
|
136
|
+
status_msg = message(status_msg) { "Expected to be redirected with status #{status}, but was #{last_response.status}" }
|
137
|
+
location_msg = message(location_msg) { "Expected to be redirected to #{path}, but was #{redirect_url}" }
|
138
|
+
assert status == last_response.status, status_msg
|
139
|
+
assert (path == redirect_url || url(path) == redirect_url), location_msg
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
data/test/post_test.rb
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
$:.push File.expand_path('../../lib', __FILE__)
|
2
|
+
|
3
|
+
require 'bundler/setup'
|
4
|
+
require 'minitest/spec'
|
5
|
+
require 'minitest/mock'
|
6
|
+
MiniTest::Unit.autorun
|
7
|
+
|
8
|
+
require 'sinatra/hackety_sling/post'
|
9
|
+
include Sinatra::HacketySling
|
10
|
+
|
11
|
+
describe Post do
|
12
|
+
it 'should return the correct date permalink' do
|
13
|
+
assert_equal '/2010/08/09/', Post.first.date_permalink
|
14
|
+
end
|
15
|
+
|
16
|
+
it 'should return the correct permalink' do
|
17
|
+
assert_equal '/2010/08/09/test-post-1/', Post.first.permalink
|
18
|
+
end
|
19
|
+
end
|
data/test/test_app.rb
ADDED
@@ -0,0 +1,8 @@
|
|
1
|
+
---
|
2
|
+
title: Test post 3
|
3
|
+
tags: [travel, leica, bw]
|
4
|
+
title_photo: 4735071835
|
5
|
+
author: ralph
|
6
|
+
---
|
7
|
+
|
8
|
+
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque commodo, erat convallis feugiat faucibus, dolor turpis faucibus sapien, eget fringilla arcu purus sit amet leo. Nulla iaculis bibendum elit, sollicitudin scelerisque arcu pulvinar ut. Nulla faucibus, eros nec lacinia placerat, dui elit pulvinar libero, ut vulputate massa lectus et augue. Nulla a mauris nulla. Suspendisse suscipit nisl volutpat augue condimentum dignissim. Pellentesque consequat fringilla dolor vitae aliquet. Aliquam non urna in urna commodo fermentum quis et mi. Proin sapien nunc, pretium nec commodo vel, aliquet vitae nisl. Cras interdum purus non nunc malesuada imperdiet. Praesent et metus risus, aliquam sollicitudin nunc. Nam at est ante. Nunc sed erat nulla, nec elementum sapien.
|
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
title: Test post 4
|
3
|
+
tags: [travel, leica, bw]
|
4
|
+
title_photo: 4735071835
|
5
|
+
---
|
6
|
+
|
7
|
+
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque commodo, erat convallis feugiat faucibus, dolor turpis faucibus sapien, eget fringilla arcu purus sit amet leo. Nulla iaculis bibendum elit, sollicitudin scelerisque arcu pulvinar ut. Nulla faucibus, eros nec lacinia placerat, dui elit pulvinar libero, ut vulputate massa lectus et augue. Nulla a mauris nulla. Suspendisse suscipit nisl volutpat augue condimentum dignissim. Pellentesque consequat fringilla dolor vitae aliquet. Aliquam non urna in urna commodo fermentum quis et mi. Proin sapien nunc, pretium nec commodo vel, aliquet vitae nisl. Cras interdum purus non nunc malesuada imperdiet. Praesent et metus risus, aliquam sollicitudin nunc. Nam at est ante. Nunc sed erat nulla, nec elementum sapien.
|
data/views/index.erubis
ADDED
data/views/post.erubis
ADDED
data/views/posts.erubis
ADDED
metadata
ADDED
@@ -0,0 +1,125 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: hackety_sling
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Ralph von der Heyden
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2011-06-19 00:00:00.000000000Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: document_mapper
|
16
|
+
requirement: &2160697580 !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: *2160697580
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: erubis
|
27
|
+
requirement: &2160697160 !ruby/object:Gem::Requirement
|
28
|
+
none: false
|
29
|
+
requirements:
|
30
|
+
- - ! '>='
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '0'
|
33
|
+
type: :runtime
|
34
|
+
prerelease: false
|
35
|
+
version_requirements: *2160697160
|
36
|
+
- !ruby/object:Gem::Dependency
|
37
|
+
name: sinatra
|
38
|
+
requirement: &2160696740 !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
40
|
+
requirements:
|
41
|
+
- - ! '>='
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: '0'
|
44
|
+
type: :runtime
|
45
|
+
prerelease: false
|
46
|
+
version_requirements: *2160696740
|
47
|
+
- !ruby/object:Gem::Dependency
|
48
|
+
name: ratom
|
49
|
+
requirement: &2160696320 !ruby/object:Gem::Requirement
|
50
|
+
none: false
|
51
|
+
requirements:
|
52
|
+
- - ! '>='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
type: :runtime
|
56
|
+
prerelease: false
|
57
|
+
version_requirements: *2160696320
|
58
|
+
- !ruby/object:Gem::Dependency
|
59
|
+
name: rack-test
|
60
|
+
requirement: &2160695900 !ruby/object:Gem::Requirement
|
61
|
+
none: false
|
62
|
+
requirements:
|
63
|
+
- - ! '>='
|
64
|
+
- !ruby/object:Gem::Version
|
65
|
+
version: '0'
|
66
|
+
type: :development
|
67
|
+
prerelease: false
|
68
|
+
version_requirements: *2160695900
|
69
|
+
description: A simple blog engine based on Sinatra and document_mapper
|
70
|
+
email:
|
71
|
+
- ralph@rvdh.de
|
72
|
+
executables: []
|
73
|
+
extensions: []
|
74
|
+
extra_rdoc_files: []
|
75
|
+
files:
|
76
|
+
- .gitignore
|
77
|
+
- Gemfile
|
78
|
+
- Rakefile
|
79
|
+
- hackety_sling.gemspec
|
80
|
+
- lib/sinatra/hackety_sling.rb
|
81
|
+
- lib/sinatra/hackety_sling/post.rb
|
82
|
+
- lib/sinatra/hackety_sling/version.rb
|
83
|
+
- test/hackety_sling_test.rb
|
84
|
+
- test/post_test.rb
|
85
|
+
- test/test_app.rb
|
86
|
+
- test/test_posts/2010-08-09-test-post-1.textile
|
87
|
+
- test/test_posts/2010-08-10-test-post-2.textile
|
88
|
+
- test/test_posts/2010-11-13-test-post-3.textile
|
89
|
+
- test/test_posts/2011-02-28-test-post-4.textile
|
90
|
+
- views/index.erubis
|
91
|
+
- views/post.erubis
|
92
|
+
- views/post_list.erubis
|
93
|
+
- views/posts.erubis
|
94
|
+
homepage: http://rvdh.de
|
95
|
+
licenses: []
|
96
|
+
post_install_message:
|
97
|
+
rdoc_options: []
|
98
|
+
require_paths:
|
99
|
+
- lib
|
100
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
101
|
+
none: false
|
102
|
+
requirements:
|
103
|
+
- - ! '>='
|
104
|
+
- !ruby/object:Gem::Version
|
105
|
+
version: '0'
|
106
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
107
|
+
none: false
|
108
|
+
requirements:
|
109
|
+
- - ! '>='
|
110
|
+
- !ruby/object:Gem::Version
|
111
|
+
version: '0'
|
112
|
+
requirements: []
|
113
|
+
rubyforge_project:
|
114
|
+
rubygems_version: 1.8.5
|
115
|
+
signing_key:
|
116
|
+
specification_version: 3
|
117
|
+
summary: A simple blog engine based on Sinatra and document_mapper
|
118
|
+
test_files:
|
119
|
+
- test/hackety_sling_test.rb
|
120
|
+
- test/post_test.rb
|
121
|
+
- test/test_app.rb
|
122
|
+
- test/test_posts/2010-08-09-test-post-1.textile
|
123
|
+
- test/test_posts/2010-08-10-test-post-2.textile
|
124
|
+
- test/test_posts/2010-11-13-test-post-3.textile
|
125
|
+
- test/test_posts/2011-02-28-test-post-4.textile
|