rumblelog 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,8 @@
1
+ rumblelog
2
+ fauna
3
+ .bundle
4
+ .config
5
+ *.gem
6
+ tmp
7
+ vendor
8
+ Gemfile.lock
data/Gemfile ADDED
@@ -0,0 +1,9 @@
1
+ source "http://rubygems.org"
2
+
3
+ gem 'sinatra'
4
+ gem 'tux'
5
+
6
+ gem 'fauna', :path => "/Users/stevej/src/fauna-ruby"
7
+ gem 'mustache'
8
+ gem 'shotgun'
9
+ gem 'rake'
data/Rakefile ADDED
@@ -0,0 +1,2 @@
1
+ $: << '.'
2
+ require 'rumblelog'
data/config/fauna.yml ADDED
@@ -0,0 +1,7 @@
1
+ rumblelog:
2
+ development:
3
+ email: stevej@fruitless.org
4
+ password: jP3X_YBwBA1iYQ
5
+ test:
6
+ email: stevej@fruitless.org
7
+ password: jP3X_YBwBA1iYQ
data/config.ru ADDED
@@ -0,0 +1,14 @@
1
+ # Ruby > 1.9.2 doesn't automatically add the CWD to the load path
2
+ $: << '.'
3
+
4
+ require 'rubygems'
5
+ require 'bundler'
6
+
7
+ Bundler.require
8
+
9
+ require './rumblelog'
10
+
11
+ use Rack::ShowExceptions
12
+
13
+ run Rumblelog
14
+
@@ -0,0 +1,42 @@
1
+ require 'fauna'
2
+
3
+ module Fauna
4
+ module Rack
5
+ def self.credentials(config_file, local_config_file, app_name)
6
+ env = ENV['RACK_ENV'] || 'development' # FIXME: need this for tux.
7
+ credentials = {}
8
+
9
+ if File.exist? config_file
10
+ credentials.merge!(YAML.load_file(config_file)[env] || {})
11
+
12
+ if File.exist? local_config_file
13
+ credentials.merge!((YAML.load_file(local_config_file)[app_name] || {})[env] || {})
14
+ end
15
+ else
16
+ STDERR.puts ">> Fauna account not configured. You can add one in config/fauna.yml."
17
+ end
18
+
19
+ credentials
20
+ end
21
+
22
+ def self.connection(credentials, logger)
23
+
24
+ root_connection = Connection.new(
25
+ :email => credentials["email"],
26
+ :password => credentials["password"],
27
+ :logger => logger)
28
+
29
+ publisher_key = root_connection.post("keys/publisher")["resource"]["key"]
30
+
31
+ connection = Connection.new(
32
+ publisher_key: publisher_key,
33
+ logger: logger)
34
+
35
+ {
36
+ root_connection: root_connection,
37
+ connection: connection
38
+ }
39
+ end
40
+ end
41
+ end
42
+
data/rumblelog.gemspec ADDED
@@ -0,0 +1,19 @@
1
+ Gem::Specification.new do |s|
2
+ s.name = 'rumblelog'
3
+ s.version = '0.1.0'
4
+ s.date = '2013-06-25'
5
+ s.summary = "A site publishing system!"
6
+ s.description = "A dynamic site publishing with Pages and Tags"
7
+ s.license = "Apache 2.0"
8
+ s.authors = ["Steve Jenson"]
9
+ s.email = 'stevej@fruitless.org'
10
+ s.homepage =
11
+ 'http://github.com/stevej/rumblelog'
12
+
13
+ s.files = `git ls-files`.split($/)
14
+ s.require_paths = ["lib"]
15
+
16
+ s.add_development_dependency "bundler"
17
+ s.add_dependency "sinatra"
18
+ s.add_dependency "fauna"
19
+ end
data/rumblelog.rb ADDED
@@ -0,0 +1,181 @@
1
+ require 'sinatra/base'
2
+ require 'mustache/sinatra'
3
+ require 'fauna'
4
+
5
+ # TODO: make this nicer
6
+ load 'lib/fauna_helper.rb'
7
+
8
+ # TODO: this is not awesome but works for now.
9
+ module Fauna
10
+ mattr_accessor :credentials
11
+ mattr_accessor :connection
12
+
13
+ self.credentials = Fauna::Rack::credentials("#{ENV["HOME"]}/.fauna.yml",
14
+ "config/fauna.yml",
15
+ "rumblelog")
16
+
17
+ self.connection = Fauna::Rack::connection(self.credentials, Logger.new("rumblelog"))[:connection]
18
+ end
19
+
20
+ class Rumblelog < Sinatra::Base
21
+ register Mustache::Sinatra
22
+ require 'views/layout'
23
+
24
+ set :mustache, {
25
+ :views => 'views/',
26
+ :templates => 'templates/'
27
+ }
28
+
29
+ helpers do
30
+ def protected!
31
+ return if authorized?
32
+ headers['WWW-Authenticate'] = 'Basic realm="Restricted Area"'
33
+ halt 401, "Not authorized\n"
34
+ end
35
+
36
+ def authorized?
37
+ @auth ||= Rack::Auth::Basic::Request.new(request.env)
38
+
39
+ @auth.provided? &&
40
+ @auth.basic? &&
41
+ @auth.credentials &&
42
+ @auth.credentials == ['admin', 'admin']
43
+ end
44
+ end
45
+
46
+
47
+ def with_context(&block)
48
+ if block.nil?
49
+ raise "with_context called without block"
50
+ elsif Fauna.connection.nil?
51
+ raise "cannot use Fauna::Client.context without connection"
52
+ else
53
+ Fauna::Client.context(Fauna.connection) do
54
+ block.call
55
+ end
56
+ end
57
+ end
58
+
59
+ if defined?(Fauna.connection)
60
+ puts "phew, we have a connection"
61
+ else
62
+ puts "no fauna connection"
63
+ end
64
+
65
+ set :public_folder, 'public'
66
+
67
+ get '/' do
68
+ # TODO: Load N Pages, unfortunately .first only grants me a `resource` accessor.
69
+ @pages = with_context { Page.all.page(:size => 3).first.resource.to_html_hash }
70
+ pp @pages
71
+ mustache :index
72
+ end
73
+
74
+ get '/create' do
75
+ protected!
76
+ mustache :create
77
+ end
78
+
79
+ post '/create' do
80
+ protected!
81
+ # TODO: validate post params
82
+ data = params[:page]
83
+ # TODO: ensure that unique_id is truly unique before creating entry.
84
+ data[:unique_id] = data[:url]
85
+ with_context { Page.create!(data) }
86
+ redirect "/"
87
+ end
88
+
89
+ get '/edit' do
90
+ protected!
91
+ end
92
+
93
+ post '/edit' do
94
+ protected!
95
+ end
96
+
97
+ get '/t/:tag' do |tag|
98
+ @pages = with_context { Tag.find_by_unique_id(tag).pages }
99
+ mustache :index
100
+ end
101
+
102
+ get '/status' do
103
+ # Are we connected to Fauna?
104
+ mustache :status
105
+ end
106
+
107
+ get '/:url' do |url|
108
+ # matches "GET /hello/foo" and "GET /hello/bar"
109
+ # params[:name] is 'foo' or 'bar'
110
+ # n stores params[:name]
111
+ @pages = with_context { Page.find_by_unique_id(url) }
112
+ mustache :render_page # TODO: bad name
113
+ end
114
+
115
+ end
116
+
117
+ class Page < Fauna::Class
118
+ field :title, :body, :url, :tags
119
+ reference :tag
120
+ after_save :update_tags
121
+
122
+ def initialize(attrs = {})
123
+ super(attrs)
124
+ end
125
+
126
+ def links_for_tags
127
+ tags = self.data['tags']
128
+ pp tags
129
+ if tags.nil?
130
+ []
131
+ else
132
+ tags.split(",").map do |tag_name|
133
+ {tag_name: tag_name.strip}
134
+ end
135
+ end
136
+ end
137
+
138
+ def to_html_hash
139
+ html_hash = data
140
+ html_hash[:links_for_tags] = self.links_for_tags
141
+ html_hash
142
+ end
143
+
144
+ def update_tags
145
+ tags = self.data['tags']
146
+ unless tags.nil?
147
+ tags.split(",").each do |tag_name|
148
+ tag_name.strip!
149
+ tag =
150
+ begin
151
+ Tag.create!(unique_id: tag_name)
152
+ rescue
153
+ Tag.find_by_unique_id(tag_name)
154
+ end
155
+ tag.pages.add self
156
+ end
157
+ end
158
+ end
159
+ end
160
+
161
+ class Tag < Fauna::Class
162
+ reference :page
163
+ end
164
+
165
+ # Data Model
166
+ #
167
+ # A Site consists of Pages
168
+ # Pages belong to tags
169
+ # Tags are organized by time
170
+ #
171
+ #
172
+ Fauna.schema do
173
+ with Tag do
174
+ event_set :pages
175
+ end
176
+
177
+ with Page do
178
+ event_set :tags
179
+ end
180
+ end
181
+
@@ -0,0 +1,3 @@
1
+ <div class="blogroll">
2
+ <a href="http://saladwithsteve.com/">my old blog</a>
3
+ </div>
@@ -0,0 +1,12 @@
1
+ <h1>{{title}}</h1>
2
+
3
+ <form name="create" action="/create" method="POST">
4
+ <br />
5
+ title: <input name="page[title]" /><br/>
6
+ url: <input name="page[url]" value="{{fresh_page_url}}"/><br/>
7
+ tags: <input name="page[tags]" /><br/>
8
+ body: <textarea name="page[body]" /></textarea><br/>
9
+ <button type="submit"/>publish</button><br>
10
+ </form>
11
+
12
+ {{> footer}}
@@ -0,0 +1,5 @@
1
+ <small>Powered by <a href="http://github.com/stevej/rumblelog">rumblelog</a> and <a href="http://fauna.org">fauna</a></small>
2
+ <div class="admin">
3
+ [<a href="/create">create post</a>, <a href="/edit">edit posts</a>, <a href="/status">status</a>]
4
+ </div>
5
+ {{> sidebar}}
@@ -0,0 +1,21 @@
1
+ <h1>{{title}}</h1>
2
+
3
+ <p>{{content}}</p>
4
+
5
+ <ul>
6
+ <li>
7
+ <a href="/">Home</a>
8
+ </li>
9
+ </ul>
10
+
11
+ {{#pages}}
12
+ {{> page_content }}
13
+ {{/pages}}
14
+
15
+ {{^pages}}
16
+ <p>
17
+ Sorry, there are no pages to display. Try creating some!
18
+ </p>
19
+ {{/pages}}
20
+
21
+ {{> footer}}
@@ -0,0 +1,17 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>
5
+ {{title}}
6
+ </title>
7
+ <style>
8
+ body { bbackground: #eee; }
9
+ li { list-style: none !important; }
10
+ </style>
11
+ </head>
12
+ <body>
13
+ <div id="main">
14
+ {{{yield}}}
15
+ </div>
16
+ </body>
17
+ </html>
@@ -0,0 +1,3 @@
1
+ {{#pages}}
2
+ {{>page_content}}
3
+ {{/pages}}
@@ -0,0 +1,9 @@
1
+ <p>
2
+ <a href="{{url}}">[{{title}}]</a><br />
3
+ tags: {{#links_for_tags}}
4
+ <a href="/t/{{tag_name}}">{{tag_name}}</a>
5
+ {{/links_for_tags}}
6
+ <div class="post-body">
7
+ {{{body}}}
8
+ </div>
9
+ </p>
@@ -0,0 +1 @@
1
+ <small>It's just me. A partial.</small>
@@ -0,0 +1,3 @@
1
+ {{#pages}}
2
+ {{> page_content}}
3
+ {{/pages}}
@@ -0,0 +1,21 @@
1
+ <h1>{{title}}</h1>
2
+
3
+ <p>{{content}}</p>
4
+
5
+ <ul>
6
+ <li>
7
+ <a href="/">Home</a>
8
+ </li>
9
+ </ul>
10
+
11
+ {{#tags}}
12
+ {{> tag_content }}
13
+ {{/tags}}
14
+
15
+ {{^tags}}
16
+ <p>
17
+ Sorry, there are no pages for those tags. Try creating some!
18
+ </p>
19
+ {{/tags}}
20
+
21
+ {{> footer}}
@@ -0,0 +1,4 @@
1
+ <div class="sidebar">
2
+ <a href="/about">About</a>
3
+ </div>
4
+ {{> blogroll}}
@@ -0,0 +1,21 @@
1
+ <h1>{{title}}</h1>
2
+
3
+ <dl class="status">
4
+ <dt>Connected to Fauna?</dt>
5
+ <dd>{{connection?}}</dd>
6
+
7
+ <dt></dt>
8
+ <dd></dd>
9
+ </dl>
10
+
11
+ <ul>
12
+ <li>
13
+ <a href="/">Home</a>
14
+ </li>
15
+ <li>
16
+ <a href="/status">Status</a>
17
+ </li>
18
+ </ul>
19
+
20
+ {{> footer}}
21
+
File without changes
data/views/create.rb ADDED
@@ -0,0 +1,10 @@
1
+ class Rumblelog
2
+ module Views
3
+ class Create < Layout
4
+ # Generate's a fresh page URL to be overwritten by the user.
5
+ def fresh_page_url
6
+ Time.now.to_i
7
+ end
8
+ end
9
+ end
10
+ end
data/views/index.rb ADDED
@@ -0,0 +1,13 @@
1
+ class Rumblelog
2
+ module Views
3
+ class Index < Layout
4
+ def pages
5
+ @pages
6
+ end
7
+
8
+ def content
9
+ "Not a blog. c'mon guys."
10
+ end
11
+ end
12
+ end
13
+ end
data/views/layout.rb ADDED
@@ -0,0 +1,9 @@
1
+ class Rumblelog
2
+ module Views
3
+ class Layout < Mustache
4
+ def title
5
+ @title || "Rumblelog"
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,9 @@
1
+ class Rumblelog
2
+ module Views
3
+ class RenderPage < Layout
4
+ def pages
5
+ @pages
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,9 @@
1
+ class Rumblelog
2
+ module Views
3
+ class RenderTag < Layout
4
+ def tags
5
+ @tags
6
+ end
7
+ end
8
+ end
9
+ end
data/views/status.rb ADDED
@@ -0,0 +1,9 @@
1
+ class Rumblelog
2
+ module Views
3
+ class Status < Layout
4
+ def connection?
5
+ !!Fauna.connection
6
+ end
7
+ end
8
+ end
9
+ end
metadata ADDED
@@ -0,0 +1,120 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rumblelog
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Steve Jenson
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-06-25 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: bundler
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :development
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
30
+ - !ruby/object:Gem::Dependency
31
+ name: sinatra
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ type: :runtime
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ - !ruby/object:Gem::Dependency
47
+ name: fauna
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ type: :runtime
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ description: A dynamic site publishing with Pages and Tags
63
+ email: stevej@fruitless.org
64
+ executables: []
65
+ extensions: []
66
+ extra_rdoc_files: []
67
+ files:
68
+ - .gitignore
69
+ - Gemfile
70
+ - Rakefile
71
+ - config.ru
72
+ - config/fauna.yml
73
+ - lib/fauna_helper.rb
74
+ - rumblelog.gemspec
75
+ - rumblelog.rb
76
+ - templates/blogroll.mustache
77
+ - templates/create.mustache
78
+ - templates/footer.mustache
79
+ - templates/index.mustache
80
+ - templates/layout.mustache
81
+ - templates/page.mustache
82
+ - templates/page_content.mustache
83
+ - templates/partial.mustache
84
+ - templates/render_page.mustache
85
+ - templates/render_tag.mustache
86
+ - templates/sidebar.mustache
87
+ - templates/status.mustache
88
+ - templates/tag_content.mustache
89
+ - views/create.rb
90
+ - views/index.rb
91
+ - views/layout.rb
92
+ - views/render_page.rb
93
+ - views/render_tag.rb
94
+ - views/status.rb
95
+ homepage: http://github.com/stevej/rumblelog
96
+ licenses:
97
+ - Apache 2.0
98
+ post_install_message:
99
+ rdoc_options: []
100
+ require_paths:
101
+ - lib
102
+ required_ruby_version: !ruby/object:Gem::Requirement
103
+ none: false
104
+ requirements:
105
+ - - ! '>='
106
+ - !ruby/object:Gem::Version
107
+ version: '0'
108
+ required_rubygems_version: !ruby/object:Gem::Requirement
109
+ none: false
110
+ requirements:
111
+ - - ! '>='
112
+ - !ruby/object:Gem::Version
113
+ version: '0'
114
+ requirements: []
115
+ rubyforge_project:
116
+ rubygems_version: 1.8.23
117
+ signing_key:
118
+ specification_version: 3
119
+ summary: A site publishing system!
120
+ test_files: []