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.
Files changed (101) hide show
  1. data/CHANGELOG +1409 -0
  2. data/COPYING +18 -0
  3. data/MANIFEST +100 -0
  4. data/README.md +485 -0
  5. data/Rakefile +139 -0
  6. data/example/app/retro_games.rb +57 -0
  7. data/example/app/whywiki_erb/layout/wiki.html.erb +15 -0
  8. data/example/app/whywiki_erb/spec/wiki.rb +19 -0
  9. data/example/app/whywiki_erb/start.rb +45 -0
  10. data/example/app/whywiki_erb/view/edit.html.erb +6 -0
  11. data/example/app/whywiki_erb/view/index.html.erb +10 -0
  12. data/example/custom_middleware.rb +43 -0
  13. data/example/error_handling.rb +31 -0
  14. data/example/hello.rb +12 -0
  15. data/example/howto_spec.rb +60 -0
  16. data/example/link.rb +35 -0
  17. data/example/providing_hash.rb +46 -0
  18. data/example/session.rb +42 -0
  19. data/innate.gemspec +118 -0
  20. data/lib/innate.rb +191 -0
  21. data/lib/innate/action.rb +156 -0
  22. data/lib/innate/adapter.rb +89 -0
  23. data/lib/innate/cache.rb +117 -0
  24. data/lib/innate/cache/api.rb +106 -0
  25. data/lib/innate/cache/drb.rb +58 -0
  26. data/lib/innate/cache/file_based.rb +39 -0
  27. data/lib/innate/cache/marshal.rb +17 -0
  28. data/lib/innate/cache/memory.rb +22 -0
  29. data/lib/innate/cache/yaml.rb +17 -0
  30. data/lib/innate/core_compatibility/basic_object.rb +9 -0
  31. data/lib/innate/core_compatibility/string.rb +3 -0
  32. data/lib/innate/current.rb +37 -0
  33. data/lib/innate/dynamap.rb +81 -0
  34. data/lib/innate/helper.rb +195 -0
  35. data/lib/innate/helper/aspect.rb +62 -0
  36. data/lib/innate/helper/cgi.rb +39 -0
  37. data/lib/innate/helper/flash.rb +36 -0
  38. data/lib/innate/helper/link.rb +55 -0
  39. data/lib/innate/helper/partial.rb +90 -0
  40. data/lib/innate/helper/redirect.rb +85 -0
  41. data/lib/innate/helper/send_file.rb +18 -0
  42. data/lib/innate/log.rb +23 -0
  43. data/lib/innate/log/color_formatter.rb +43 -0
  44. data/lib/innate/log/hub.rb +72 -0
  45. data/lib/innate/mock.rb +49 -0
  46. data/lib/innate/node.rb +471 -0
  47. data/lib/innate/options.rb +91 -0
  48. data/lib/innate/options/dsl.rb +155 -0
  49. data/lib/innate/request.rb +165 -0
  50. data/lib/innate/response.rb +18 -0
  51. data/lib/innate/route.rb +109 -0
  52. data/lib/innate/session.rb +104 -0
  53. data/lib/innate/session/flash.rb +94 -0
  54. data/lib/innate/setup.rb +23 -0
  55. data/lib/innate/spec.rb +42 -0
  56. data/lib/innate/state.rb +22 -0
  57. data/lib/innate/state/accessor.rb +130 -0
  58. data/lib/innate/state/fiber.rb +68 -0
  59. data/lib/innate/state/thread.rb +39 -0
  60. data/lib/innate/traited.rb +20 -0
  61. data/lib/innate/trinity.rb +22 -0
  62. data/lib/innate/version.rb +3 -0
  63. data/lib/innate/view.rb +67 -0
  64. data/lib/innate/view/erb.rb +17 -0
  65. data/lib/innate/view/none.rb +9 -0
  66. data/lib/rack/middleware_compiler.rb +62 -0
  67. data/lib/rack/reloader.rb +192 -0
  68. data/spec/example/hello.rb +14 -0
  69. data/spec/example/link.rb +29 -0
  70. data/spec/helper.rb +2 -0
  71. data/spec/innate/cache/common.rb +45 -0
  72. data/spec/innate/cache/marshal.rb +5 -0
  73. data/spec/innate/cache/memory.rb +5 -0
  74. data/spec/innate/cache/yaml.rb +5 -0
  75. data/spec/innate/dynamap.rb +22 -0
  76. data/spec/innate/helper.rb +66 -0
  77. data/spec/innate/helper/aspect.rb +80 -0
  78. data/spec/innate/helper/cgi.rb +37 -0
  79. data/spec/innate/helper/flash.rb +148 -0
  80. data/spec/innate/helper/link.rb +82 -0
  81. data/spec/innate/helper/partial.rb +66 -0
  82. data/spec/innate/helper/redirect.rb +148 -0
  83. data/spec/innate/helper/send_file.rb +21 -0
  84. data/spec/innate/helper/view/aspect_hello.erb +1 -0
  85. data/spec/innate/helper/view/locals.erb +1 -0
  86. data/spec/innate/helper/view/loop.erb +4 -0
  87. data/spec/innate/helper/view/num.erb +1 -0
  88. data/spec/innate/helper/view/partial.erb +1 -0
  89. data/spec/innate/helper/view/recursive.erb +8 -0
  90. data/spec/innate/mock.rb +84 -0
  91. data/spec/innate/node.rb +180 -0
  92. data/spec/innate/node/bar.html +1 -0
  93. data/spec/innate/node/foo.html.erb +1 -0
  94. data/spec/innate/node/with_layout.erb +3 -0
  95. data/spec/innate/options.rb +90 -0
  96. data/spec/innate/parameter.rb +154 -0
  97. data/spec/innate/request.rb +73 -0
  98. data/spec/innate/route.rb +129 -0
  99. data/spec/innate/session.rb +59 -0
  100. data/spec/innate/traited.rb +55 -0
  101. 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,6 @@
1
+ <a href="<%= r @page %>"><%= h "< #{@page}" %></a>
2
+ <form method="post" action="<%= r :save %>">
3
+ <input type="hidden" name="page" value="<%= h @page %>" />
4
+ <textarea name="text"><%= @text %></textarea>
5
+ <input type="submit" value="Save" />
6
+ </form>
@@ -0,0 +1,10 @@
1
+ <% unless @page == 'Home' %>
2
+ <a href="<%= r 'Home' %>">&lt; 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,12 @@
1
+ require 'innate'
2
+
3
+ class Hello
4
+ include Innate::Node
5
+ map '/'
6
+
7
+ def index
8
+ 'Hello, World!'
9
+ end
10
+ end
11
+
12
+ Innate.start
@@ -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