rumblelog 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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: []