manveru-innate 2009.02.06
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/CHANGELOG +1409 -0
- data/COPYING +18 -0
- data/MANIFEST +100 -0
- data/README.md +485 -0
- data/Rakefile +139 -0
- data/example/app/retro_games.rb +57 -0
- data/example/app/whywiki_erb/layout/wiki.html.erb +15 -0
- data/example/app/whywiki_erb/spec/wiki.rb +19 -0
- data/example/app/whywiki_erb/start.rb +45 -0
- data/example/app/whywiki_erb/view/edit.html.erb +6 -0
- data/example/app/whywiki_erb/view/index.html.erb +10 -0
- data/example/custom_middleware.rb +43 -0
- data/example/error_handling.rb +31 -0
- data/example/hello.rb +12 -0
- data/example/howto_spec.rb +60 -0
- data/example/link.rb +35 -0
- data/example/providing_hash.rb +46 -0
- data/example/session.rb +42 -0
- data/innate.gemspec +118 -0
- data/lib/innate.rb +191 -0
- data/lib/innate/action.rb +156 -0
- data/lib/innate/adapter.rb +89 -0
- data/lib/innate/cache.rb +117 -0
- data/lib/innate/cache/api.rb +106 -0
- data/lib/innate/cache/drb.rb +58 -0
- data/lib/innate/cache/file_based.rb +39 -0
- data/lib/innate/cache/marshal.rb +17 -0
- data/lib/innate/cache/memory.rb +22 -0
- data/lib/innate/cache/yaml.rb +17 -0
- data/lib/innate/core_compatibility/basic_object.rb +9 -0
- data/lib/innate/core_compatibility/string.rb +3 -0
- data/lib/innate/current.rb +37 -0
- data/lib/innate/dynamap.rb +81 -0
- data/lib/innate/helper.rb +195 -0
- data/lib/innate/helper/aspect.rb +62 -0
- data/lib/innate/helper/cgi.rb +39 -0
- data/lib/innate/helper/flash.rb +36 -0
- data/lib/innate/helper/link.rb +55 -0
- data/lib/innate/helper/partial.rb +90 -0
- data/lib/innate/helper/redirect.rb +85 -0
- data/lib/innate/helper/send_file.rb +18 -0
- data/lib/innate/log.rb +23 -0
- data/lib/innate/log/color_formatter.rb +43 -0
- data/lib/innate/log/hub.rb +72 -0
- data/lib/innate/mock.rb +49 -0
- data/lib/innate/node.rb +471 -0
- data/lib/innate/options.rb +91 -0
- data/lib/innate/options/dsl.rb +155 -0
- data/lib/innate/request.rb +165 -0
- data/lib/innate/response.rb +18 -0
- data/lib/innate/route.rb +109 -0
- data/lib/innate/session.rb +104 -0
- data/lib/innate/session/flash.rb +94 -0
- data/lib/innate/setup.rb +23 -0
- data/lib/innate/spec.rb +42 -0
- data/lib/innate/state.rb +22 -0
- data/lib/innate/state/accessor.rb +130 -0
- data/lib/innate/state/fiber.rb +68 -0
- data/lib/innate/state/thread.rb +39 -0
- data/lib/innate/traited.rb +20 -0
- data/lib/innate/trinity.rb +22 -0
- data/lib/innate/version.rb +3 -0
- data/lib/innate/view.rb +67 -0
- data/lib/innate/view/erb.rb +17 -0
- data/lib/innate/view/none.rb +9 -0
- data/lib/rack/middleware_compiler.rb +62 -0
- data/lib/rack/reloader.rb +192 -0
- data/spec/example/hello.rb +14 -0
- data/spec/example/link.rb +29 -0
- data/spec/helper.rb +2 -0
- data/spec/innate/cache/common.rb +45 -0
- data/spec/innate/cache/marshal.rb +5 -0
- data/spec/innate/cache/memory.rb +5 -0
- data/spec/innate/cache/yaml.rb +5 -0
- data/spec/innate/dynamap.rb +22 -0
- data/spec/innate/helper.rb +66 -0
- data/spec/innate/helper/aspect.rb +80 -0
- data/spec/innate/helper/cgi.rb +37 -0
- data/spec/innate/helper/flash.rb +148 -0
- data/spec/innate/helper/link.rb +82 -0
- data/spec/innate/helper/partial.rb +66 -0
- data/spec/innate/helper/redirect.rb +148 -0
- data/spec/innate/helper/send_file.rb +21 -0
- data/spec/innate/helper/view/aspect_hello.erb +1 -0
- data/spec/innate/helper/view/locals.erb +1 -0
- data/spec/innate/helper/view/loop.erb +4 -0
- data/spec/innate/helper/view/num.erb +1 -0
- data/spec/innate/helper/view/partial.erb +1 -0
- data/spec/innate/helper/view/recursive.erb +8 -0
- data/spec/innate/mock.rb +84 -0
- data/spec/innate/node.rb +180 -0
- data/spec/innate/node/bar.html +1 -0
- data/spec/innate/node/foo.html.erb +1 -0
- data/spec/innate/node/with_layout.erb +3 -0
- data/spec/innate/options.rb +90 -0
- data/spec/innate/parameter.rb +154 -0
- data/spec/innate/request.rb +73 -0
- data/spec/innate/route.rb +129 -0
- data/spec/innate/session.rb +59 -0
- data/spec/innate/traited.rb +55 -0
- metadata +160 -0
data/Rakefile
ADDED
@@ -0,0 +1,139 @@
|
|
1
|
+
require 'rake/rdoctask'
|
2
|
+
require 'rake/clean'
|
3
|
+
require 'time'
|
4
|
+
require 'date'
|
5
|
+
require 'pp'
|
6
|
+
|
7
|
+
INNATE_VERSION = Date.today.strftime("%Y.%m.%d")
|
8
|
+
|
9
|
+
task :default => [:spec]
|
10
|
+
|
11
|
+
CLEAN.include('*coverage*')
|
12
|
+
|
13
|
+
desc 'update lib/innate/version.rb'
|
14
|
+
task :reversion do
|
15
|
+
File.open('lib/innate/version.rb', 'w+') do |file|
|
16
|
+
file.puts('module Innate')
|
17
|
+
file.puts(' VERSION = %p' % INNATE_VERSION)
|
18
|
+
file.puts('end')
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
desc 'publish to github'
|
23
|
+
task :release => [:reversion, :gemspec] do
|
24
|
+
sh('git add MANIFEST CHANGELOG innate.gemspec lib/innate/version.rb')
|
25
|
+
puts "I added the relevant files, you can now run:", ''
|
26
|
+
puts "git commit -m 'Version #{INNATE_VERSION}'"
|
27
|
+
puts "git tag -m '#{INNATE_VERSION}'"
|
28
|
+
puts "git push"
|
29
|
+
puts
|
30
|
+
end
|
31
|
+
|
32
|
+
desc 'update manifest'
|
33
|
+
task :manifest do
|
34
|
+
File.open('MANIFEST', 'w+') do|manifest|
|
35
|
+
manifest.puts(`git ls-files`)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
desc 'update changelog'
|
40
|
+
task :changelog do
|
41
|
+
File.open('CHANGELOG', 'w+') do |changelog|
|
42
|
+
`git log -z --abbrev-commit`.split("\0").each do |commit|
|
43
|
+
next if commit =~ /^Merge: \d*/
|
44
|
+
ref, author, time, _, title, _, message = commit.split("\n", 7)
|
45
|
+
ref = ref[/commit ([0-9a-f]+)/, 1]
|
46
|
+
author = author[/Author: (.*)/, 1].strip
|
47
|
+
time = Time.parse(time[/Date: (.*)/, 1]).utc
|
48
|
+
title.strip!
|
49
|
+
|
50
|
+
changelog.puts "[#{ref} | #{time}] #{author}"
|
51
|
+
changelog.puts '', " * #{title}"
|
52
|
+
changelog.puts '', message.rstrip if message
|
53
|
+
changelog.puts
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
desc 'generate gemspec'
|
59
|
+
task :gemspec => [:manifest, :changelog] do
|
60
|
+
manifest = File.read('MANIFEST').split("\n")
|
61
|
+
files = manifest.map{|file| " %p," % file }.join("\n")[0..-2]
|
62
|
+
|
63
|
+
gemspec = <<-GEMSPEC
|
64
|
+
Gem::Specification.new do |s|
|
65
|
+
s.name = "innate"
|
66
|
+
s.version = #{INNATE_VERSION.dump}
|
67
|
+
|
68
|
+
s.summary = "Powerful web-framework wrapper for Rack."
|
69
|
+
s.description = "Simple, straight-forward, base for web-frameworks."
|
70
|
+
s.platform = "ruby"
|
71
|
+
s.has_rdoc = true
|
72
|
+
s.author = "Michael 'manveru' Fellinger"
|
73
|
+
s.email = "m.fellinger@gmail.com"
|
74
|
+
s.homepage = "http://github.com/manveru/innate"
|
75
|
+
s.require_path = "lib"
|
76
|
+
|
77
|
+
s.add_dependency('rack', '>= 0.4.0')
|
78
|
+
|
79
|
+
s.files = [
|
80
|
+
#{files}
|
81
|
+
]
|
82
|
+
end
|
83
|
+
GEMSPEC
|
84
|
+
|
85
|
+
File.open('innate.gemspec', 'w+'){|gs| gs.puts(gemspec) }
|
86
|
+
end
|
87
|
+
|
88
|
+
desc 'code coverage'
|
89
|
+
task :rcov => :clean do
|
90
|
+
specs = Dir['spec/innate/**/*.rb']
|
91
|
+
specs -= Dir['spec/innate/cache/common.rb']
|
92
|
+
|
93
|
+
# we ignore adapter as this has extensive specs in rack already.
|
94
|
+
ignore = %w[ gem rack bacon innate/adapter\.rb ]
|
95
|
+
ignore << 'fiber\.rb' if RUBY_VERSION < '1.9'
|
96
|
+
|
97
|
+
ignored = ignore.join(',')
|
98
|
+
|
99
|
+
cmd = "rcov --aggregate coverage.data --sort coverage -t --%s -x '#{ignored}' %s"
|
100
|
+
|
101
|
+
while spec = specs.shift
|
102
|
+
puts '', "Gather coverage for #{spec} ..."
|
103
|
+
html = specs.empty? ? 'html' : 'no-html'
|
104
|
+
sh(cmd % [html, spec])
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
desc 'Run all specs'
|
109
|
+
task :spec do
|
110
|
+
require 'open3'
|
111
|
+
|
112
|
+
specs = Dir['spec/{innate,example}/**/*.rb']
|
113
|
+
specs.delete_if{|f| f =~ /cache\/common\.rb/ }
|
114
|
+
|
115
|
+
total = specs.size
|
116
|
+
len = specs.sort.last.size
|
117
|
+
left_format = "%4d/%d: %-#{len + 11}s"
|
118
|
+
|
119
|
+
red, green = "\e[31m%s\e[0m", "\e[32m%s\e[0m"
|
120
|
+
|
121
|
+
specs.each_with_index do |spec, idx|
|
122
|
+
print(left_format % [idx + 1, total, spec])
|
123
|
+
|
124
|
+
Open3.popen3("#{RUBY} #{spec}") do |sin, sout, serr|
|
125
|
+
out = sout.read
|
126
|
+
err = serr.read
|
127
|
+
|
128
|
+
md = out.match(/(\d+) tests, (\d+) assertions, (\d+) failures, (\d+) errors/)
|
129
|
+
tests, assertions, failures, errors = all = md.captures.map{|c| c.to_i }
|
130
|
+
|
131
|
+
if failures + errors > 0
|
132
|
+
puts((red % "%5d tests, %d assertions, %d failures, %d errors") % all)
|
133
|
+
puts "", out, err, ""
|
134
|
+
else
|
135
|
+
puts((green % "%5d passed") % tests)
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
require 'innate'
|
2
|
+
require 'yaml/store'
|
3
|
+
|
4
|
+
STORE = YAML::Store.new('games.yaml')
|
5
|
+
|
6
|
+
def STORE.[](key) transaction{|s| s[key] } end
|
7
|
+
def STORE.[]=(key, value) transaction{|s| s[key] = value } end
|
8
|
+
def STORE.each
|
9
|
+
YAML.load_file('games.yaml').sort_by{|k,v| -v }.each{|(k,v)| yield(k, v) }
|
10
|
+
end
|
11
|
+
|
12
|
+
class Games
|
13
|
+
include Innate::Node
|
14
|
+
map '/'
|
15
|
+
provide :html => :haml
|
16
|
+
|
17
|
+
def index
|
18
|
+
TEMPLATE
|
19
|
+
end
|
20
|
+
|
21
|
+
def create
|
22
|
+
if request.post?
|
23
|
+
name = request.params['name']
|
24
|
+
STORE[name] ||= 0
|
25
|
+
end
|
26
|
+
|
27
|
+
redirect_referrer
|
28
|
+
end
|
29
|
+
|
30
|
+
def vote(name)
|
31
|
+
STORE[url_decode name] += 1
|
32
|
+
|
33
|
+
redirect_referrer
|
34
|
+
end
|
35
|
+
|
36
|
+
TEMPLATE = <<-'T'.strip
|
37
|
+
!!! XML
|
38
|
+
!!!
|
39
|
+
|
40
|
+
%html
|
41
|
+
%head
|
42
|
+
%title Top Retro Games
|
43
|
+
%body
|
44
|
+
%h1 Vote on your favorite Retro Game
|
45
|
+
%form{:action => r(:create), :method => 'POST'}
|
46
|
+
%input{:type => 'text', :name => 'name'}
|
47
|
+
%input{:type => 'submit', :value => 'Add'}
|
48
|
+
%ol
|
49
|
+
- STORE.each do |name, votes|
|
50
|
+
%li
|
51
|
+
= Games.a("Vote", "/vote/#{u name}")
|
52
|
+
= h("%5d => %s" % [votes, name])
|
53
|
+
T
|
54
|
+
|
55
|
+
end
|
56
|
+
|
57
|
+
Innate.start
|
@@ -0,0 +1,15 @@
|
|
1
|
+
<?xml version='1.0' encoding='utf-8' ?>
|
2
|
+
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
3
|
+
<html>
|
4
|
+
<head>
|
5
|
+
<title><%= "MicroWiki #{h @page}" %></title>
|
6
|
+
<style type="text/css">
|
7
|
+
a.exists{ color: #00f; }
|
8
|
+
a.missing{ color: #f00; }
|
9
|
+
textarea{ width: 90%; height: 20em; }
|
10
|
+
</style>
|
11
|
+
</head>
|
12
|
+
<body>
|
13
|
+
<%= @content %>
|
14
|
+
</body>
|
15
|
+
</html>
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'innate'
|
2
|
+
require 'innate/spec'
|
3
|
+
require 'yaml/store'
|
4
|
+
|
5
|
+
base = File.join(File.dirname(__FILE__), '..')
|
6
|
+
DB = YAML::Store.new(db_file = "#{base}/spec/wiki.yaml")
|
7
|
+
|
8
|
+
require "start"
|
9
|
+
|
10
|
+
Innate.config.app.root = base
|
11
|
+
|
12
|
+
describe 'Wiki' do
|
13
|
+
it 'should have index page' do
|
14
|
+
page = Innate::Mock.get('/')
|
15
|
+
page.body.should == ''
|
16
|
+
end
|
17
|
+
|
18
|
+
FileUtils.rm_f(db_file)
|
19
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
# The minimal _why wiki in Innate
|
2
|
+
|
3
|
+
%w[rubygems innate erb maruku yaml/store].each{|l| require(l) }
|
4
|
+
|
5
|
+
DB = YAML::Store.new('wiki.yaml') unless defined?(DB)
|
6
|
+
|
7
|
+
class Wiki
|
8
|
+
include Innate::Node
|
9
|
+
map '/'
|
10
|
+
provide :html => :erb
|
11
|
+
layout 'wiki'
|
12
|
+
|
13
|
+
def index(page = 'Home')
|
14
|
+
@page = page
|
15
|
+
@text = 'foo'
|
16
|
+
sync{
|
17
|
+
@text = DB[page].to_s.dup
|
18
|
+
@text.gsub!(/\[\[(.*?)\]\]/) do
|
19
|
+
%(<a href="#{r($1)}" class="#{DB[$1] ? 'exists' : 'missing'}">#{h($1)}</a>)
|
20
|
+
end
|
21
|
+
}
|
22
|
+
end
|
23
|
+
|
24
|
+
def edit(page)
|
25
|
+
@page = page
|
26
|
+
@text = sync{ DB[page].to_s }
|
27
|
+
end
|
28
|
+
|
29
|
+
def save
|
30
|
+
redirect_referrer unless request.post?
|
31
|
+
|
32
|
+
page, text = request[:page, :text]
|
33
|
+
sync{ DB[page] = text } if page and text
|
34
|
+
|
35
|
+
redirect(r(page))
|
36
|
+
end
|
37
|
+
|
38
|
+
private
|
39
|
+
|
40
|
+
def sync
|
41
|
+
Innate::STATE.sync{ DB.transaction{ yield }}
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
Innate.start :adapter => :mongrel
|
@@ -0,0 +1,10 @@
|
|
1
|
+
<% unless @page == 'Home' %>
|
2
|
+
<a href="<%= r 'Home' %>">< Home</a>
|
3
|
+
<% end %>
|
4
|
+
<h1><%= h @page %></h1>
|
5
|
+
<% if @text.empty? %>
|
6
|
+
<a href="<%= r :edit, @page %>"><%= h "Create #{@page}" %></a>
|
7
|
+
<% else %>
|
8
|
+
<a href="<%= r :edit, @page %>"><%= h "Edit #{@page}" %></a>
|
9
|
+
<%= Maruku.new(@text).to_html %>
|
10
|
+
<% end %>
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require 'innate'
|
2
|
+
|
3
|
+
class Demo
|
4
|
+
include Innate::Node
|
5
|
+
map '/'
|
6
|
+
|
7
|
+
def index
|
8
|
+
'Hello, World!'
|
9
|
+
end
|
10
|
+
|
11
|
+
def empty
|
12
|
+
response.status = 405
|
13
|
+
''
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
# Make sure you do this before Innate.start, otherwise you have to use
|
18
|
+
# Innate.middleware! to force a rebuild in the MiddlewareCompiler.
|
19
|
+
Innate.middleware :innate do |mw|
|
20
|
+
# Makes sure all requests and responses conform to Rack protocol
|
21
|
+
mw.use Rack::Lint
|
22
|
+
|
23
|
+
# Avoid showing empty failure pages, give information when it happens.
|
24
|
+
mw.use Rack::ShowStatus
|
25
|
+
|
26
|
+
# Catch exceptions inside Innate and give nice status info
|
27
|
+
mw.use Rack::ShowExceptions
|
28
|
+
|
29
|
+
# Log access
|
30
|
+
mw.use Rack::CommonLogger
|
31
|
+
|
32
|
+
# Reload modified files before request
|
33
|
+
mw.use Rack::Reloader
|
34
|
+
|
35
|
+
# Initializes the Current objects: Request, Response, and Session
|
36
|
+
mw.use Innate::Current
|
37
|
+
|
38
|
+
# This will try to find a static file in /public first, and try DynaMap if
|
39
|
+
# Rack::File returns a 404 status.
|
40
|
+
mw.cascade Rack::File.new('public'), Innate::DynaMap
|
41
|
+
end
|
42
|
+
|
43
|
+
Innate.start
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'innate'
|
2
|
+
|
3
|
+
class Flawed
|
4
|
+
include Innate::Node
|
5
|
+
map '/'
|
6
|
+
|
7
|
+
def index
|
8
|
+
raise ArgumentError, "No go"
|
9
|
+
end
|
10
|
+
|
11
|
+
def i_raise
|
12
|
+
100 * "foo"
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
class Errors
|
17
|
+
include Innate::Node
|
18
|
+
map '/error'
|
19
|
+
|
20
|
+
def internal
|
21
|
+
path = request.env['rack.route_exceptions.path_info']
|
22
|
+
exception = request.env['rack.route_exceptions.exception']
|
23
|
+
|
24
|
+
format = "Oh my, you just went to %p, something went horribly wrong: %p"
|
25
|
+
format % [path, exception.message]
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
Rack::RouteExceptions.route(Exception, '/error/internal')
|
30
|
+
|
31
|
+
Innate.start
|
data/example/hello.rb
ADDED
@@ -0,0 +1,60 @@
|
|
1
|
+
require 'innate'
|
2
|
+
require 'bacon'
|
3
|
+
|
4
|
+
class SpecMe
|
5
|
+
include Innate::Node
|
6
|
+
map '/'
|
7
|
+
|
8
|
+
def index
|
9
|
+
"I should be at /"
|
10
|
+
end
|
11
|
+
|
12
|
+
def foo
|
13
|
+
action.content_type = 'text/css'
|
14
|
+
"I should be at /foo"
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
class SpecMeToo
|
19
|
+
include Innate::Node
|
20
|
+
map '/too'
|
21
|
+
|
22
|
+
def index
|
23
|
+
"I should be at /too"
|
24
|
+
end
|
25
|
+
|
26
|
+
def foo
|
27
|
+
action.content_type = 'text/css'
|
28
|
+
"I should be at /too/foo"
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
Innate.setup_middleware
|
33
|
+
|
34
|
+
Bacon.summary_on_exit
|
35
|
+
Bacon.extend(Bacon::TestUnitOutput)
|
36
|
+
|
37
|
+
describe 'An example spec' do
|
38
|
+
def assert(url, body, content_type)
|
39
|
+
response = Innate::Mock.get(url)
|
40
|
+
response.status.should == 200
|
41
|
+
response.body.should == body
|
42
|
+
response.content_type.should == content_type
|
43
|
+
end
|
44
|
+
|
45
|
+
should 'respond to /' do
|
46
|
+
assert('/', "I should be at /", 'text/html')
|
47
|
+
end
|
48
|
+
|
49
|
+
should 'respond to /foo' do
|
50
|
+
assert('/foo', "I should be at /foo", 'text/css')
|
51
|
+
end
|
52
|
+
|
53
|
+
should 'respond to /too' do
|
54
|
+
assert('/too', "I should be at /too", 'text/html')
|
55
|
+
end
|
56
|
+
|
57
|
+
should 'respond to /too/foo' do
|
58
|
+
assert('/too/foo', "I should be at /too/foo", 'text/css')
|
59
|
+
end
|
60
|
+
end
|