manveru-innate 2009.02.21 → 2009.02.25

Sign up to get free protection for your applications and to get access to all the features.
Files changed (43) hide show
  1. data/CHANGELOG +112 -0
  2. data/MANIFEST +6 -3
  3. data/Rakefile +2 -5
  4. data/example/app/retro_games.rb +2 -2
  5. data/example/app/todo/layout/default.erb +11 -0
  6. data/example/app/todo/spec/todo.rb +63 -0
  7. data/example/app/todo/start.rb +51 -0
  8. data/example/app/todo/view/index.erb +39 -0
  9. data/example/app/whywiki_erb/layout/wiki.html.erb +1 -1
  10. data/example/app/whywiki_erb/start.rb +3 -7
  11. data/example/app/whywiki_erb/view/edit.html.erb +1 -1
  12. data/example/app/whywiki_erb/view/index.html.erb +6 -4
  13. data/example/custom_middleware.rb +5 -13
  14. data/example/hello.rb +1 -2
  15. data/example/howto_spec.rb +14 -39
  16. data/example/link.rb +5 -13
  17. data/example/session.rb +16 -20
  18. data/innate.gemspec +7 -4
  19. data/lib/innate/action.rb +8 -7
  20. data/lib/innate/adapter.rb +1 -1
  21. data/lib/innate/cache.rb +9 -0
  22. data/lib/innate/core_compatibility/basic_object.rb +1 -0
  23. data/lib/innate/helper.rb +5 -5
  24. data/lib/innate/node.rb +18 -17
  25. data/lib/innate/options.rb +2 -2
  26. data/lib/innate/spec.rb +25 -4
  27. data/lib/innate/state.rb +12 -4
  28. data/lib/innate/traited.rb +55 -3
  29. data/lib/innate/version.rb +1 -1
  30. data/lib/innate/view/erb.rb +1 -1
  31. data/lib/innate/view/none.rb +2 -2
  32. data/lib/innate/view.rb +4 -2
  33. data/lib/innate.rb +137 -104
  34. data/spec/example/hello.rb +0 -1
  35. data/spec/example/link.rb +3 -7
  36. data/spec/example/session.rb +28 -0
  37. data/spec/innate/helper/redirect.rb +1 -4
  38. data/spec/innate/node/only_view.html +1 -0
  39. data/spec/innate/node.rb +12 -0
  40. metadata +8 -5
  41. data/example/error_handling.rb +0 -31
  42. data/example/providing_hash.rb +0 -46
  43. data/lib/innate/setup.rb +0 -23
data/lib/innate.rb CHANGED
@@ -59,81 +59,59 @@ module Innate
59
59
 
60
60
  extend Trinity
61
61
 
62
- # This constant holds a couple of common middlewares and allows for easy
63
- # addition of new ones.
64
- # The Proc to use is determined by the value of options.mode.
65
- # The Proc value is passed to setup_middleware if no block is given to
66
- # Innate::start.
67
- #
68
- # A quick overview over the middleware used here:
69
- #
70
- # * Rack::CommonLogger
71
- # Logs a line in Apache common log format or <tt>rack.errors</tt>.
72
- #
73
- # * Rack::ShowExceptions
74
- # Catches all exceptions raised from the app it wraps. It shows a useful
75
- # backtrace with the sourcefile and clickable context, the whole Rack
76
- # environment and the request data.
77
- # Be careful when you use this on public-facing sites as it could reveal
78
- # information helpful to attackers.
79
- #
80
- # * Rack::ShowStatus
81
- # Catches all empty responses the app it wraps and replaces them with a
82
- # site explaining the error.
83
- # Additional details can be put into <tt>rack.showstatus.detail</tt> and
84
- # will be shown as HTML. If such details exist, the error page is always
85
- # rendered, even if the reply was not empty.
86
- #
87
- # * Rack::ConditionalGet
88
- # Middleware that enables conditional GET using If-None-Match and
89
- # If-Modified-Since. The application should set either or both of the
90
- # Last-Modified or Etag response headers according to RFC 2616. When
91
- # either of the conditions is met, the response body is set to be zero
92
- # length and the response status is set to 304 Not Modified.
93
- #
94
- # * Rack::Head
95
- # Removes the body of the response for HEAD requests.
96
- #
97
- # * Rack::Reloader
98
- # Pure ruby source reloader, runs on every request with a configurable
99
- # cooldown period.
100
- #
101
- # * Rack::Lint
102
- # Rack::Lint validates your application and the requests and responses
103
- # according to the Rack spec.
104
- #
105
- # Note that `m.innate` takes away most of the boring part and leaves it up to
106
- # you to select your middleware in your application.
107
- #
108
- # `m.innate` expands to:
109
- #
110
- # use Rack::Cascade.new([
111
- # Rack::File.new('public'),
112
- # Innate::Current.new(
113
- # Rack::Cascade.new([
114
- # Innate::Rewrite.new(Innate::DynaMap),
115
- # Innate::Route.new(Innate::DynaMap)])))
116
- #
117
- # @see Rack::MiddlewareCompiler
118
- MIDDLEWARE = {
119
- :dev => lambda{|m|
120
- m.use(Rack::Lint, Rack::CommonLogger, Rack::ShowExceptions,
121
- Rack::ShowStatus, Rack::ConditionalGet, Rack::Head, Rack::Reloader)
122
- m.innate },
123
- :live => lambda{|m|
124
- m.use(Rack::CommonLogger, Rack::ShowStatus, Rack::ConditionalGet,
125
- Rack::Head)
126
- m.innate }
127
- }
128
-
62
+ # Contains all the module functions for Innate, we keep them in a module so
63
+ # Ramaze can simply use them as well.
129
64
  module SingletonMethods
130
- def start(parameter = {}, &block)
131
- options[:app][:root] = go_figure_root(parameter, caller)
132
- parameter.reject!{|k, v| [:root, :file].include?(k) }
133
- options.merge!(parameter)
65
+ # The method that starts the whole business.
66
+ #
67
+ # Call Innate.start after you defined your application.
68
+ #
69
+ # Usually, this is a blocking call and will not return until the adapter
70
+ # has finished, which usually happens when you kill the application or hit
71
+ # ^C.
72
+ #
73
+ # We do return if options.started is true, which indicates that all you
74
+ # wanted to do is setup the environment and update options.
75
+ #
76
+ # @usage
77
+ #
78
+ # # passing options
79
+ # Innate.start :adapter => :mongrel, :mode => :live
80
+ #
81
+ # # defining custom middleware
82
+ # Innate.start do |m|
83
+ # m.innate
84
+ # end
85
+ #
86
+ # @return [nil] if options.started is true
87
+ # @yield [MiddlewareCompiler]
88
+ # @param [Proc] block will be passed to {middleware!}
89
+ #
90
+ # @option param :host [String] ('0.0.0.0')
91
+ # IP address or hostname that we respond to - 0.0.0.0 for all
92
+ # @option param :port [Fixnum] (7000)
93
+ # Port for the server
94
+ # @option param :started [boolean] (false)
95
+ # Indicate that calls Innate::start will be ignored
96
+ # @option param :adapter [Symbol] (:webrick)
97
+ # Web server to run on
98
+ # @option param :setup [Array] ([Innate::Cache, Innate::Node])
99
+ # Will send ::setup to each element during Innate::start
100
+ # @option param :header [Hash] ({'Content-Type' => 'text/html'})
101
+ # Headers that will be merged into the response before Node::call
102
+ # @option param :trap [String] ('SIGINT')
103
+ # Trap this signal to issue shutdown, nil/false to disable trap
104
+ # @option param :state [Symbol] (:Fiber)
105
+ # Keep state in Thread or Fiber, fall back to Thread if Fiber not available
106
+ # @option param :mode [Symbol] (:dev)
107
+ # Indicates which default middleware to use, (:dev|:live)
108
+ def start(param = {}, &block)
109
+ options[:app][:root] = go_figure_root(param, caller)
110
+ param.reject!{|k, v| [:root, :file].include?(k) }
111
+ options.merge!(param)
134
112
 
135
113
  setup_dependencies
136
- setup_middleware(&block)
114
+ middleware!(options.mode, &block) if block_given?
137
115
 
138
116
  return if options.started
139
117
  options.started = true
@@ -144,53 +122,42 @@ module Innate
144
122
  end
145
123
 
146
124
  def start!(options = Innate.options)
147
- Adapter.start(middleware(:innate), options)
125
+ Adapter.start(middleware(options.mode), options)
148
126
  end
149
127
 
150
128
  def stop(wait = 3)
151
- Log.info("Shutdown Innate within #{wait} seconds")
129
+ Log.info("Shutdown within #{wait} seconds")
152
130
  Timeout.timeout(wait){ exit }
153
131
  ensure
154
132
  exit!
155
133
  end
156
134
 
157
- def middleware(name, &block)
158
- Rack::MiddlewareCompiler.build(name, &block)
159
- end
160
-
161
- def middleware!(name, &block)
162
- Rack::MiddlewareCompiler.build!(name, &block)
163
- end
164
-
165
- def middleware_recompile(name = :innate)
166
- Rack::MiddlewareCompiler::COMPILED[name].compile!
167
- end
168
-
169
135
  def setup_dependencies
170
136
  options[:setup].each{|obj| obj.setup }
171
137
  end
172
138
 
173
- # Set the default middleware for applications.
174
- def setup_middleware(force = false, &block)
175
- mode = options.mode
176
- block ||= MIDDLEWARE[mode]
177
- raise("No Middleware for mode: %p found" % mode) unless block
178
-
179
- force ? middleware!(:innate, &block) : middleware(:innate, &block)
139
+ # Treat Innate like a rack application, pass the rack +env+ and optionally
140
+ # the +mode+ the application runs in.
141
+ #
142
+ # @param [Hash] env rack env
143
+ # @param [Symbol] mode indicates the mode of the application
144
+ # @default mode options.mode
145
+ # @return [Array] with [body, header, status]
146
+ # @author manveru
147
+ def call(env, mode = options.mode)
148
+ middleware(mode).call(env)
180
149
  end
181
150
 
182
- # Pass the +env+ to this method and it will be sent to the appropriate
183
- # middleware called +mw+.
184
- # Tries to avoid recursion.
185
-
186
- def call(env, mw = :innate)
187
- this_file = File.expand_path(__FILE__)
188
- count = 0
189
- caller_lines(caller){|f, l, m| count += 1 if f == this_file }
151
+ def middleware(mode, &block)
152
+ Rack::MiddlewareCompiler.build(mode, &block)
153
+ end
190
154
 
191
- raise("Recursive loop in Innate::call") if count > 10
155
+ def middleware!(mode, &block)
156
+ Rack::MiddlewareCompiler.build!(mode, &block)
157
+ end
192
158
 
193
- middleware(mw).call(env)
159
+ def middleware_recompile(mode = options.mode)
160
+ Rack::MiddlewareCompiler::COMPILED[mode].compile!
194
161
  end
195
162
 
196
163
  # Innate can be started by:
@@ -203,7 +170,6 @@ module Innate
203
170
  #
204
171
  # TODO: better documentation and nice defaults, don't want to rely on a
205
172
  # filename, bad mojo.
206
-
207
173
  def go_figure_root(options, backtrace)
208
174
  if o_file = options[:file]
209
175
  return File.dirname(o_file)
@@ -240,4 +206,71 @@ module Innate
240
206
  end
241
207
 
242
208
  extend SingletonMethods
209
+
210
+ # This sets up the default modes.
211
+ # The Proc to use is determined by the value of options.mode.
212
+ # The Proc value is passed to setup_middleware if no block is given to
213
+ # Innate::start.
214
+ #
215
+ # A quick overview over the middleware used here:
216
+ #
217
+ # * Rack::CommonLogger
218
+ # Logs a line in Apache common log format or <tt>rack.errors</tt>.
219
+ #
220
+ # * Rack::ShowExceptions
221
+ # Catches all exceptions raised from the app it wraps. It shows a useful
222
+ # backtrace with the sourcefile and clickable context, the whole Rack
223
+ # environment and the request data.
224
+ # Be careful when you use this on public-facing sites as it could reveal
225
+ # information helpful to attackers.
226
+ #
227
+ # * Rack::ShowStatus
228
+ # Catches all empty responses the app it wraps and replaces them with a
229
+ # site explaining the error.
230
+ # Additional details can be put into <tt>rack.showstatus.detail</tt> and
231
+ # will be shown as HTML. If such details exist, the error page is always
232
+ # rendered, even if the reply was not empty.
233
+ #
234
+ # * Rack::ConditionalGet
235
+ # Middleware that enables conditional GET using If-None-Match and
236
+ # If-Modified-Since. The application should set either or both of the
237
+ # Last-Modified or Etag response headers according to RFC 2616. When
238
+ # either of the conditions is met, the response body is set to be zero
239
+ # length and the response status is set to 304 Not Modified.
240
+ #
241
+ # * Rack::Head
242
+ # Removes the body of the response for HEAD requests.
243
+ #
244
+ # * Rack::Reloader
245
+ # Pure ruby source reloader, runs on every request with a configurable
246
+ # cooldown period.
247
+ #
248
+ # * Rack::Lint
249
+ # Rack::Lint validates your application and the requests and responses
250
+ # according to the Rack spec.
251
+ #
252
+ # Note that `m.innate` takes away most of the boring part and leaves it up to
253
+ # you to select your middleware in your application.
254
+ #
255
+ # `m.innate` expands to:
256
+ #
257
+ # use Rack::Cascade.new([
258
+ # Rack::File.new('public'),
259
+ # Innate::Current.new(
260
+ # Rack::Cascade.new([
261
+ # Innate::Rewrite.new(Innate::DynaMap),
262
+ # Innate::Route.new(Innate::DynaMap)])))
263
+ #
264
+ # @see Rack::MiddlewareCompiler
265
+ middleware :dev do |m|
266
+ m.use(Rack::Lint, Rack::CommonLogger, Rack::ShowExceptions,
267
+ Rack::ShowStatus, Rack::ConditionalGet, Rack::Head, Rack::Reloader)
268
+ m.innate
269
+ end
270
+
271
+ middleware :live do |m|
272
+ m.use(Rack::CommonLogger, Rack::ShowStatus, Rack::ConditionalGet,
273
+ Rack::Head)
274
+ m.innate
275
+ end
243
276
  end
@@ -1,5 +1,4 @@
1
1
  require 'spec/helper'
2
-
3
2
  require 'example/hello'
4
3
 
5
4
  describe 'example/hello' do
data/spec/example/link.rb CHANGED
@@ -5,21 +5,17 @@ describe 'example/link' do
5
5
  behaves_like :mock
6
6
 
7
7
  should 'have index on Linking' do
8
- get('/').body.should == 'simple link<br /><a href="/help">Help?</a>'
9
- end
10
-
11
- should 'have new on Linking' do
12
- get('/new').body.should == 'Something new!'
8
+ get('/').body.should == 'Index links to <a href="/help">Help?</a>'
13
9
  end
14
10
 
15
11
  should 'have help on Linking' do
16
12
  get('/help').body.should ==
17
- "You have help<br /><a href=\"/link_to/another\">A Different Node</a>"
13
+ "Help links to <a href=\"/link_to/another\">A Different Node</a>"
18
14
  end
19
15
 
20
16
  should 'have another on Different' do
21
17
  get('/link_to/another').body.
22
- should == "<a href=\"/link_to/and/deeper\">Even deeper</a>"
18
+ should == "<a href=\"/link_to/and/deeper\">Another links even deeper</a>"
23
19
  end
24
20
 
25
21
  should 'have and__deeper on Different' do
@@ -0,0 +1,28 @@
1
+ require 'spec/helper'
2
+ require 'example/session'
3
+
4
+ describe 'example/session' do
5
+ behaves_like :session
6
+
7
+ it 'starts at 0' do
8
+ session do |mock|
9
+ mock.get('/').should =~ /Value is: 0/
10
+ end
11
+ end
12
+
13
+ it 'increments the counter' do
14
+ session do |mock|
15
+ mock.get('/increment').should =~ /Value is: 1/
16
+ mock.get('/increment').should =~ /Value is: 2/
17
+ mock.get('/increment').should =~ /Value is: 3/
18
+ end
19
+ end
20
+
21
+ it 'decrements the counter' do
22
+ session do |mock|
23
+ mock.get('/decrement').should =~ /Value is: -1/
24
+ mock.get('/decrement').should =~ /Value is: -2/
25
+ mock.get('/decrement').should =~ /Value is: -3/
26
+ end
27
+ end
28
+ end
@@ -1,7 +1,7 @@
1
1
  require 'spec/helper'
2
2
 
3
3
  class SpecRedirectHelper
4
- include Innate::Node
4
+ Innate.node '/'
5
5
 
6
6
  def index
7
7
  self.class.name
@@ -59,9 +59,6 @@ class SpecRedirectHelper
59
59
  end
60
60
  end
61
61
 
62
- Innate.setup_dependencies
63
- Innate.setup_middleware
64
-
65
62
  describe Innate::Helper::Redirect do
66
63
  behaves_like :mock
67
64
 
@@ -0,0 +1 @@
1
+ Only template
data/spec/innate/node.rb CHANGED
@@ -206,6 +206,18 @@ describe 'Innate::Node' do
206
206
  got.body.should == 'No action found at: "/bar"'
207
207
  end
208
208
 
209
+ should 'get an action view if there is no method' do
210
+ got = Innate::Mock.get('/provide_template/only_view')
211
+ got.status.should == 200
212
+ got.body.strip.should == "Only template"
213
+ end
214
+
215
+ should 'not get an action view with params if there is no method' do
216
+ got = Innate::Mock.get('/provide_template/only_view/param')
217
+ got.status.should == 404
218
+ got.body.strip.should == 'No action found at: "/only_view/param"'
219
+ end
220
+
209
221
  should 'use alias_view' do
210
222
  assert_wish('/alias_view/aliased', "<h1>Hello, World!</h1>", 'text/html')
211
223
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: manveru-innate
3
3
  version: !ruby/object:Gem::Version
4
- version: 2009.02.21
4
+ version: 2009.02.25
5
5
  platform: ruby
6
6
  authors:
7
7
  - Michael 'manveru' Fellinger
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-02-13 00:00:00 -08:00
12
+ date: 2009-02-25 00:00:00 -08:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -37,17 +37,19 @@ files:
37
37
  - README.md
38
38
  - Rakefile
39
39
  - example/app/retro_games.rb
40
+ - example/app/todo/layout/default.erb
41
+ - example/app/todo/spec/todo.rb
42
+ - example/app/todo/start.rb
43
+ - example/app/todo/view/index.erb
40
44
  - example/app/whywiki_erb/layout/wiki.html.erb
41
45
  - example/app/whywiki_erb/spec/wiki.rb
42
46
  - example/app/whywiki_erb/start.rb
43
47
  - example/app/whywiki_erb/view/edit.html.erb
44
48
  - example/app/whywiki_erb/view/index.html.erb
45
49
  - example/custom_middleware.rb
46
- - example/error_handling.rb
47
50
  - example/hello.rb
48
51
  - example/howto_spec.rb
49
52
  - example/link.rb
50
- - example/providing_hash.rb
51
53
  - example/session.rb
52
54
  - innate.gemspec
53
55
  - lib/innate.rb
@@ -84,7 +86,6 @@ files:
84
86
  - lib/innate/route.rb
85
87
  - lib/innate/session.rb
86
88
  - lib/innate/session/flash.rb
87
- - lib/innate/setup.rb
88
89
  - lib/innate/spec.rb
89
90
  - lib/innate/state.rb
90
91
  - lib/innate/state/accessor.rb
@@ -100,6 +101,7 @@ files:
100
101
  - lib/rack/reloader.rb
101
102
  - spec/example/hello.rb
102
103
  - spec/example/link.rb
104
+ - spec/example/session.rb
103
105
  - spec/helper.rb
104
106
  - spec/innate/action/layout.rb
105
107
  - spec/innate/action/layout/file_layout.erb
@@ -127,6 +129,7 @@ files:
127
129
  - spec/innate/node/another_layout/another_layout.erb
128
130
  - spec/innate/node/bar.html
129
131
  - spec/innate/node/foo.html.erb
132
+ - spec/innate/node/only_view.html
130
133
  - spec/innate/node/with_layout.erb
131
134
  - spec/innate/options.rb
132
135
  - spec/innate/parameter.rb
@@ -1,31 +0,0 @@
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
@@ -1,46 +0,0 @@
1
- require 'innate'
2
-
3
- # This demonstrates how to obtain different content types from the return value
4
- # of action methods.
5
- #
6
- # Try following requests:
7
- # /set/foo/bar
8
- # /set/duh/duf
9
- #
10
- # /index.json
11
- # /index.yaml
12
- #
13
- # /get/foo.json
14
- # /get/foo.yaml
15
- #
16
- # Note that this functionality is quite experimental, but by strategically
17
- # placing ressources in actions it may be possible to achieve interesting
18
- # effects and interoperability with JavaScript at a low cost.
19
- #
20
- # TODO:
21
- # * parsing requests based on the content-type, but that's much less
22
- # straight-forward and would require some kind of convention?
23
-
24
- class Dict
25
- include Innate::Node
26
- map '/'
27
-
28
- DICT = {}
29
-
30
- # /get/foo || /get/foo.json || /get/foo.yaml
31
- def get(key)
32
- {key => DICT[key]}
33
- end
34
-
35
- # /set/foo/bar || /set/foo/bar.json || /set/foo/bar.yaml
36
- def set(key, value)
37
- {key => (DICT[key] = value)}
38
- end
39
-
40
- # /index.json || /.json || /index.yaml || /.yaml
41
- def index
42
- DICT
43
- end
44
- end
45
-
46
- Innate.start
data/lib/innate/setup.rb DELETED
@@ -1,23 +0,0 @@
1
- module Innate
2
- def self.setup(&block)
3
- Setup.new(&block)
4
- end
5
-
6
- class Setup
7
- def initialize(&block)
8
- instance_eval(&block) if block
9
- end
10
-
11
- def gem(*args)
12
- raise
13
- end
14
-
15
- def start(options = {})
16
- Innate.start(options)
17
- end
18
-
19
- def require(*libs)
20
- libs.flatten.each{|lib| Kernel::require(lib) }
21
- end
22
- end
23
- end