hackety_sling 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,5 @@
1
+ *.gem
2
+ .bundle
3
+ Gemfile.lock
4
+ pkg/*
5
+ .rvmrc
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'http://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in ../hackety_sling.gemspec
4
+ gemspec
data/Rakefile ADDED
@@ -0,0 +1,7 @@
1
+ require 'bundler/gem_tasks'
2
+ require 'rake/testtask'
3
+
4
+ task :default => :test
5
+ Rake::TestTask.new(:test) do |t|
6
+ t.test_files = FileList['test/*_test.rb']
7
+ end
@@ -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,5 @@
1
+ module Sinatra
2
+ module HacketySling
3
+ VERSION = '0.0.1'
4
+ end
5
+ 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,6 @@
1
+ require 'sinatra/base'
2
+ require 'sinatra/hackety_sling'
3
+
4
+ class TestApp < Sinatra::Base
5
+ register Sinatra::HacketySling
6
+ end
@@ -0,0 +1,8 @@
1
+ ---
2
+ id:
3
+ title: Test post 1
4
+ tags: [ruby]
5
+ title_photo: 4780215856
6
+ ---
7
+
8
+ photo. 4780215856
@@ -0,0 +1,7 @@
1
+ ---
2
+ title: Test post 2
3
+ tags: [ruby]
4
+ title_photo: 4894723997
5
+ ---
6
+
7
+ photo. 4894723997
@@ -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.
@@ -0,0 +1,4 @@
1
+ <% @posts.each do |post| -%>
2
+ <a href="<%= post.permalink %>"><%=post.title %></a>
3
+ <%= post.content %>
4
+ <% end -%>
data/views/post.erubis ADDED
@@ -0,0 +1,2 @@
1
+ <%= @post.title %>
2
+ <%= @post.content %>
@@ -0,0 +1,3 @@
1
+ <%- @posts.each do |post| -%>
2
+ <a href="<%= post.permalink %>"><%=post.title %></a>
3
+ <%- end -%>
@@ -0,0 +1,4 @@
1
+ <% @posts.each do |post| -%>
2
+ <a href="<%= post.permalink %>"><%=post.title %></a>
3
+ <%= post.content %>
4
+ <% end -%>
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