manveru-innate 2009.02.06
Sign up to get free protection for your applications and to get access to all the features.
- 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
|