innate 2009.04

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 (128) hide show
  1. data/CHANGELOG +2981 -0
  2. data/COPYING +18 -0
  3. data/MANIFEST +127 -0
  4. data/README.md +563 -0
  5. data/Rakefile +35 -0
  6. data/example/app/retro_games.rb +60 -0
  7. data/example/app/todo/layout/default.xhtml +11 -0
  8. data/example/app/todo/spec/todo.rb +63 -0
  9. data/example/app/todo/start.rb +51 -0
  10. data/example/app/todo/view/index.xhtml +39 -0
  11. data/example/app/whywiki_erb/layout/wiki.html.erb +15 -0
  12. data/example/app/whywiki_erb/spec/wiki.rb +19 -0
  13. data/example/app/whywiki_erb/start.rb +42 -0
  14. data/example/app/whywiki_erb/view/edit.erb +6 -0
  15. data/example/app/whywiki_erb/view/index.erb +12 -0
  16. data/example/custom_middleware.rb +35 -0
  17. data/example/hello.rb +11 -0
  18. data/example/howto_spec.rb +35 -0
  19. data/example/link.rb +27 -0
  20. data/example/provides.rb +31 -0
  21. data/example/session.rb +38 -0
  22. data/innate.gemspec +29 -0
  23. data/lib/innate.rb +269 -0
  24. data/lib/innate/action.rb +150 -0
  25. data/lib/innate/adapter.rb +76 -0
  26. data/lib/innate/cache.rb +134 -0
  27. data/lib/innate/cache/api.rb +128 -0
  28. data/lib/innate/cache/drb.rb +58 -0
  29. data/lib/innate/cache/file_based.rb +41 -0
  30. data/lib/innate/cache/marshal.rb +17 -0
  31. data/lib/innate/cache/memory.rb +22 -0
  32. data/lib/innate/cache/yaml.rb +17 -0
  33. data/lib/innate/current.rb +37 -0
  34. data/lib/innate/dynamap.rb +96 -0
  35. data/lib/innate/helper.rb +183 -0
  36. data/lib/innate/helper/aspect.rb +124 -0
  37. data/lib/innate/helper/cgi.rb +54 -0
  38. data/lib/innate/helper/flash.rb +36 -0
  39. data/lib/innate/helper/link.rb +94 -0
  40. data/lib/innate/helper/redirect.rb +85 -0
  41. data/lib/innate/helper/render.rb +87 -0
  42. data/lib/innate/helper/send_file.rb +26 -0
  43. data/lib/innate/log.rb +20 -0
  44. data/lib/innate/log/color_formatter.rb +43 -0
  45. data/lib/innate/log/hub.rb +73 -0
  46. data/lib/innate/middleware_compiler.rb +65 -0
  47. data/lib/innate/mock.rb +49 -0
  48. data/lib/innate/node.rb +1025 -0
  49. data/lib/innate/options.rb +37 -0
  50. data/lib/innate/options/dsl.rb +202 -0
  51. data/lib/innate/options/stub.rb +7 -0
  52. data/lib/innate/request.rb +141 -0
  53. data/lib/innate/response.rb +23 -0
  54. data/lib/innate/route.rb +110 -0
  55. data/lib/innate/session.rb +121 -0
  56. data/lib/innate/session/flash.rb +94 -0
  57. data/lib/innate/spec.rb +23 -0
  58. data/lib/innate/state.rb +27 -0
  59. data/lib/innate/state/accessor.rb +130 -0
  60. data/lib/innate/state/fiber.rb +74 -0
  61. data/lib/innate/state/thread.rb +47 -0
  62. data/lib/innate/traited.rb +85 -0
  63. data/lib/innate/trinity.rb +18 -0
  64. data/lib/innate/version.rb +3 -0
  65. data/lib/innate/view.rb +60 -0
  66. data/lib/innate/view/erb.rb +15 -0
  67. data/lib/innate/view/etanni.rb +36 -0
  68. data/lib/innate/view/none.rb +9 -0
  69. data/spec/example/app/retro_games.rb +30 -0
  70. data/spec/example/hello.rb +13 -0
  71. data/spec/example/link.rb +25 -0
  72. data/spec/example/provides.rb +16 -0
  73. data/spec/example/session.rb +22 -0
  74. data/spec/helper.rb +10 -0
  75. data/spec/innate/action/layout.rb +107 -0
  76. data/spec/innate/action/layout/file_layout.xhtml +1 -0
  77. data/spec/innate/cache/common.rb +47 -0
  78. data/spec/innate/cache/marshal.rb +5 -0
  79. data/spec/innate/cache/memory.rb +5 -0
  80. data/spec/innate/cache/yaml.rb +5 -0
  81. data/spec/innate/dynamap.rb +22 -0
  82. data/spec/innate/helper.rb +86 -0
  83. data/spec/innate/helper/aspect.rb +75 -0
  84. data/spec/innate/helper/cgi.rb +37 -0
  85. data/spec/innate/helper/flash.rb +118 -0
  86. data/spec/innate/helper/link.rb +139 -0
  87. data/spec/innate/helper/redirect.rb +160 -0
  88. data/spec/innate/helper/render.rb +133 -0
  89. data/spec/innate/helper/send_file.rb +21 -0
  90. data/spec/innate/helper/view/aspect_hello.xhtml +1 -0
  91. data/spec/innate/helper/view/locals.xhtml +1 -0
  92. data/spec/innate/helper/view/loop.xhtml +4 -0
  93. data/spec/innate/helper/view/num.xhtml +1 -0
  94. data/spec/innate/helper/view/partial.xhtml +1 -0
  95. data/spec/innate/helper/view/recursive.xhtml +7 -0
  96. data/spec/innate/mock.rb +84 -0
  97. data/spec/innate/node/mapping.rb +37 -0
  98. data/spec/innate/node/node.rb +134 -0
  99. data/spec/innate/node/resolve.rb +82 -0
  100. data/spec/innate/node/view/another_layout/another_layout.xhtml +3 -0
  101. data/spec/innate/node/view/bar.xhtml +1 -0
  102. data/spec/innate/node/view/foo.html.xhtml +1 -0
  103. data/spec/innate/node/view/only_view.xhtml +1 -0
  104. data/spec/innate/node/view/with_layout.xhtml +1 -0
  105. data/spec/innate/node/wrap_action_call.rb +83 -0
  106. data/spec/innate/options.rb +115 -0
  107. data/spec/innate/parameter.rb +154 -0
  108. data/spec/innate/provides.rb +99 -0
  109. data/spec/innate/provides/list.html.xhtml +1 -0
  110. data/spec/innate/provides/list.txt.xhtml +1 -0
  111. data/spec/innate/request.rb +77 -0
  112. data/spec/innate/route.rb +135 -0
  113. data/spec/innate/session.rb +54 -0
  114. data/spec/innate/state/fiber.rb +58 -0
  115. data/spec/innate/state/thread.rb +40 -0
  116. data/spec/innate/traited.rb +55 -0
  117. data/tasks/bacon.rake +66 -0
  118. data/tasks/changelog.rake +18 -0
  119. data/tasks/gem.rake +22 -0
  120. data/tasks/gem_installer.rake +76 -0
  121. data/tasks/grancher.rake +12 -0
  122. data/tasks/install_dependencies.rake +4 -0
  123. data/tasks/manifest.rake +4 -0
  124. data/tasks/rcov.rake +19 -0
  125. data/tasks/release.rake +51 -0
  126. data/tasks/reversion.rake +8 -0
  127. data/tasks/setup.rake +28 -0
  128. metadata +181 -0
@@ -0,0 +1,99 @@
1
+ begin
2
+ require 'json'
3
+ rescue LoadError
4
+ exit
5
+ end
6
+
7
+ require 'spec/helper'
8
+ require 'yaml'
9
+
10
+ Innate.options.merge!(:views => 'provides', :layouts => 'provides')
11
+
12
+ class SpecNodeProvides
13
+ Innate.node '/'
14
+
15
+ provide(:html, :engine => :None)
16
+ provide(:yaml, :type => 'text/yaml'){|a,s| s.to_yaml }
17
+ provide(:json, :type => 'application/json'){|a,s| s.to_json }
18
+
19
+ def object
20
+ {'intro' => 'Hello, World!'}
21
+ end
22
+
23
+ def string
24
+ 'Just 42'
25
+ end
26
+ end
27
+
28
+ class SpecNodeProvidesTemplates
29
+ Innate.node '/template'
30
+ map_views '/'
31
+
32
+ provide(:yaml, :type => 'text/yaml'){|a,s| s.to_yaml }
33
+ provide(:json, :type => 'application/json'){|a,s| s.to_json }
34
+ provide(:txt, :engine => :Etanni, :type => 'text/plain')
35
+
36
+ def list
37
+ @users = %w[starbucks apollo athena]
38
+ end
39
+ end
40
+
41
+ shared :assert_wish do
42
+ def assert_wish(uri, body, content_type)
43
+ got = get(uri)
44
+ got.status.should == 200
45
+ got.body.strip.should == body.strip
46
+ got['Content-Type'].should == content_type
47
+ end
48
+ end
49
+
50
+ describe 'Content representation' do
51
+ describe 'without template' do
52
+ behaves_like :mock, :assert_wish
53
+
54
+ it 'provides yaml for an object' do
55
+ assert_wish('/object.yaml', {'intro' => 'Hello, World!'}.to_yaml, 'text/yaml')
56
+ end
57
+
58
+ it 'provides json for an object' do
59
+ assert_wish('/object.json', {'intro' => 'Hello, World!'}.to_json, 'application/json')
60
+ end
61
+
62
+ it 'provides html for an object' do
63
+ assert_wish('/string.html', 'Just 42', 'text/html')
64
+ end
65
+
66
+ it 'defaults to html presentation' do
67
+ assert_wish('/string', 'Just 42', 'text/html')
68
+ end
69
+ end
70
+
71
+ describe 'with templates' do
72
+ behaves_like :mock, :assert_wish
73
+
74
+ it 'defaults to <name>.html.<engine>' do
75
+ body = '<ul><li>starbucks</li><li>apollo</li><li>athena</li></ul>'
76
+ assert_wish('/template/list', body, 'text/html')
77
+ end
78
+
79
+ it 'uses explicit wish for <name>.html.<engine>' do
80
+ body = '<ul><li>starbucks</li><li>apollo</li><li>athena</li></ul>'
81
+ assert_wish('/template/list.html', body, 'text/html')
82
+ end
83
+
84
+ it 'fails when the wish cannot be satisfied' do
85
+ got = get('/template/list.svg')
86
+ got.status.should == 404
87
+ end
88
+
89
+ it 'uses the object returned from the action method for block provides' do
90
+ body = %w[starbucks apollo athena].to_yaml
91
+ assert_wish('/template/list.yaml', body, 'text/yaml')
92
+ end
93
+
94
+ it 'uses explicit wish for <name>.txt.<engine>' do
95
+ body = "starbucks\napollo\nathena"
96
+ assert_wish('/template/list.txt', body, 'text/plain')
97
+ end
98
+ end
99
+ end
@@ -0,0 +1 @@
1
+ <ul><?r @users.each do |user| ?><li>#{user}</li><?r end ?></ul>
@@ -0,0 +1 @@
1
+ <?r @users.each do |user| ?>#{"#{user}\n"}<?r end ?>
@@ -0,0 +1,77 @@
1
+ require 'spec/helper'
2
+
3
+ describe Innate::Request do
4
+ def request(env = {})
5
+ Innate::Request.new(@env.merge(env))
6
+ end
7
+
8
+ @env = {
9
+ "GATEWAY_INTERFACE" => "CGI/1.1",
10
+ "HTTP_ACCEPT" => "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
11
+ "HTTP_ACCEPT_CHARSET" => "UTF-8,*",
12
+ "HTTP_ACCEPT_ENCODING" => "gzip,deflate",
13
+ "HTTP_ACCEPT_LANGUAGE" => "en-us,en;q=0.8,de-at;q=0.5,de;q=0.3",
14
+ "HTTP_CACHE_CONTROL" => "max-age=0",
15
+ "HTTP_CONNECTION" => "keep-alive",
16
+ "HTTP_HOST" => "localhost:7000",
17
+ "HTTP_KEEP_ALIVE" => "300",
18
+ "HTTP_USER_AGENT" => "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.0.5) Gecko/2008123017 Firefox/3.0.4 Ubiquity/0.1.4",
19
+ "HTTP_VERSION" => "HTTP/1.1",
20
+ "PATH_INFO" => "/",
21
+ "QUERY_STRING" => "a=b",
22
+ "REMOTE_ADDR" => "127.0.0.1",
23
+ "REMOTE_HOST" => "delta.local",
24
+ "REQUEST_METHOD" => "GET",
25
+ "REQUEST_PATH" => "/",
26
+ "REQUEST_URI" => "http://localhost:7000/",
27
+ "SCRIPT_NAME" => "",
28
+ "SERVER_NAME" => "localhost",
29
+ "SERVER_PORT" => "7000",
30
+ "SERVER_PROTOCOL" => "HTTP/1.1",
31
+ }
32
+
33
+ should 'provide #request_uri' do
34
+ request('REQUEST_URI' => '/?a=b').request_uri.should == '/?a=b'
35
+ request('REQUEST_URI' => '/').request_uri.should == '/'
36
+ end
37
+
38
+ should 'provide #local_net?' do
39
+ request.local_net?('192.168.0.1').to_s.should == '192.168.0.0'
40
+ request.local_net?('252.168.0.1').should == nil
41
+ request.local_net?('unknown').should == nil
42
+ request('REMOTE_ADDR' => '211.3.129.47, 66.249.85.131').local_net?.should == nil
43
+ request('REMOTE_ADDR' => '211.3.129.47').local_net?.should == nil
44
+ end
45
+
46
+ should 'provide #subset' do
47
+ params = {'a' => 'b', 'c' => 'd', 'e' => 'f'}
48
+ env = { 'rack.request.form_hash' => params }
49
+ req = request(env)
50
+
51
+ req.params.should == params
52
+ req.subset(:a).should == {'a' => 'b'}
53
+ req.subset(:a, :c).should == {'a' => 'b', 'c' => 'd'}
54
+ end
55
+
56
+ should 'provide #domain on http' do
57
+ request('rack.url_scheme' => 'http').domain.
58
+ should == URI('http://localhost:7000/')
59
+
60
+ request('rack.url_scheme' => 'http').domain('/foo').
61
+ should == URI('http://localhost:7000/foo')
62
+
63
+ request('rack.url_scheme' => 'http').domain('/foo', :keep_query => true).
64
+ should == URI('http://localhost:7000/foo?a=b')
65
+ end
66
+
67
+ should 'provide #domain on https' do
68
+ request('rack.url_scheme' => 'https').domain.
69
+ should == URI('https://localhost:7000/')
70
+
71
+ request('rack.url_scheme' => 'https').domain('/foo').
72
+ should == URI('https://localhost:7000/foo')
73
+
74
+ request('rack.url_scheme' => 'https').domain('/foo', :keep_query => true).
75
+ should == URI('https://localhost:7000/foo?a=b')
76
+ end
77
+ end
@@ -0,0 +1,135 @@
1
+ require 'spec/helper'
2
+
3
+ class SpecRouter
4
+ Innate.node('/').provide(:html, :None)
5
+
6
+ def float(flt)
7
+ "Float: %3.3f" % flt
8
+ end
9
+
10
+ def string(str)
11
+ "String: #{str}"
12
+ end
13
+
14
+ def price(p)
15
+ "Price: \$#{p}"
16
+ end
17
+
18
+ def sum(a, b)
19
+ a.to_i + b.to_i
20
+ end
21
+
22
+ def bar
23
+ 'this is bar'
24
+ end
25
+ end
26
+
27
+ Route, Rewrite = Innate::Route, Innate::Rewrite
28
+
29
+ describe Innate::Route do
30
+ def check(uri, status, body = nil)
31
+ got = Innate::Mock.get(uri)
32
+ got.status.should == status
33
+ got.body.should == body if body
34
+ end
35
+
36
+ should 'take lambda routers' do
37
+ Route['string'] = lambda{|path, req|
38
+ path if path =~ %r!^/string!
39
+ }
40
+ Route['string'].class.should == Proc
41
+
42
+ Route['calc sum'] = lambda{|path, req|
43
+ if req[:do_calc]
44
+ lval, rval = req[:a, :b]
45
+ rval = rval.to_i * 10
46
+ "/sum/#{lval}/#{rval}"
47
+ end
48
+ }
49
+
50
+ Innate::Route('foo') do |path, req|
51
+ '/bar' if req[:bar]
52
+ end
53
+ end
54
+
55
+ should 'define string routes' do
56
+ Route['/foobar'] = '/bar'
57
+ Route['/foobar'].should == '/bar'
58
+ end
59
+
60
+ should 'define regex routes' do
61
+ Route[%r!^/(\d+\.\d{2})$!] = "/price/%.2f"
62
+ Route[%r!^/(\d+\.\d{2})$!].should == "/price/%.2f"
63
+
64
+ Route[%r!^/(\d+\.\d+)!] = "/float/%.3f"
65
+ Route[%r!^/(\d+\.\d+)!].should == "/float/%.3f"
66
+
67
+ Route[%r!^/(\w+)!] = "/string/%s"
68
+ Route[%r!^/(\w+)!].should == "/string/%s"
69
+ end
70
+
71
+ should 'be used at /float' do
72
+ check('/123.123', 200, 'Float: 123.123')
73
+ end
74
+
75
+ should 'be used at /string' do
76
+ check('/foo', 200, 'String: foo')
77
+ end
78
+
79
+ should 'use %.3f' do
80
+ check('/123.123456', 200, 'Float: 123.123')
81
+ end
82
+
83
+ should 'resolve in the order added' do
84
+ check('/12.84', 200, 'Price: $12.84')
85
+ end
86
+
87
+ should 'use lambda routers' do
88
+ check('/string/abc', 200, 'String: abc')
89
+
90
+ check('/?do_calc=1&a=2&b=6', 200, '62')
91
+ end
92
+
93
+ it 'should support Route() with blocks' do
94
+ check('/foo?bar=1', 200, 'this is bar')
95
+ end
96
+
97
+ it 'should support string route translations' do
98
+ check('/foobar', 200, 'this is bar')
99
+ end
100
+
101
+ it 'should clear routes' do
102
+ Route::ROUTES.size.should > 0
103
+ Route.clear
104
+ Route::ROUTES.size.should == 0
105
+ end
106
+
107
+ it 'should not recurse given a bad route' do
108
+ Innate::Route[ %r!^/good/(.+)$! ] = "/bad/%s"
109
+ check('/good/hi', 404)
110
+ end
111
+ end
112
+
113
+ describe Innate::Rewrite do
114
+ Innate::Rewrite[ %r!^/(.+)$! ] = "/string/%s"
115
+
116
+ it 'should rewrite on non-existent actions' do
117
+ got = Innate::Mock.get('/hello')
118
+ got.status.should == 200
119
+ got.body.should == 'String: hello'
120
+ end
121
+
122
+ it 'should exclude existing actions' do
123
+ got = Innate::Mock.get('/bar')
124
+ got.status.should == 200
125
+ got.body.should == 'this is bar'
126
+ end
127
+
128
+ it 'should rewite with (key, val)' do
129
+ Innate::Rewrite[ %r!^/(.+)$! ] = nil
130
+ Innate::Rewrite(%r!^/(.+)$!, "/string/%s")
131
+ got = Innate::Mock.get('/hello')
132
+ got.status.should == 200
133
+ got.body.should == 'String: hello'
134
+ end
135
+ end
@@ -0,0 +1,54 @@
1
+ require 'spec/helper'
2
+
3
+ class SpecSession
4
+ Innate.node('/').provide(:html, :None)
5
+
6
+ def index
7
+ 'No session here'
8
+ end
9
+
10
+ def init
11
+ session[:counter] = 0
12
+ end
13
+
14
+ def view
15
+ session[:counter]
16
+ end
17
+
18
+ def increment
19
+ session[:counter] += 1
20
+ end
21
+
22
+ def decrement
23
+ session[:counter] -= 1
24
+ end
25
+
26
+ def reset
27
+ session.clear
28
+ end
29
+ end
30
+
31
+ describe Innate::Session do
32
+ behaves_like :mock
33
+
34
+ should 'initiate session as needed' do
35
+ get '/'
36
+ last_response.body.should == 'No session here'
37
+ last_response['Set-Cookie'].should == nil
38
+
39
+ get('/init')
40
+ last_response.body.should == '0'
41
+
42
+ 1.upto(10) do |n|
43
+ get('/increment').body.should == n.to_s
44
+ end
45
+
46
+ get('/reset')
47
+ get('/view').body.should == ''
48
+ get('/init').body.should == '0'
49
+
50
+ -1.downto(-10) do |n|
51
+ get('/decrement').body.should == n.to_s
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,58 @@
1
+ require 'spec/helper'
2
+
3
+ describe 'Innate::State::Fiber' do
4
+ begin
5
+ require 'fiber'
6
+ rescue LoadError
7
+ it('needs fiber'){ should.flunk('needed fiber') }
8
+ exit
9
+ end
10
+
11
+ F = Innate::State::Fiber
12
+
13
+ it 'sets value in current thread with #[]=' do
14
+ Innate::Fiber.new{
15
+ t = F.new
16
+ t[:a] = :b
17
+ Fiber.current[:a].should == :b
18
+ }.resume
19
+ end
20
+
21
+ it 'gets value in current thread with #[]' do
22
+ Innate::Fiber.new{
23
+ t = F.new
24
+ Fiber.current[:b] = :c
25
+ t[:b].should == :c
26
+ }.resume
27
+ end
28
+
29
+ it 'executes block in #wrap' do
30
+ Innate::Fiber.new{
31
+ t = F.new
32
+ t.wrap{ :foo }.should == :foo
33
+ }.resume
34
+ end
35
+
36
+ it 'reraises exceptions occured in #wrap thread' do
37
+ Innate::Fiber.new{
38
+ t = F.new
39
+ Thread.abort_on_exception = false
40
+ lambda{ t.wrap{ raise 'foo' } }.should.raise
41
+ }.resume
42
+ end
43
+
44
+ it 'defers execution of passed block in #defer' do
45
+ Innate::Fiber.new{
46
+ t = F.new
47
+ t.defer{ :foo }.value.should == :foo
48
+ }.resume
49
+ end
50
+
51
+ it 'copies thread variables to thread spawned in #defer' do
52
+ Innate::Fiber.new{
53
+ t = F.new
54
+ t[:a] = :b
55
+ t.defer{ Fiber.current[:a] }.value.should == :b
56
+ }.resume
57
+ end
58
+ end
@@ -0,0 +1,40 @@
1
+ require 'spec/helper'
2
+ require 'innate/state/thread'
3
+
4
+ describe Innate::State::Thread do
5
+ T = Innate::State::Thread
6
+
7
+ it 'sets value in current thread with #[]=' do
8
+ t = T.new
9
+ t[:a] = :b
10
+ Thread.current[:a].should == :b
11
+ end
12
+
13
+ it 'gets value in current thread with #[]' do
14
+ t = T.new
15
+ Thread.current[:b] = :c
16
+ t[:b].should == :c
17
+ end
18
+
19
+ it 'executes block in #wrap' do
20
+ t = T.new
21
+ t.wrap{ :foo }.should == :foo
22
+ end
23
+
24
+ it 'reraises exceptions occured in #wrap thread' do
25
+ t = T.new
26
+ Thread.abort_on_exception = false
27
+ lambda{ t.wrap{ raise 'foo' } }.should.raise
28
+ end
29
+
30
+ it 'defers execution of passed block in #defer' do
31
+ t = T.new
32
+ t.defer{ :foo }.value.should == :foo
33
+ end
34
+
35
+ it 'copies thread variables to thread spawned in #defer' do
36
+ t = T.new
37
+ t[:a] = :b
38
+ t.defer{ Thread.current[:a] }.value.should == :b
39
+ end
40
+ end