rjspotter-innate 2009.06.29

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/AUTHORS +10 -0
  2. data/CHANGELOG +3261 -0
  3. data/COPYING +18 -0
  4. data/MANIFEST +127 -0
  5. data/README.md +563 -0
  6. data/Rakefile +39 -0
  7. data/example/app/retro_games.rb +60 -0
  8. data/example/app/todo/layout/default.xhtml +11 -0
  9. data/example/app/todo/spec/todo.rb +63 -0
  10. data/example/app/todo/start.rb +51 -0
  11. data/example/app/todo/view/index.xhtml +39 -0
  12. data/example/app/whywiki_erb/layout/wiki.html.erb +15 -0
  13. data/example/app/whywiki_erb/spec/wiki.rb +19 -0
  14. data/example/app/whywiki_erb/start.rb +42 -0
  15. data/example/app/whywiki_erb/view/edit.erb +6 -0
  16. data/example/app/whywiki_erb/view/index.erb +12 -0
  17. data/example/custom_middleware.rb +35 -0
  18. data/example/hello.rb +11 -0
  19. data/example/howto_spec.rb +35 -0
  20. data/example/link.rb +27 -0
  21. data/example/provides.rb +31 -0
  22. data/example/session.rb +38 -0
  23. data/innate.gemspec +41 -0
  24. data/lib/innate.rb +269 -0
  25. data/lib/innate/action.rb +137 -0
  26. data/lib/innate/adapter.rb +76 -0
  27. data/lib/innate/cache.rb +134 -0
  28. data/lib/innate/cache/api.rb +128 -0
  29. data/lib/innate/cache/drb.rb +58 -0
  30. data/lib/innate/cache/file_based.rb +44 -0
  31. data/lib/innate/cache/marshal.rb +20 -0
  32. data/lib/innate/cache/memory.rb +21 -0
  33. data/lib/innate/cache/yaml.rb +20 -0
  34. data/lib/innate/current.rb +35 -0
  35. data/lib/innate/dynamap.rb +96 -0
  36. data/lib/innate/helper.rb +185 -0
  37. data/lib/innate/helper/aspect.rb +124 -0
  38. data/lib/innate/helper/cgi.rb +54 -0
  39. data/lib/innate/helper/flash.rb +36 -0
  40. data/lib/innate/helper/link.rb +94 -0
  41. data/lib/innate/helper/redirect.rb +85 -0
  42. data/lib/innate/helper/render.rb +152 -0
  43. data/lib/innate/helper/send_file.rb +26 -0
  44. data/lib/innate/log.rb +20 -0
  45. data/lib/innate/log/color_formatter.rb +49 -0
  46. data/lib/innate/log/hub.rb +77 -0
  47. data/lib/innate/middleware_compiler.rb +65 -0
  48. data/lib/innate/mock.rb +49 -0
  49. data/lib/innate/node.rb +1029 -0
  50. data/lib/innate/options.rb +37 -0
  51. data/lib/innate/options/dsl.rb +205 -0
  52. data/lib/innate/options/stub.rb +7 -0
  53. data/lib/innate/request.rb +141 -0
  54. data/lib/innate/response.rb +24 -0
  55. data/lib/innate/route.rb +114 -0
  56. data/lib/innate/session.rb +133 -0
  57. data/lib/innate/session/flash.rb +94 -0
  58. data/lib/innate/spec.rb +1 -0
  59. data/lib/innate/spec/bacon.rb +28 -0
  60. data/lib/innate/state.rb +26 -0
  61. data/lib/innate/state/accessor.rb +130 -0
  62. data/lib/innate/traited.rb +90 -0
  63. data/lib/innate/trinity.rb +18 -0
  64. data/lib/innate/version.rb +3 -0
  65. data/lib/innate/view.rb +97 -0
  66. data/lib/innate/view/erb.rb +14 -0
  67. data/lib/innate/view/etanni.rb +33 -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 +121 -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 +115 -0
  86. data/spec/innate/helper/link.rb +139 -0
  87. data/spec/innate/helper/redirect.rb +171 -0
  88. data/spec/innate/helper/render.rb +165 -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/modes.rb +61 -0
  98. data/spec/innate/node/mapping.rb +37 -0
  99. data/spec/innate/node/node.rb +135 -0
  100. data/spec/innate/node/resolve.rb +82 -0
  101. data/spec/innate/node/view/another_layout/another_layout.xhtml +3 -0
  102. data/spec/innate/node/view/bar.xhtml +1 -0
  103. data/spec/innate/node/view/foo.html.xhtml +1 -0
  104. data/spec/innate/node/view/only_view.xhtml +1 -0
  105. data/spec/innate/node/view/with_layout.xhtml +1 -0
  106. data/spec/innate/node/wrap_action_call.rb +83 -0
  107. data/spec/innate/options.rb +123 -0
  108. data/spec/innate/parameter.rb +154 -0
  109. data/spec/innate/provides.rb +99 -0
  110. data/spec/innate/provides/list.html.xhtml +1 -0
  111. data/spec/innate/provides/list.txt.xhtml +1 -0
  112. data/spec/innate/request.rb +79 -0
  113. data/spec/innate/route.rb +135 -0
  114. data/spec/innate/session.rb +58 -0
  115. data/spec/innate/traited.rb +55 -0
  116. data/tasks/authors.rake +30 -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_setup.rake +99 -0
  121. data/tasks/grancher.rake +12 -0
  122. data/tasks/manifest.rake +4 -0
  123. data/tasks/rcov.rake +19 -0
  124. data/tasks/release.rake +53 -0
  125. data/tasks/reversion.rake +8 -0
  126. data/tasks/setup.rake +6 -0
  127. data/tasks/ycov.rake +84 -0
  128. metadata +218 -0
@@ -0,0 +1,18 @@
1
+ require 'innate/state/accessor'
2
+ require 'innate/request'
3
+
4
+ module Innate
5
+ # The module to be included into the Controller it basically just provides
6
+ # #request, #response and #session, each accessing Thread.current to
7
+ # retrieve the demanded object
8
+
9
+ module Trinity
10
+ extend StateAccessor
11
+
12
+ state_accessor :request, :response, :session, :actions
13
+
14
+ def action
15
+ actions.last
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,3 @@
1
+ module Innate
2
+ VERSION = "2009.06.12"
3
+ end
@@ -0,0 +1,97 @@
1
+ module Innate
2
+
3
+ # This is a container module for wrappers of templating engines and handles
4
+ # lazy requiring of needed engines.
5
+ module View
6
+ include Optioned
7
+
8
+ ENGINE, TEMP = {}, {}
9
+
10
+ options.dsl do
11
+ o "Cache compiled templates",
12
+ :cache, true
13
+
14
+ o "Cache template files after they're read to prevent additional filesystem calls",
15
+ :read_cache, false
16
+ end
17
+
18
+ # In order to be able to render actions without running
19
+ # Innate::setup_dependencies we have to add the cache here already.
20
+ Cache.add(:view)
21
+
22
+ module_function
23
+
24
+ def compile(string)
25
+ return yield(string.to_s) unless View.options.cache
26
+ string = string.to_s
27
+ checksum = Digest::MD5.hexdigest(string)
28
+ Cache.view[checksum] ||= yield(string)
29
+ end
30
+
31
+ def exts_of(engine)
32
+ name = engine.to_s
33
+ ENGINE.reject{|k,v| v != name }.keys
34
+ end
35
+
36
+ # Try to obtain given engine by its registered name.
37
+ def get(engine)
38
+ if klass = TEMP[engine]
39
+ return klass
40
+ elsif klass = ENGINE[engine]
41
+ TEMP[engine] = obtain(klass)
42
+ else
43
+ TEMP[engine] = obtain(engine, View)
44
+ end
45
+ end
46
+
47
+ # We need to put this in a Mutex because simultanous calls for the same
48
+ # class will cause race conditions and one call may return the wrong class
49
+ # on the first request (before TEMP is set).
50
+ # No mutex is used in Fiber environment, see Innate::State and subclasses.
51
+ def obtain(klass, root = Object)
52
+ Thread.exclusive{
53
+ klass.to_s.scan(/\w+/){|part| root = root.const_get(part) }
54
+ return root
55
+ }
56
+ end
57
+
58
+ # Reads the specified view template from the filesystem. When the read_cache
59
+ # option is enabled, templates will be cached to prevent unnecessary
60
+ # filesystem reads in the future.
61
+ #
62
+ # @example usage
63
+ #
64
+ # View.read('some/file.xhtml')
65
+ #
66
+ # @param [#to_str] view
67
+ #
68
+ # @api private
69
+ # @see Action#render
70
+ def read(view)
71
+ return Cache.view[view] ||= ::File.read(view) if View.options.read_cache
72
+ ::File.read(view)
73
+ end
74
+
75
+ # Register given templating engine wrapper and extensions for later usage.
76
+ #
77
+ # +name+ : the class name of the templating engine wrapper
78
+ # +exts+ : any number of arguments will be turned into strings via #to_s
79
+ # that indicate which filename-extensions the templates may have.
80
+ def register(klass, *exts)
81
+ exts.each do |ext|
82
+ ext = ext.to_s
83
+ engine = ENGINE[ext]
84
+ Log.warn("overwriting %p, was set to %p" % [ext, engine]) if engine
85
+ ENGINE[ext] = klass
86
+ end
87
+ end
88
+
89
+ autoload :None, 'innate/view/none'
90
+ autoload :ERB, 'innate/view/erb'
91
+ autoload :Etanni, 'innate/view/etanni'
92
+
93
+ register 'Innate::View::None', :css, :html, :htm
94
+ register 'Innate::View::ERB', :erb
95
+ register 'Innate::View::Etanni', :xhtml
96
+ end
97
+ end
@@ -0,0 +1,14 @@
1
+ require 'erb'
2
+
3
+ module Innate
4
+ module View
5
+ module ERB
6
+ def self.call(action, string)
7
+ erb = View.compile(string){|s| ::ERB.new(s, nil, '%<>') }
8
+ erb.filename = (action.view || action.method).to_s
9
+ html = erb.result(action.binding)
10
+ return html, 'text/html'
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,33 @@
1
+ module Innate
2
+ module View
3
+ module Etanni
4
+ def self.call(action, string)
5
+ etanni = View.compile(string){|s| Innate::Etanni.new(s) }
6
+ html = etanni.result(action.binding, (action.view || action.method))
7
+ return html, 'text/html'
8
+ end
9
+ end
10
+ end
11
+
12
+ class Etanni
13
+ SEPARATOR = "E69t116A65n110N78i105S83e101P80a97R82a97T84o111R82"
14
+ START = "\n<<#{SEPARATOR}.chomp\n"
15
+ STOP = "\n#{SEPARATOR}\n"
16
+ ADD = "_out_ << "
17
+
18
+ def initialize(template)
19
+ @template = template
20
+ compile
21
+ end
22
+
23
+ def compile
24
+ temp = @template.dup
25
+ temp.gsub!(/<\?r\s+(.*?)\s+\?>/m, "#{STOP} \\1; #{ADD} #{START}")
26
+ @compiled = "_out_ = #{START} #{temp} #{STOP} _out_"
27
+ end
28
+
29
+ def result(binding, filename = '<Etanni>')
30
+ eval(@compiled, binding, filename).to_s.strip
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,9 @@
1
+ module Innate
2
+ module View
3
+ module None
4
+ def self.call(action, string)
5
+ return string.to_s, 'text/html'
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,30 @@
1
+ require 'spec/helper'
2
+ require 'example/app/retro_games'
3
+
4
+ describe 'Retro-games app' do
5
+ behaves_like :rack_test
6
+
7
+ it 'lists the first game' do
8
+ get '/'
9
+ last_response.should =~ /1 =&gt; Pacman/
10
+ end
11
+
12
+ it 'has a form to add another game' do
13
+ get '/'
14
+ last_response.should =~ /<form/
15
+ end
16
+
17
+ it 'allows you to add another game' do
18
+ post '/create', :name => 'Street Fighter II'
19
+ follow_redirect!
20
+ last_response.should =~ /0 =&gt; Street Fighter II/
21
+ end
22
+
23
+ it 'allows you to vote for a game' do
24
+ get '/vote/Street+Fighter+II'
25
+ follow_redirect!
26
+ last_response.should =~ /1 =&gt; Street Fighter II/
27
+ end
28
+
29
+ FileUtils.rm_f('games.yaml')
30
+ end
@@ -0,0 +1,13 @@
1
+ require 'spec/helper'
2
+ require 'example/hello'
3
+
4
+ describe 'example/hello' do
5
+ behaves_like :rack_test
6
+
7
+ should 'have index action' do
8
+ got = get('/')
9
+ got.status.should == 200
10
+ got['Content-Type'].should == 'text/html'
11
+ got.body.should == 'Hello, World!'
12
+ end
13
+ end
@@ -0,0 +1,25 @@
1
+ require 'spec/helper'
2
+ require 'example/link'
3
+
4
+ describe 'example/link' do
5
+ behaves_like :rack_test
6
+
7
+ should 'have index on Linking' do
8
+ get('/').body.should == 'Index links to <a href="/help">Help?</a>'
9
+ end
10
+
11
+ should 'have help on Linking' do
12
+ get('/help').body.should ==
13
+ "Help links to <a href=\"/link_to/another\">A Different Node</a>"
14
+ end
15
+
16
+ should 'have another on Different' do
17
+ get('/link_to/another').body.
18
+ should == "<a href=\"/link_to/and/deeper\">Another links even deeper</a>"
19
+ end
20
+
21
+ should 'have and__deeper on Different' do
22
+ get('/link_to/and/deeper').body.
23
+ should == "<a href=\"/index\">Back to Linking Node</a>"
24
+ end
25
+ end
@@ -0,0 +1,16 @@
1
+ require 'spec/helper'
2
+ require 'example/provides'
3
+
4
+ describe 'examples/provide' do
5
+ behaves_like :rack_test
6
+
7
+ it 'provides YAML representation' do
8
+ get '/list.yaml'
9
+ last_response.body.should == ARTICLES.to_yaml
10
+ last_response['Content-Type'].should == 'text/yaml'
11
+
12
+ get '/list'
13
+ last_response.body.should == ''
14
+ last_response['Content-Type'].should == 'text/html'
15
+ end
16
+ end
@@ -0,0 +1,22 @@
1
+ require 'spec/helper'
2
+ require 'example/session'
3
+
4
+ describe 'example/session' do
5
+ behaves_like :rack_test
6
+
7
+ it 'starts at 0' do
8
+ get('/').body.should =~ /Value is: 0/
9
+ end
10
+
11
+ it 'increments the counter' do
12
+ get('/increment').body.should =~ /Value is: 1/
13
+ get('/increment').body.should =~ /Value is: 2/
14
+ get('/increment').body.should =~ /Value is: 3/
15
+ end
16
+
17
+ it 'decrements the counter' do
18
+ get('/decrement').body.should =~ /Value is: 2/
19
+ get('/decrement').body.should =~ /Value is: 1/
20
+ get('/decrement').body.should =~ /Value is: 0/
21
+ end
22
+ end
@@ -0,0 +1,10 @@
1
+ if caller_line = caller.grep(%r!spec/innate/!).first
2
+ caller_file = caller_line.split(':', 2).first
3
+ caller_root = File.dirname(caller_file)
4
+ $0 = caller_file
5
+ end
6
+
7
+ require File.expand_path(File.join(File.dirname(__FILE__), '../lib/innate'))
8
+ require 'innate/spec'
9
+
10
+ Innate.options.roots = [caller_root] if caller_root
@@ -0,0 +1,121 @@
1
+ require 'spec/helper'
2
+
3
+ class SpecActionLayout
4
+ include Innate::Node
5
+ map_layouts '/'
6
+ end
7
+
8
+ class SpecActionLayoutMethod < SpecActionLayout
9
+ Innate.node('/from_method', self)
10
+ layout('method_layout')
11
+
12
+ def method_layout
13
+ '<pre>#{ @content }</pre>'
14
+ end
15
+
16
+ def index
17
+ 'Method Layout'
18
+ end
19
+
20
+ def foo
21
+ "bar"
22
+ end
23
+ end
24
+
25
+ class SpecActionLayoutFile < SpecActionLayout
26
+ Innate.node('/from_file', self)
27
+ layout('file_layout')
28
+
29
+ def index
30
+ "File Layout"
31
+ end
32
+ end
33
+
34
+ class SpecActionLayoutSpecific < SpecActionLayout
35
+ Innate.node('/specific', self)
36
+ layout('file_layout'){|name, wish| name == 'index' }
37
+
38
+ def index
39
+ 'Specific Layout'
40
+ end
41
+
42
+ def without
43
+ "Without wrapper"
44
+ end
45
+ end
46
+
47
+ class SpecActionLayoutDeny < SpecActionLayout
48
+ Innate.node('/deny', self)
49
+ layout('file_layout'){|name, wish| name != 'without' }
50
+
51
+ def index
52
+ "Deny Layout"
53
+ end
54
+
55
+ def without
56
+ "Without wrapper"
57
+ end
58
+ end
59
+
60
+ class SpecActionLayoutMulti < SpecActionLayout
61
+ Innate.node('/multi', self)
62
+ layout('file_layout'){|name, wish| name =~ /index|second/ }
63
+
64
+ def index
65
+ "Multi Layout Index"
66
+ end
67
+
68
+ def second
69
+ "Multi Layout Second"
70
+ end
71
+
72
+ def without
73
+ "Without wrapper"
74
+ end
75
+ end
76
+
77
+ class SpecIVFromView < SpecActionLayout
78
+ Innate.node('/iv', self)
79
+ layout :multiply
80
+
81
+ def index
82
+ '#{ @a = 1 }'
83
+ end
84
+
85
+ def multiply
86
+ '#{@content} #{ @a * 2 } #{ @a * 3 }'
87
+ end
88
+ end
89
+
90
+ describe 'Innate::Action#layout' do
91
+ behaves_like :rack_test
92
+
93
+ it 'uses a layout method' do
94
+ get('/from_method').body.should == '<pre>Method Layout</pre>'
95
+ get('/from_method/foo').body.should == '<pre>bar</pre>'
96
+ end
97
+
98
+ it 'uses a layout file' do
99
+ get('/from_file').body.strip.should == '<p>File Layout</p>'
100
+ end
101
+
102
+ it 'denies layout to some actions' do
103
+ get('/deny').body.strip.should == '<p>Deny Layout</p>'
104
+ get('/deny/without').body.strip.should == 'Without wrapper'
105
+ end
106
+
107
+ it 'uses layout only for specific action' do
108
+ get('/specific').body.strip.should == '<p>Specific Layout</p>'
109
+ get('/specific/without').body.strip.should == 'Without wrapper'
110
+ end
111
+
112
+ it 'uses layout only for specific actions' do
113
+ get('/multi').body.strip.should == '<p>Multi Layout Index</p>'
114
+ get('/multi/second').body.strip.should == '<p>Multi Layout Second</p>'
115
+ get('/multi/without').body.strip.should == 'Without wrapper'
116
+ end
117
+
118
+ it 'uses layout only for specific actions' do
119
+ get('/iv').body.strip.should == '1 2 3'
120
+ end
121
+ end
@@ -0,0 +1 @@
1
+ <p>#{ @content }</p>
@@ -0,0 +1,47 @@
1
+ require 'spec/helper'
2
+
3
+ Innate::Cache.options.names = [:one, :two]
4
+ Innate::Cache.options.one = $common_cache_class
5
+ Innate::Cache.options.two = $common_cache_class
6
+ Innate.setup_dependencies
7
+
8
+ describe $common_cache_class do
9
+ cache = Innate::Cache.one
10
+
11
+ @hello = 'Hello, World!'
12
+
13
+ should 'store without ttl' do
14
+ cache.store(:hello, @hello).should == @hello
15
+ end
16
+
17
+ should 'fetch' do
18
+ cache.fetch(:hello).should == @hello
19
+ end
20
+
21
+ should 'delete' do
22
+ cache.delete(:hello)
23
+ cache.fetch(:hello).should == nil
24
+ end
25
+
26
+ should 'delete two key/value pairs at once' do
27
+ cache.store(:hello, @hello).should == @hello
28
+ cache.store(:innate, 'innate').should == 'innate'
29
+ cache.delete(:hello, :innate)
30
+ cache.fetch(:hello).should == nil
31
+ cache.fetch(:innate).should == nil
32
+ end
33
+
34
+ should 'store with ttl' do
35
+ cache.store(:hello, @hello, :ttl => 0.2)
36
+ cache.fetch(:hello).should == @hello
37
+ sleep 0.3
38
+ cache.fetch(:hello).should == nil
39
+ end
40
+
41
+ should 'clear' do
42
+ cache.store(:hello, @hello)
43
+ cache.fetch(:hello).should == @hello
44
+ cache.clear
45
+ cache.fetch(:hello).should == nil
46
+ end
47
+ end