innate 2012.03 → 2012.12

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.
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