innate 2012.03 → 2012.12

Sign up to get free protection for your applications and to get access to all the features.
data/MANIFEST CHANGED
@@ -37,6 +37,7 @@ lib/innate/cache/marshal.rb
37
37
  lib/innate/cache/memory.rb
38
38
  lib/innate/cache/yaml.rb
39
39
  lib/innate/current.rb
40
+ lib/innate/default_middleware.rb
40
41
  lib/innate/dynamap.rb
41
42
  lib/innate/helper.rb
42
43
  lib/innate/helper/aspect.rb
@@ -48,13 +49,12 @@ lib/innate/helper/render.rb
48
49
  lib/innate/log.rb
49
50
  lib/innate/log/color_formatter.rb
50
51
  lib/innate/log/hub.rb
51
- lib/innate/middleware_compiler.rb
52
+ lib/innate/lru_hash.rb
52
53
  lib/innate/mock.rb
53
54
  lib/innate/node.rb
54
55
  lib/innate/options.rb
55
56
  lib/innate/options/dsl.rb
56
57
  lib/innate/options/stub.rb
57
- lib/innate/rack_file_wrapper.rb
58
58
  lib/innate/request.rb
59
59
  lib/innate/response.rb
60
60
  lib/innate/route.rb
@@ -1,5 +1,5 @@
1
1
  require 'rubygems'
2
- require 'innate'
2
+ require File.expand_path('../../lib/innate', __FILE__)
3
3
 
4
4
  class Demo
5
5
  Innate.node '/'
@@ -14,22 +14,26 @@ class Demo
14
14
  end
15
15
  end
16
16
 
17
- Innate.start do |mw|
17
+ Innate.options.mode = :dev
18
+
19
+ Innate.middleware(:dev) do
18
20
  # Makes sure all requests and responses conform to Rack protocol
19
- mw.use Rack::Lint
21
+ use Rack::Lint
20
22
 
21
23
  # Avoid showing empty failure pages, give information when it happens.
22
- mw.use Rack::ShowStatus
24
+ use Rack::ShowStatus
23
25
 
24
26
  # Catch exceptions inside Innate and give nice status info
25
- mw.use Rack::ShowExceptions
27
+ use Rack::ShowExceptions
26
28
 
27
29
  # Log access
28
- mw.use Rack::CommonLogger
30
+ use Rack::CommonLogger
29
31
 
30
32
  # Reload modified files before request
31
- mw.use Rack::Reloader
33
+ use Rack::Reloader
32
34
 
33
35
  # Start up the application
34
- mw.innate
36
+ run Innate.core
35
37
  end
38
+
39
+ Innate.start
data/innate.gemspec CHANGED
@@ -2,18 +2,18 @@
2
2
 
3
3
  Gem::Specification.new do |s|
4
4
  s.name = "innate"
5
- s.version = "2012.03"
5
+ s.version = "2012.12"
6
6
 
7
7
  s.required_rubygems_version = Gem::Requirement.new(">= 1.3.1") if s.respond_to? :required_rubygems_version=
8
8
  s.authors = ["Michael 'manveru' Fellinger"]
9
- s.date = "2012-03-07"
9
+ s.date = "2012-12-07"
10
10
  s.description = "Simple, straight-forward base for web-frameworks."
11
11
  s.email = "m.fellinger@gmail.com"
12
- s.files = [".gems", ".gitignore", ".load_gemset", ".rvmrc", ".travis.yml", "AUTHORS", "CHANGELOG", "COPYING", "MANIFEST", "README.md", "Rakefile", "example/app/retro_games.rb", "example/app/todo/layout/default.xhtml", "example/app/todo/spec/todo.rb", "example/app/todo/start.rb", "example/app/todo/view/index.xhtml", "example/app/whywiki_erb/layout/wiki.html.erb", "example/app/whywiki_erb/spec/wiki.rb", "example/app/whywiki_erb/start.rb", "example/app/whywiki_erb/view/edit.erb", "example/app/whywiki_erb/view/index.erb", "example/custom_middleware.rb", "example/hello.rb", "example/howto_spec.rb", "example/link.rb", "example/provides.rb", "example/session.rb", "innate.gemspec", "lib/innate.rb", "lib/innate/action.rb", "lib/innate/adapter.rb", "lib/innate/cache.rb", "lib/innate/cache/api.rb", "lib/innate/cache/drb.rb", "lib/innate/cache/file_based.rb", "lib/innate/cache/marshal.rb", "lib/innate/cache/memory.rb", "lib/innate/cache/yaml.rb", "lib/innate/current.rb", "lib/innate/dynamap.rb", "lib/innate/helper.rb", "lib/innate/helper/aspect.rb", "lib/innate/helper/cgi.rb", "lib/innate/helper/flash.rb", "lib/innate/helper/link.rb", "lib/innate/helper/redirect.rb", "lib/innate/helper/render.rb", "lib/innate/log.rb", "lib/innate/log/color_formatter.rb", "lib/innate/log/hub.rb", "lib/innate/middleware_compiler.rb", "lib/innate/mock.rb", "lib/innate/node.rb", "lib/innate/options.rb", "lib/innate/options/dsl.rb", "lib/innate/options/stub.rb", "lib/innate/rack_file_wrapper.rb", "lib/innate/request.rb", "lib/innate/response.rb", "lib/innate/route.rb", "lib/innate/session.rb", "lib/innate/session/flash.rb", "lib/innate/spec.rb", "lib/innate/spec/bacon.rb", "lib/innate/state.rb", "lib/innate/state/accessor.rb", "lib/innate/traited.rb", "lib/innate/trinity.rb", "lib/innate/version.rb", "lib/innate/view.rb", "lib/innate/view/erb.rb", "lib/innate/view/etanni.rb", "lib/innate/view/none.rb", "spec/example/app/retro_games.rb", "spec/example/hello.rb", "spec/example/link.rb", "spec/example/provides.rb", "spec/example/session.rb", "spec/helper.rb", "spec/innate/action/layout.rb", "spec/innate/action/layout/file_layout.xhtml", "spec/innate/cache/common.rb", "spec/innate/cache/marshal.rb", "spec/innate/cache/memory.rb", "spec/innate/cache/yaml.rb", "spec/innate/dynamap.rb", "spec/innate/etanni.rb", "spec/innate/helper.rb", "spec/innate/helper/aspect.rb", "spec/innate/helper/cgi.rb", "spec/innate/helper/flash.rb", "spec/innate/helper/link.rb", "spec/innate/helper/redirect.rb", "spec/innate/helper/render.rb", "spec/innate/helper/view/aspect_hello.xhtml", "spec/innate/helper/view/locals.xhtml", "spec/innate/helper/view/loop.xhtml", "spec/innate/helper/view/num.xhtml", "spec/innate/helper/view/partial.xhtml", "spec/innate/helper/view/recursive.xhtml", "spec/innate/mock.rb", "spec/innate/modes.rb", "spec/innate/node/mapping.rb", "spec/innate/node/node.rb", "spec/innate/node/resolve.rb", "spec/innate/node/view/another_layout/another_layout.xhtml", "spec/innate/node/view/bar.xhtml", "spec/innate/node/view/cat2/cat22.xhtml", "spec/innate/node/view/cat3/cat33.xhtml", "spec/innate/node/view/foo.html.xhtml", "spec/innate/node/view/only_view.xhtml", "spec/innate/node/view/sub/baz.xhtml", "spec/innate/node/view/sub/foo/baz.xhtml", "spec/innate/node/view/with_layout.xhtml", "spec/innate/node/wrap_action_call.rb", "spec/innate/options.rb", "spec/innate/parameter.rb", "spec/innate/provides.rb", "spec/innate/provides/list.html.xhtml", "spec/innate/provides/list.txt.xhtml", "spec/innate/request.rb", "spec/innate/response.rb", "spec/innate/route.rb", "spec/innate/session.rb", "spec/innate/traited.rb", "tasks/authors.rake", "tasks/bacon.rake", "tasks/changelog.rake", "tasks/gem.rake", "tasks/gem_setup.rake", "tasks/grancher.rake", "tasks/manifest.rake", "tasks/rcov.rake", "tasks/release.rake", "tasks/reversion.rake", "tasks/setup.rake", "tasks/ycov.rake"]
12
+ s.files = [".gems", ".gitignore", ".load_gemset", ".rvmrc", ".travis.yml", "AUTHORS", "CHANGELOG", "COPYING", "MANIFEST", "README.md", "Rakefile", "example/app/retro_games.rb", "example/app/todo/layout/default.xhtml", "example/app/todo/spec/todo.rb", "example/app/todo/start.rb", "example/app/todo/view/index.xhtml", "example/app/whywiki_erb/layout/wiki.html.erb", "example/app/whywiki_erb/spec/wiki.rb", "example/app/whywiki_erb/start.rb", "example/app/whywiki_erb/view/edit.erb", "example/app/whywiki_erb/view/index.erb", "example/custom_middleware.rb", "example/hello.rb", "example/howto_spec.rb", "example/link.rb", "example/provides.rb", "example/session.rb", "innate.gemspec", "lib/innate.rb", "lib/innate/action.rb", "lib/innate/adapter.rb", "lib/innate/cache.rb", "lib/innate/cache/api.rb", "lib/innate/cache/drb.rb", "lib/innate/cache/file_based.rb", "lib/innate/cache/marshal.rb", "lib/innate/cache/memory.rb", "lib/innate/cache/yaml.rb", "lib/innate/current.rb", "lib/innate/default_middleware.rb", "lib/innate/dynamap.rb", "lib/innate/helper.rb", "lib/innate/helper/aspect.rb", "lib/innate/helper/cgi.rb", "lib/innate/helper/flash.rb", "lib/innate/helper/link.rb", "lib/innate/helper/redirect.rb", "lib/innate/helper/render.rb", "lib/innate/log.rb", "lib/innate/log/color_formatter.rb", "lib/innate/log/hub.rb", "lib/innate/lru_hash.rb", "lib/innate/mock.rb", "lib/innate/node.rb", "lib/innate/options.rb", "lib/innate/options/dsl.rb", "lib/innate/options/stub.rb", "lib/innate/request.rb", "lib/innate/response.rb", "lib/innate/route.rb", "lib/innate/session.rb", "lib/innate/session/flash.rb", "lib/innate/spec.rb", "lib/innate/spec/bacon.rb", "lib/innate/state.rb", "lib/innate/state/accessor.rb", "lib/innate/traited.rb", "lib/innate/trinity.rb", "lib/innate/version.rb", "lib/innate/view.rb", "lib/innate/view/erb.rb", "lib/innate/view/etanni.rb", "lib/innate/view/none.rb", "spec/example/app/retro_games.rb", "spec/example/hello.rb", "spec/example/link.rb", "spec/example/provides.rb", "spec/example/session.rb", "spec/helper.rb", "spec/innate/action/layout.rb", "spec/innate/action/layout/file_layout.xhtml", "spec/innate/cache/common.rb", "spec/innate/cache/marshal.rb", "spec/innate/cache/memory.rb", "spec/innate/cache/yaml.rb", "spec/innate/dynamap.rb", "spec/innate/etanni.rb", "spec/innate/helper.rb", "spec/innate/helper/aspect.rb", "spec/innate/helper/cgi.rb", "spec/innate/helper/flash.rb", "spec/innate/helper/link.rb", "spec/innate/helper/redirect.rb", "spec/innate/helper/render.rb", "spec/innate/helper/view/aspect_hello.xhtml", "spec/innate/helper/view/locals.xhtml", "spec/innate/helper/view/loop.xhtml", "spec/innate/helper/view/num.xhtml", "spec/innate/helper/view/partial.xhtml", "spec/innate/helper/view/recursive.xhtml", "spec/innate/mock.rb", "spec/innate/modes.rb", "spec/innate/node/mapping.rb", "spec/innate/node/node.rb", "spec/innate/node/resolve.rb", "spec/innate/node/view/another_layout/another_layout.xhtml", "spec/innate/node/view/bar.xhtml", "spec/innate/node/view/cat2/cat22.xhtml", "spec/innate/node/view/cat3/cat33.xhtml", "spec/innate/node/view/foo.html.xhtml", "spec/innate/node/view/only_view.xhtml", "spec/innate/node/view/sub/baz.xhtml", "spec/innate/node/view/sub/foo/baz.xhtml", "spec/innate/node/view/with_layout.xhtml", "spec/innate/node/wrap_action_call.rb", "spec/innate/options.rb", "spec/innate/parameter.rb", "spec/innate/provides.rb", "spec/innate/provides/list.html.xhtml", "spec/innate/provides/list.txt.xhtml", "spec/innate/request.rb", "spec/innate/response.rb", "spec/innate/route.rb", "spec/innate/session.rb", "spec/innate/traited.rb", "tasks/authors.rake", "tasks/bacon.rake", "tasks/changelog.rake", "tasks/gem.rake", "tasks/gem_setup.rake", "tasks/grancher.rake", "tasks/manifest.rake", "tasks/rcov.rake", "tasks/release.rake", "tasks/reversion.rake", "tasks/setup.rake", "tasks/ycov.rake"]
13
13
  s.homepage = "http://github.com/manveru/innate"
14
14
  s.require_paths = ["lib"]
15
15
  s.rubyforge_project = "innate"
16
- s.rubygems_version = "1.8.15"
16
+ s.rubygems_version = "1.8.24"
17
17
  s.summary = "Powerful web-framework wrapper for Rack."
18
18
 
19
19
  if s.respond_to? :specification_version then
@@ -21,16 +21,16 @@ Gem::Specification.new do |s|
21
21
 
22
22
  if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
23
23
  s.add_runtime_dependency(%q<rack>, ["~> 1.4.1"])
24
- s.add_development_dependency(%q<rack-test>, [">= 0.6.1"])
25
24
  s.add_development_dependency(%q<bacon>, [">= 1.1.0"])
25
+ s.add_development_dependency(%q<rack-test>, [">= 0.6.1"])
26
26
  else
27
27
  s.add_dependency(%q<rack>, ["~> 1.4.1"])
28
- s.add_dependency(%q<rack-test>, [">= 0.6.1"])
29
28
  s.add_dependency(%q<bacon>, [">= 1.1.0"])
29
+ s.add_dependency(%q<rack-test>, [">= 0.6.1"])
30
30
  end
31
31
  else
32
32
  s.add_dependency(%q<rack>, ["~> 1.4.1"])
33
- s.add_dependency(%q<rack-test>, [">= 0.6.1"])
34
33
  s.add_dependency(%q<bacon>, [">= 1.1.0"])
34
+ s.add_dependency(%q<rack-test>, [">= 0.6.1"])
35
35
  end
36
36
  end
data/lib/innate.rb CHANGED
@@ -22,7 +22,6 @@ module Innate
22
22
  require 'pathname'
23
23
  require 'pp'
24
24
  require 'set'
25
- require 'socket'
26
25
  require 'thread'
27
26
  require 'uri'
28
27
 
@@ -33,12 +32,12 @@ module Innate
33
32
  require 'innate/version'
34
33
  require 'innate/traited'
35
34
  require 'innate/trinity'
36
- require 'innate/middleware_compiler'
37
35
  require 'innate/options/dsl'
38
36
  require 'innate/options/stub'
39
37
  require 'innate/dynamap'
40
38
 
41
39
  # innate full
40
+ require 'innate/lru_hash'
42
41
  require 'innate/cache'
43
42
  require 'innate/node'
44
43
  require 'innate/options'
@@ -53,15 +52,30 @@ module Innate
53
52
  require 'innate/session'
54
53
  require 'innate/session/flash'
55
54
  require 'innate/route'
56
- require 'innate/rack_file_wrapper'
57
55
 
58
56
  extend Trinity
59
57
 
58
+ ##
59
+ # Hash that will contain the middleware for each defined mode.
60
+ #
61
+ # @return [Hash]
62
+ #
63
+ MIDDLEWARE = {}
64
+
60
65
  # Contains all the module functions for Innate, we keep them in a module so
61
66
  # Ramaze can simply use them as well.
62
67
  module SingletonMethods
63
68
  PROXY_OPTIONS = { :port => 'adapter.port', :host => 'adapter.host',
64
69
  :adapter => 'adapter.handler' }
70
+
71
+ ##
72
+ # Returns an instance of `Rack::Builder` that can be used to start a Innate
73
+ # application.
74
+ #
75
+ # @return [Rack::Builder]
76
+ #
77
+ attr_accessor :app
78
+
65
79
  # The method that starts the whole business.
66
80
  #
67
81
  # Call Innate.start after you defined your application.
@@ -78,14 +92,7 @@ module Innate
78
92
  # # passing options
79
93
  # Innate.start :adapter => :mongrel, :mode => :live
80
94
  #
81
- # # defining custom middleware
82
- # Innate.start do |m|
83
- # m.innate
84
- # end
85
- #
86
95
  # @return [nil] if options.started is true
87
- # @yield [MiddlewareCompiler]
88
- # @param [Proc] block will be passed to {middleware!}
89
96
  #
90
97
  # @option param :host [String] ('0.0.0.0')
91
98
  # IP address or hostname that we respond to - 0.0.0.0 for all
@@ -103,7 +110,7 @@ module Innate
103
110
  # Trap this signal to issue shutdown, nil/false to disable trap
104
111
  # @option param :mode [Symbol] (:dev)
105
112
  # Indicates which default middleware to use, (:dev|:live)
106
- def start(options = {}, &block)
113
+ def start(options = {})
107
114
  root, file = options.delete(:root), options.delete(:file)
108
115
  innate_options = Innate.options
109
116
 
@@ -118,19 +125,33 @@ module Innate
118
125
  innate_options.merge!(options)
119
126
 
120
127
  setup_dependencies
121
- middleware!(innate_options.mode, &block) if block_given?
122
128
 
123
129
  return if innate_options.started
130
+
124
131
  innate_options.started = true
125
132
 
126
133
  signal = innate_options.trap
134
+
127
135
  trap(signal){ stop(10) } if signal
128
136
 
137
+ mode = self.options[:mode].to_sym
138
+
139
+ # While Rack itself will spit out errors for invalid instances of
140
+ # Rack::Builder these errors are typically not very user friendly.
141
+ if !Innate.app or !MIDDLEWARE[mode]
142
+ raise(
143
+ ArgumentError,
144
+ "The mode \"#{mode}\" does not have a set of middleware defined. " \
145
+ "You can define these middleware using " \
146
+ "#{self}.middleware(:#{mode}) { ... }"
147
+ )
148
+ end
149
+
129
150
  start!
130
151
  end
131
152
 
132
153
  def start!(mode = options[:mode])
133
- Adapter.start(middleware(mode))
154
+ Adapter.start(Innate.app)
134
155
  end
135
156
 
136
157
  def stop(wait = 3)
@@ -149,6 +170,10 @@ module Innate
149
170
  options[:setup].each{|obj| obj.teardown if obj.respond_to?(:teardown) }
150
171
  end
151
172
 
173
+ def setup
174
+ options.mode ||= (ENV['RACK_ENV'] || :dev)
175
+ end
176
+
152
177
  # Treat Innate like a rack application, pass the rack +env+ and optionally
153
178
  # the +mode+ the application runs in.
154
179
  #
@@ -157,20 +182,63 @@ module Innate
157
182
  # @default mode options.mode
158
183
  # @return [Array] with [body, header, status]
159
184
  # @author manveru
160
- def call(env, mode = options[:mode])
161
- middleware(mode).call(env)
185
+ def call(env)
186
+ Innate.app.call(env)
162
187
  end
163
188
 
164
- def middleware(mode = options[:mode], &block)
165
- options[:middleware_compiler].build(mode, &block)
189
+ ##
190
+ # Updates `Innate.app` based on the current mode.
191
+ #
192
+ # @param [#to_sym] mode The mode to use.
193
+ #
194
+ def recompile_middleware(mode = options[:mode])
195
+ mode = mode.to_sym
196
+
197
+ if MIDDLEWARE[mode]
198
+ Innate.app = Rack::Builder.new(&MIDDLEWARE[mode])
199
+ end
166
200
  end
167
201
 
168
- def middleware!(mode = options[:mode], &block)
169
- options[:middleware_compiler].build!(mode, &block)
202
+ ##
203
+ # Returns an instance of `Rack::Cascade` for running Innate applications.
204
+ # This method should be called using `Rack::Builder#run`:
205
+ #
206
+ # Innate.middleware(:dev) do
207
+ # run Innate.core
208
+ # end
209
+ #
210
+ # @return [Rack::Cascade]
211
+ #
212
+ def core
213
+ roots, publics = options[:roots], options[:publics]
214
+
215
+ joined = roots.map { |root| publics.map { |p| File.join(root, p) } }
216
+ joined = joined.flatten.map { |p| Rack::File.new(p) }
217
+ current = Current.new(Route.new(DynaMap), Rewrite.new(DynaMap))
218
+
219
+ return Rack::Cascade.new(joined << current, [404, 405])
170
220
  end
171
221
 
172
- def middleware_recompile(mode = options[:mode])
173
- options[:middleware_compiler]::COMPILED[mode].compile!
222
+ ##
223
+ # Sets the middleware for the given mode.
224
+ #
225
+ # @example
226
+ # Innate.middleware(:dev) do
227
+ # use Rack::Head
228
+ # use Rack::Reloader
229
+ #
230
+ # run Innate.core
231
+ # end
232
+ #
233
+ # @param [#to_sym] mode The mode that the middleware belong to.
234
+ # @param [Proc] block Block containing the middleware. This block will be
235
+ # passed to an instance of `Rack::Builder` and can thus contain everything
236
+ # this class allows you to use.
237
+ #
238
+ def middleware(mode, &block)
239
+ MIDDLEWARE[mode.to_sym] = block
240
+
241
+ recompile_middleware
174
242
  end
175
243
 
176
244
  # @example Innate can be started by:
@@ -200,71 +268,5 @@ module Innate
200
268
 
201
269
  extend SingletonMethods
202
270
 
203
- # This sets up the default modes.
204
- # The Proc to use is determined by the value of options.mode.
205
- # The Proc value is passed to setup_middleware if no block is given to
206
- # Innate::start.
207
- #
208
- # A quick overview over the middleware used here:
209
- #
210
- # * Rack::CommonLogger
211
- # Logs a line in Apache common log format or <tt>rack.errors</tt>.
212
- #
213
- # * Rack::ShowExceptions
214
- # Catches all exceptions raised from the app it wraps. It shows a useful
215
- # backtrace with the sourcefile and clickable context, the whole Rack
216
- # environment and the request data.
217
- # Be careful when you use this on public-facing sites as it could reveal
218
- # information helpful to attackers.
219
- #
220
- # * Rack::ShowStatus
221
- # Catches all empty responses the app it wraps and replaces them with a
222
- # site explaining the error.
223
- # Additional details can be put into <tt>rack.showstatus.detail</tt> and
224
- # will be shown as HTML. If such details exist, the error page is always
225
- # rendered, even if the reply was not empty.
226
- #
227
- # * Rack::ConditionalGet
228
- # Middleware that enables conditional GET using If-None-Match and
229
- # If-Modified-Since. The application should set either or both of the
230
- # Last-Modified or Etag response headers according to RFC 2616. When
231
- # either of the conditions is met, the response body is set to be zero
232
- # length and the response status is set to 304 Not Modified.
233
- #
234
- # * Rack::Head
235
- # Removes the body of the response for HEAD requests.
236
- #
237
- # * Rack::Reloader
238
- # Pure ruby source reloader, runs on every request with a configurable
239
- # cooldown period.
240
- #
241
- # * Rack::Lint
242
- # Rack::Lint validates your application and the requests and responses
243
- # according to the Rack spec.
244
- #
245
- # Note that `m.innate` takes away most of the boring part and leaves it up to
246
- # you to select your middleware in your application.
247
- #
248
- # `m.innate` expands to:
249
- #
250
- # use Rack::Cascade.new([
251
- # Rack::File.new('public'),
252
- # Innate::Current.new(
253
- # Rack::Cascade.new([
254
- # Innate::Rewrite.new(Innate::DynaMap),
255
- # Innate::Route.new(Innate::DynaMap)]))])
256
- #
257
- # @see Rack::MiddlewareCompiler
258
- middleware :dev do |m|
259
- m.apps(Rack::Lint, Rack::Head, Rack::ContentLength, Rack::CommonLogger,
260
- Rack::ShowExceptions, Rack::ShowStatus, Rack::ConditionalGet)
261
- m.use(Rack::Reloader, 2)
262
- m.innate
263
- end
264
-
265
- middleware :live do |m|
266
- m.apps(Rack::Head, Rack::ContentLength, Rack::CommonLogger,
267
- Rack::ShowStatus, Rack::ConditionalGet)
268
- m.innate
269
- end
271
+ require 'innate/default_middleware'
270
272
  end
data/lib/innate/action.rb CHANGED
@@ -82,12 +82,11 @@ module Innate
82
82
 
83
83
  instance.wrap_action_call(self) do
84
84
  copy_variables
85
- self.method_value = instance.__send__(method, *params) if method
86
- self.view_value = View.read(view) if view
85
+ self.method_value = method ? instance.__send__(method, *params) : nil
86
+ self.view_value = view ? View.read(view) : nil
87
87
 
88
- body, content_type = wrap_in_layout{
89
- engine.call(self, view_value || method_value || '') }
90
- options[:content_type] ||= content_type if content_type
88
+ body, content_type = wrap_in_layout{ engine.call(self, view_value || method_value || '') }
89
+ options[:content_type] ||= content_type
91
90
  body
92
91
  end
93
92
  end
@@ -0,0 +1,22 @@
1
+ Innate.middleware(:dev) do
2
+ use Rack::Lint
3
+ use Rack::Head
4
+ use Rack::ContentLength
5
+ use Rack::CommonLogger
6
+ use Rack::ShowExceptions
7
+ use Rack::ShowStatus
8
+ use Rack::ConditionalGet
9
+ use Rack::Reloader, 2
10
+
11
+ run Innate.core
12
+ end
13
+
14
+ Innate.middleware(:live) do
15
+ use Rack::Head
16
+ use Rack::ContentLength
17
+ use Rack::CommonLogger
18
+ use Rack::ShowStatus
19
+ use Rack::ConditionalGet
20
+
21
+ run Innate.core
22
+ end
@@ -1,12 +1,45 @@
1
1
  module Innate
2
2
  module Helper
3
-
4
- # Provides before/after wrappers for actions
3
+ ##
4
+ # The Aspect helper allows you to execute hooks before or after a number of
5
+ # actions.
6
+ #
7
+ # See {Innate::Helper::Aspect::SingletonMethods} for more details on the
8
+ # various hooks available.
9
+ #
10
+ # @example Querying a database before a number of actions.
11
+ # class Posts
12
+ # include Innate::Node
13
+ #
14
+ # map '/'
15
+ # helper :aspect
16
+ #
17
+ # before(:index, :other) do
18
+ # @posts = Post.all
19
+ # end
20
+ #
21
+ # def index
22
+ # return @posts
23
+ # end
24
+ #
25
+ # def other
26
+ # return @posts[0]
27
+ # end
28
+ # end
5
29
  #
6
30
  # This helper is essential for proper working of {Action#render}.
31
+ #
7
32
  module Aspect
8
- AOP = Hash.new{|h,k| h[k] = Hash.new{|hh,kk| hh[kk] = {} }}
33
+ ##
34
+ # Hash containing the various hooks to call for certain actions.
35
+ #
36
+ AOP = Hash.new { |h,k| h[k] = Hash.new { |hh,kk| hh[kk] = {} } }
9
37
 
38
+ ##
39
+ # Called whenever this helper is included into a class.
40
+ #
41
+ # @param [Class] into The class the module was included into.
42
+ #
10
43
  def self.included(into)
11
44
  into.extend(SingletonMethods)
12
45
  into.add_action_wrapper(5.0, :aspect_wrap)
@@ -15,10 +48,16 @@ module Innate
15
48
  # Consider objects that have Aspect included
16
49
  def self.ancestral_aop(from)
17
50
  aop = {}
18
- from.ancestors.reverse.map{|anc| aop.merge!(AOP[anc]) if anc < Aspect }
51
+ from.ancestors.reverse.map { |anc| aop.merge!(AOP[anc]) if anc < Aspect }
19
52
  aop
20
53
  end
21
54
 
55
+ ##
56
+ # Calls the aspect for a given position and name.
57
+ #
58
+ # @param [#to_sym] position The position of the hook, e.g. :before_all.
59
+ # @param [#to_sym] name The name of the method for which to call the hook.
60
+ #
22
61
  def aspect_call(position, name)
23
62
  return unless aop = Aspect.ancestral_aop(self.class)
24
63
  return unless block = at_position = aop[position]
@@ -28,6 +67,11 @@ module Innate
28
67
  instance_eval(&block) if block
29
68
  end
30
69
 
70
+ ##
71
+ # Wraps the specified action between various hooks.
72
+ #
73
+ # @param [Innate::Action] action The action to wrap.
74
+ #
31
75
  def aspect_wrap(action)
32
76
  return yield unless method = action.name
33
77
 
@@ -40,20 +84,21 @@ module Innate
40
84
  result
41
85
  end
42
86
 
87
+ ##
43
88
  # This awesome piece of hackery implements action AOP.
44
89
  #
45
90
  # The so-called aspects are simply methods that may yield the next aspect
46
- # in the chain, this is similar to racks concept of middleware, but instead
47
- # of initializing with an app we simply pass a block that may be yielded
48
- # with the action being processed.
91
+ # in the chain, this is similar to racks concept of middleware, but
92
+ # instead of initializing with an app we simply pass a block that may be
93
+ # yielded with the action being processed.
49
94
  #
50
- # This gives us things like logging, caching, aspects, authentication, etc.
95
+ # This gives us things like logging, caching, aspects, authentication,
96
+ # etc.
51
97
  #
52
- # Add the name of your method to the trait[:wrap] to add your own method to
53
- # the wrap_action_call chain.
98
+ # Add the name of your method to the trait[:wrap] to add your own method
99
+ # to the wrap_action_call chain.
54
100
  #
55
101
  # @example adding your method
56
- #
57
102
  # class MyNode
58
103
  # Innate.node '/'
59
104
  #
@@ -68,16 +113,17 @@ module Innate
68
113
  # end
69
114
  #
70
115
  #
71
- # methods may register
72
- # themself in the trait[:wrap] and will be called in left-to-right order,
73
- # each being passed the action instance and a block that they have to yield
74
- # to continue the chain.
75
- #
76
- # @param [Action] action instance that is being passed to every registered method
77
- # @param [Proc] block contains the instructions to call the action method if any
116
+ # methods may register themself in the trait[:wrap] and will be called in
117
+ # left-to-right order, each being passed the action instance and a block
118
+ # that they have to yield to continue the chain.
78
119
  #
120
+ # @param [Action] action instance that is being passed to every registered
121
+ # method
122
+ # @param [Proc] block contains the instructions to call the action method
123
+ # if any
79
124
  # @see Action#render
80
125
  # @author manveru
126
+ #
81
127
  def wrap_action_call(action, &block)
82
128
  return yield if action.options[:is_layout]
83
129
  wrap = SortedSet.new
@@ -88,25 +134,142 @@ module Innate
88
134
  __send__(head, action, &combined)
89
135
  end
90
136
 
137
+ ##
138
+ # Module containing various methods that will be made available as class
139
+ # methods to the class that included {Innate::Helper::Aspect}.
140
+ #
91
141
  module SingletonMethods
92
142
  include Traited
93
143
 
144
+ ##
145
+ # Hook that is called before all the actions in a node.
146
+ #
147
+ # @example
148
+ # class MainController
149
+ # include Innate::Node
150
+ #
151
+ # map '/'
152
+ #
153
+ # helper :aspect
154
+ #
155
+ # before_all do
156
+ # puts 'Executed before all actions'
157
+ # end
158
+ #
159
+ # def index
160
+ # return 'Hello, Innate!'
161
+ # end
162
+ # end
163
+ #
94
164
  def before_all(&block)
95
165
  AOP[self][:before_all] = block
96
166
  end
97
167
 
168
+ ##
169
+ # Hook that is called before a specific list of actions.
170
+ #
171
+ # @example
172
+ # class MainController
173
+ # include Innate::Node
174
+ #
175
+ # map '/'
176
+ #
177
+ # helper :aspect
178
+ #
179
+ # before(:index, :other) do
180
+ # puts 'Executed before specific actions only.'
181
+ # end
182
+ #
183
+ # def index
184
+ # return 'Hello, Innate!'
185
+ # end
186
+ #
187
+ # def other
188
+ # return 'Other method'
189
+ # end
190
+ # end
191
+ #
98
192
  def before(*names, &block)
99
193
  names.each{|name| AOP[self][:before][name] = block }
100
194
  end
101
195
 
196
+ ##
197
+ # Hook that is called after all the actions in a node.
198
+ #
199
+ # @example
200
+ # class MainController
201
+ # include Innate::Node
202
+ #
203
+ # map '/'
204
+ #
205
+ # helper :aspect
206
+ #
207
+ # after_all do
208
+ # puts 'Executed after all actions'
209
+ # end
210
+ #
211
+ # def index
212
+ # return 'Hello, Innate!'
213
+ # end
214
+ # end
215
+ #
102
216
  def after_all(&block)
103
217
  AOP[self][:after_all] = block
104
218
  end
105
219
 
220
+ ##
221
+ # Hook that is called after a specific list of actions.
222
+ #
223
+ # @example
224
+ # class MainController
225
+ # include Innate::Node
226
+ #
227
+ # map '/'
228
+ #
229
+ # helper :aspect
230
+ #
231
+ # after(:index, :other) do
232
+ # puts 'Executed after specific actions only.'
233
+ # end
234
+ #
235
+ # def index
236
+ # return 'Hello, Innate!'
237
+ # end
238
+ #
239
+ # def other
240
+ # return 'Other method'
241
+ # end
242
+ # end
243
+ #
106
244
  def after(*names, &block)
107
245
  names.each{|name| AOP[self][:after][name] = block }
108
246
  end
109
247
 
248
+ ##
249
+ # Wraps the block around the list of actions resulting in the block
250
+ # being called both before and after each action.
251
+ #
252
+ # @example
253
+ # class MainController
254
+ # include Innate::Node
255
+ #
256
+ # map '/'
257
+ #
258
+ # helper :aspect
259
+ #
260
+ # wrap(:index) do
261
+ # puts 'Wrapped around the index method'
262
+ # end
263
+ #
264
+ # def index
265
+ # return 'Hello, Innate!'
266
+ # end
267
+ #
268
+ # def other
269
+ # return 'Other method'
270
+ # end
271
+ # end
272
+ #
110
273
  def wrap(*names, &block)
111
274
  before(*names, &block)
112
275
  after(*names, &block)
@@ -119,7 +282,7 @@ module Innate
119
282
  trait :wrap => SortedSet[[order, method_name.to_s]]
120
283
  end
121
284
  end
122
- end
123
- end
124
- end
125
- end
285
+ end # SingletonMethods
286
+ end # Aspect
287
+ end # Helper
288
+ end # Innate