renee 0.3.11 → 0.4.0.pre1

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 (231) hide show
  1. data/Gemfile +17 -0
  2. data/Gemfile-renee +8 -0
  3. data/Gemfile-renee-core +8 -0
  4. data/Gemfile-renee-render +9 -0
  5. data/Gemfile-renee-session +9 -0
  6. data/Gemfile-renee-url-generation +8 -0
  7. data/MIT-LICENSE.txt +7 -0
  8. data/README-renee-core.md +242 -0
  9. data/README-renee-render.md +38 -0
  10. data/README-renee-session.md +3 -0
  11. data/README-renee-url-generation.md +3 -0
  12. data/README.md +131 -6
  13. data/Rakefile +109 -9
  14. data/TODO.txt +45 -0
  15. data/config.ru +26 -0
  16. data/examples/blog/blog.rb +3 -1
  17. data/examples/blog/config.ru +24 -19
  18. data/examples/blog/views/edit.erb +10 -1
  19. data/examples/blog/views/show.erb +5 -0
  20. data/lib/renee.rb +11 -4
  21. data/lib/renee/core.rb +98 -0
  22. data/lib/renee/core/chaining.rb +66 -0
  23. data/lib/renee/core/env_accessors.rb +72 -0
  24. data/lib/renee/core/exceptions.rb +15 -0
  25. data/lib/renee/core/matcher.rb +61 -0
  26. data/lib/renee/core/plugins.rb +31 -0
  27. data/lib/renee/core/rack_interaction.rb +50 -0
  28. data/lib/renee/core/request_context.rb +56 -0
  29. data/lib/renee/core/responding.rb +112 -0
  30. data/lib/renee/core/response.rb +78 -0
  31. data/lib/renee/core/routing.rb +319 -0
  32. data/lib/renee/core/transform.rb +18 -0
  33. data/lib/renee/render.rb +221 -0
  34. data/lib/renee/session.rb +50 -0
  35. data/lib/renee/url_generation.rb +117 -0
  36. data/lib/renee/util.rb +7 -0
  37. data/lib/renee/version.rb +2 -4
  38. data/plan.txt +19 -0
  39. data/renee-core.gemspec +26 -0
  40. data/renee-render.gemspec +30 -0
  41. data/renee-session.gemspec +28 -0
  42. data/renee-url-generation.gemspec +24 -0
  43. data/renee.gemspec +5 -6
  44. data/site/MIT-LICENSE.txt +7 -0
  45. data/site/public/css/app.css +75 -0
  46. data/site/public/docs/renee-core/Renee.html +208 -0
  47. data/site/public/docs/renee-core/Renee/Core.html +366 -0
  48. data/site/public/docs/renee-core/Renee/Core/Chaining.html +192 -0
  49. data/site/public/docs/renee-core/Renee/Core/ClassMethods.html +725 -0
  50. data/site/public/docs/renee-core/Renee/Core/ClientError.html +317 -0
  51. data/site/public/docs/renee-core/Renee/Core/EnvAccessors.html +152 -0
  52. data/site/public/docs/renee-core/Renee/Core/EnvAccessors/ClassMethods.html +354 -0
  53. data/site/public/docs/renee-core/Renee/Core/Matcher.html +675 -0
  54. data/site/public/docs/renee-core/Renee/Core/Plugins.html +475 -0
  55. data/site/public/docs/renee-core/Renee/Core/RackInteraction.html +488 -0
  56. data/site/public/docs/renee-core/Renee/Core/RequestContext.html +511 -0
  57. data/site/public/docs/renee-core/Renee/Core/Responding.html +877 -0
  58. data/site/public/docs/renee-core/Renee/Core/Response.html +691 -0
  59. data/site/public/docs/renee-core/Renee/Core/Routing.html +1589 -0
  60. data/site/public/docs/renee-core/Renee/Core/Transform.html +249 -0
  61. data/site/public/docs/renee-core/Renee/Core/URLGeneration.html +597 -0
  62. data/site/public/docs/renee-core/_index.html +244 -0
  63. data/site/public/docs/renee-core/class_list.html +47 -0
  64. data/site/public/docs/renee-core/css/common.css +1 -0
  65. data/site/public/docs/renee-core/css/full_list.css +55 -0
  66. data/site/public/docs/renee-core/css/style.css +322 -0
  67. data/site/public/docs/renee-core/file.README-renee-core.html +341 -0
  68. data/site/public/docs/renee-core/file.README.html +212 -0
  69. data/site/public/docs/renee-core/file_list.html +49 -0
  70. data/site/public/docs/renee-core/frames.html +13 -0
  71. data/site/public/docs/renee-core/index.html +341 -0
  72. data/site/public/docs/renee-core/js/app.js +205 -0
  73. data/site/public/docs/renee-core/js/full_list.js +167 -0
  74. data/site/public/docs/renee-core/js/jquery.js +16 -0
  75. data/site/public/docs/renee-core/method_list.html +590 -0
  76. data/site/public/docs/renee-core/top-level-namespace.html +103 -0
  77. data/site/public/docs/renee-render/Renee.html +116 -0
  78. data/site/public/docs/renee-render/Renee/Core.html +346 -0
  79. data/site/public/docs/renee-render/Renee/Core/Chaining.html +125 -0
  80. data/site/public/docs/renee-render/Renee/Core/ClassMethods.html +620 -0
  81. data/site/public/docs/renee-render/Renee/Core/ClientError.html +317 -0
  82. data/site/public/docs/renee-render/Renee/Core/EnvAccessors.html +152 -0
  83. data/site/public/docs/renee-render/Renee/Core/EnvAccessors/ClassMethods.html +354 -0
  84. data/site/public/docs/renee-render/Renee/Core/Matcher.html +675 -0
  85. data/site/public/docs/renee-render/Renee/Core/RackInteraction.html +488 -0
  86. data/site/public/docs/renee-render/Renee/Core/RequestContext.html +421 -0
  87. data/site/public/docs/renee-render/Renee/Core/Responding.html +873 -0
  88. data/site/public/docs/renee-render/Renee/Core/Response.html +691 -0
  89. data/site/public/docs/renee-render/Renee/Core/Routing.html +1682 -0
  90. data/site/public/docs/renee-render/Renee/Core/Transform.html +249 -0
  91. data/site/public/docs/renee-render/Renee/Core/URLGeneration.html +597 -0
  92. data/site/public/docs/renee-render/Renee/Render.html +873 -0
  93. data/site/public/docs/renee-render/Renee/Render/ClassMethods.html +382 -0
  94. data/site/public/docs/renee-render/Renee/Render/TemplateNotFound.html +126 -0
  95. data/site/public/docs/renee-render/_index.html +143 -0
  96. data/site/public/docs/renee-render/class_list.html +47 -0
  97. data/site/public/docs/renee-render/css/common.css +1 -0
  98. data/site/public/docs/renee-render/css/full_list.css +55 -0
  99. data/site/public/docs/renee-render/css/style.css +322 -0
  100. data/site/public/docs/renee-render/file.README-renee-render.html +104 -0
  101. data/site/public/docs/renee-render/file.README.html +212 -0
  102. data/site/public/docs/renee-render/file_list.html +49 -0
  103. data/site/public/docs/renee-render/frames.html +13 -0
  104. data/site/public/docs/renee-render/index.html +104 -0
  105. data/site/public/docs/renee-render/js/app.js +205 -0
  106. data/site/public/docs/renee-render/js/full_list.js +167 -0
  107. data/site/public/docs/renee-render/js/jquery.js +16 -0
  108. data/site/public/docs/renee-render/method_list.html +110 -0
  109. data/site/public/docs/renee-render/top-level-namespace.html +103 -0
  110. data/site/public/docs/renee-session/Renee.html +106 -0
  111. data/site/public/docs/renee-session/Renee/Session.html +173 -0
  112. data/site/public/docs/renee-session/Renee/Session/ClassMethods.html +470 -0
  113. data/site/public/docs/renee-session/_index.html +136 -0
  114. data/site/public/docs/renee-session/class_list.html +47 -0
  115. data/site/public/docs/renee-session/css/common.css +1 -0
  116. data/site/public/docs/renee-session/css/full_list.css +55 -0
  117. data/site/public/docs/renee-session/css/style.css +322 -0
  118. data/site/public/docs/renee-session/file.README-renee-core.html +341 -0
  119. data/site/public/docs/renee-session/file.README-renee-session.html +69 -0
  120. data/site/public/docs/renee-session/file_list.html +49 -0
  121. data/site/public/docs/renee-session/frames.html +13 -0
  122. data/site/public/docs/renee-session/index.html +69 -0
  123. data/site/public/docs/renee-session/js/app.js +205 -0
  124. data/site/public/docs/renee-session/js/full_list.js +167 -0
  125. data/site/public/docs/renee-session/js/jquery.js +16 -0
  126. data/site/public/docs/renee-session/method_list.html +102 -0
  127. data/site/public/docs/renee-session/top-level-namespace.html +103 -0
  128. data/site/public/docs/renee-url-generation/Renee.html +208 -0
  129. data/site/public/docs/renee-url-generation/Renee/Core.html +366 -0
  130. data/site/public/docs/renee-url-generation/Renee/Core/Chaining.html +192 -0
  131. data/site/public/docs/renee-url-generation/Renee/Core/ClassMethods.html +725 -0
  132. data/site/public/docs/renee-url-generation/Renee/Core/ClientError.html +317 -0
  133. data/site/public/docs/renee-url-generation/Renee/Core/EnvAccessors.html +152 -0
  134. data/site/public/docs/renee-url-generation/Renee/Core/EnvAccessors/ClassMethods.html +354 -0
  135. data/site/public/docs/renee-url-generation/Renee/Core/Matcher.html +675 -0
  136. data/site/public/docs/renee-url-generation/Renee/Core/Plugins.html +475 -0
  137. data/site/public/docs/renee-url-generation/Renee/Core/RackInteraction.html +488 -0
  138. data/site/public/docs/renee-url-generation/Renee/Core/RequestContext.html +511 -0
  139. data/site/public/docs/renee-url-generation/Renee/Core/Responding.html +877 -0
  140. data/site/public/docs/renee-url-generation/Renee/Core/Response.html +691 -0
  141. data/site/public/docs/renee-url-generation/Renee/Core/Routing.html +1589 -0
  142. data/site/public/docs/renee-url-generation/Renee/Core/Transform.html +249 -0
  143. data/site/public/docs/renee-url-generation/_index.html +244 -0
  144. data/site/public/docs/renee-url-generation/class_list.html +47 -0
  145. data/site/public/docs/renee-url-generation/css/common.css +1 -0
  146. data/site/public/docs/renee-url-generation/css/full_list.css +55 -0
  147. data/site/public/docs/renee-url-generation/css/style.css +322 -0
  148. data/site/public/docs/renee-url-generation/file.README-renee-url-generation.html +69 -0
  149. data/site/public/docs/renee-url-generation/file_list.html +49 -0
  150. data/site/public/docs/renee-url-generation/frames.html +13 -0
  151. data/site/public/docs/renee-url-generation/index.html +69 -0
  152. data/site/public/docs/renee-url-generation/js/app.js +205 -0
  153. data/site/public/docs/renee-url-generation/js/full_list.js +167 -0
  154. data/site/public/docs/renee-url-generation/js/jquery.js +16 -0
  155. data/site/public/docs/renee-url-generation/method_list.html +590 -0
  156. data/site/public/docs/renee-url-generation/top-level-namespace.html +103 -0
  157. data/site/public/docs/renee/Renee.html +232 -0
  158. data/site/public/docs/renee/Renee/Application.html +367 -0
  159. data/site/public/docs/renee/Renee/Core.html +370 -0
  160. data/site/public/docs/renee/Renee/Core/Chaining.html +192 -0
  161. data/site/public/docs/renee/Renee/Core/ClassMethods.html +725 -0
  162. data/site/public/docs/renee/Renee/Core/ClientError.html +317 -0
  163. data/site/public/docs/renee/Renee/Core/EnvAccessors.html +152 -0
  164. data/site/public/docs/renee/Renee/Core/EnvAccessors/ClassMethods.html +354 -0
  165. data/site/public/docs/renee/Renee/Core/Matcher.html +675 -0
  166. data/site/public/docs/renee/Renee/Core/Plugins.html +475 -0
  167. data/site/public/docs/renee/Renee/Core/RackInteraction.html +488 -0
  168. data/site/public/docs/renee/Renee/Core/RequestContext.html +511 -0
  169. data/site/public/docs/renee/Renee/Core/Responding.html +877 -0
  170. data/site/public/docs/renee/Renee/Core/Response.html +691 -0
  171. data/site/public/docs/renee/Renee/Core/Routing.html +1589 -0
  172. data/site/public/docs/renee/Renee/Core/Transform.html +249 -0
  173. data/site/public/docs/renee/Renee/Core/URLGeneration.html +597 -0
  174. data/site/public/docs/renee/Renee/Render.html +877 -0
  175. data/site/public/docs/renee/Renee/Render/ClassMethods.html +382 -0
  176. data/site/public/docs/renee/Renee/Render/TemplateNotFound.html +126 -0
  177. data/site/public/docs/renee/Renee/Session.html +177 -0
  178. data/site/public/docs/renee/Renee/Session/ClassMethods.html +470 -0
  179. data/site/public/docs/renee/Renee/URLGeneration.html +142 -0
  180. data/site/public/docs/renee/Renee/URLGeneration/ClassMethods.html +593 -0
  181. data/site/public/docs/renee/Renee/Util.html +163 -0
  182. data/site/public/docs/renee/_index.html +336 -0
  183. data/site/public/docs/renee/class_list.html +47 -0
  184. data/site/public/docs/renee/css/common.css +1 -0
  185. data/site/public/docs/renee/css/full_list.css +55 -0
  186. data/site/public/docs/renee/css/style.css +322 -0
  187. data/site/public/docs/renee/file.README.html +212 -0
  188. data/site/public/docs/renee/file_list.html +49 -0
  189. data/site/public/docs/renee/frames.html +13 -0
  190. data/site/public/docs/renee/index.html +212 -0
  191. data/site/public/docs/renee/js/app.js +205 -0
  192. data/site/public/docs/renee/js/full_list.js +167 -0
  193. data/site/public/docs/renee/js/jquery.js +16 -0
  194. data/site/public/docs/renee/method_list.html +758 -0
  195. data/site/public/docs/renee/top-level-namespace.html +202 -0
  196. data/site/public/img/favicon.ico +0 -0
  197. data/site/public/img/reneeclean.png +0 -0
  198. data/site/public/img/russiangithub.png +0 -0
  199. data/site/public/img/stoneposter.png +0 -0
  200. data/site/public/img/vospit.jpeg +0 -0
  201. data/site/views/chaining.md +32 -0
  202. data/site/views/index.md +219 -0
  203. data/site/views/layouts/app.haml +16 -0
  204. data/site/views/rack-integration.md +51 -0
  205. data/site/views/responding.md +103 -0
  206. data/site/views/route-generation.md +82 -0
  207. data/site/views/routing.md +261 -0
  208. data/site/views/settings.md +19 -0
  209. data/site/views/team-renee.md +13 -0
  210. data/site/views/tutorial.md +57 -0
  211. data/site/views/variable-types.md +57 -0
  212. data/test.watchr +61 -0
  213. data/test/renee-core/chaining_test.rb +33 -0
  214. data/test/renee-core/env_accessors_test.rb +43 -0
  215. data/test/renee-core/include_test.rb +14 -0
  216. data/test/renee-core/request_context_test.rb +70 -0
  217. data/test/renee-core/responding_test.rb +128 -0
  218. data/test/renee-core/routing_test.rb +443 -0
  219. data/test/renee-core/test_helper.rb +4 -0
  220. data/test/renee-core/variable_type_test.rb +57 -0
  221. data/test/renee-render/render_test.rb +162 -0
  222. data/test/renee-render/test_helper.rb +9 -0
  223. data/test/renee-session/session_test.rb +31 -0
  224. data/test/renee-session/test_helper.rb +9 -0
  225. data/test/renee-url-generation/test_helper.rb +10 -0
  226. data/test/renee-url-generation/url_generation_test.rb +63 -0
  227. data/test/{blog_test.rb → renee/blog_test.rb} +10 -5
  228. data/test/renee/test_helper.rb +56 -0
  229. data/test/test_helper.rb +23 -10
  230. metadata +333 -156
  231. data/.yardopts +0 -6
@@ -0,0 +1,72 @@
1
+ module Renee
2
+ class Core
3
+ # Defines class-level methods for creating accessors for variables in your environment.
4
+ module EnvAccessors
5
+
6
+ # Exception for attempting to define an env accessor cannot be written as a method name.
7
+ # @example
8
+ # env_accessor "current.user" # raises InvalidEnvNameError
9
+ # env_accessor "current.user" => :current_user # this works
10
+ InvalidEnvNameError = Class.new(RuntimeError)
11
+
12
+ # Class-methods included by this module.
13
+ module ClassMethods
14
+
15
+ # Defines getters and setters for a list of attributes. If the attributes cannot easily be expressed, use the
16
+ # hash-syntax for defining them.
17
+ # @example
18
+ # env_accessor "some_value" # will define methods to read and write env['some_value']
19
+ # env_accessor "current.user" => :current_user will define methods to read and write env['current.user']
20
+ def env_accessor(*attrs)
21
+ env_reader(*attrs)
22
+ env_writer(*attrs)
23
+ end
24
+
25
+ # Defines getters for a list of attributes.
26
+ # @see env_accessor
27
+ def env_reader(*attrs)
28
+ instance_eval do
29
+ env_attr_iter(*attrs) do |key, meth|
30
+ define_method(meth) do
31
+ env[key]
32
+ end
33
+ end
34
+ end
35
+ end
36
+
37
+ # Defines setters for a list of attributes.
38
+ # @see env_accessor
39
+ def env_writer(*attrs)
40
+ instance_eval do
41
+ env_attr_iter(*attrs) do |key, meth|
42
+ define_method("#{meth}=") do |val|
43
+ env[key] = val
44
+ end
45
+ end
46
+ end
47
+ end
48
+
49
+ private
50
+ def env_attr_iter(*attrs)
51
+ attrs.each do |a|
52
+ case a
53
+ when Hash
54
+ a.each do |k, v|
55
+ yield k, v
56
+ end
57
+ else
58
+ raise InvalidEnvNameError, "Called env attr for #{a.inspect}, to use this, call your env method like this. env_reader #{a.inspect} => #{a.to_s.gsub(/-\./, '_').to_sym.inspect}" if a.to_s[/[-\.]/]
59
+ yield a, a.to_sym
60
+ end
61
+ end
62
+ end
63
+
64
+ end
65
+
66
+ # @private
67
+ def self.included(o)
68
+ o.extend(ClassMethods)
69
+ end
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,15 @@
1
+ module Renee
2
+ class Core
3
+ # Used to indicate a client-error has occurred (e.g. 4xx)
4
+ class ClientError < StandardError
5
+ attr_reader :response
6
+
7
+ # @param [String] message The message for this exception.
8
+ # @yield The optional block to instance-eval in the case this error is raised.
9
+ def initialize(message, &response)
10
+ super(message)
11
+ @response = response
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,61 @@
1
+ module Renee
2
+ class Core
3
+ # Class used for variable matching.
4
+ class Matcher
5
+ attr_accessor :name
6
+
7
+ # @param [Regexp] matcher The regexp matcher to determine what is part of the variable.
8
+ def initialize(matcher)
9
+ @matcher = matcher
10
+ end
11
+
12
+ # Used to specific the error handler if the matcher doesn't match anything. By default, there is no error handler.
13
+ # @yield The block to be executed it fails to match.
14
+ def on_error(&blk)
15
+ @error_handler = blk
16
+ self
17
+ end
18
+
19
+ # Used to transform the value matched.
20
+ # @yield TODO
21
+ def on_transform(&blk)
22
+ @transform_handler = blk
23
+ self
24
+ end
25
+
26
+ # Convienence method to creating halting error handler.
27
+ # @param [Symbol, Integer] error_code The HTTP code to halt with.
28
+ # @see #interpret_response
29
+ def raise_on_error!(error_code = :bad_request)
30
+ on_error { halt error_code }
31
+ self
32
+ end
33
+
34
+ # Matcher for string
35
+ # @param [String] val The value to attempt to match on.
36
+ # @raise [ClientError] If the match fails to match and there is an error handler defined.
37
+ def [](val)
38
+ match = nil
39
+ case @matcher
40
+ when Array
41
+ match = nil
42
+ @matcher.find { |m| match = m[val] }
43
+ else
44
+ if match = /^#{@matcher.to_s}/.match(val)
45
+ match = [match[0]]
46
+ match << @transform_handler.call(match.first) if @transform_handler
47
+ match
48
+ end
49
+ end
50
+ if match
51
+ match
52
+ elsif @error_handler
53
+ raise ClientError.new("There was an error interpreting the value #{val.inspect} for #{name.inspect}", &@error_handler)
54
+ end
55
+ end
56
+ end
57
+
58
+ # Matcher for Integers
59
+ IntegerMatcher = Matcher.new(/\d+/).on_transform{|v| Integer(v)}
60
+ end
61
+ end
@@ -0,0 +1,31 @@
1
+ module Renee
2
+ class Core
3
+ module Plugins
4
+ attr_reader :init_blocks, :before_blocks, :after_blocks
5
+
6
+ def on_init(&blk)
7
+ init_blocks << blk
8
+ end
9
+
10
+ def init_blocks
11
+ (@init_blocks ||= [])
12
+ end
13
+
14
+ def on_before(&blk)
15
+ before_blocks << blk
16
+ end
17
+
18
+ def before_blocks
19
+ (@before_blocks ||= [])
20
+ end
21
+
22
+ def on_after(&blk)
23
+ before_blocks << blk
24
+ end
25
+
26
+ def after_blocks
27
+ (@after_blocks ||= [])
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,50 @@
1
+ module Renee
2
+ class Core
3
+ # A module that defines useful Rack interaction methods.
4
+ module RackInteraction
5
+ # Creates an ad-hoc Rack application within the context of a Rack::Builder.
6
+ # @yield The block to be used to instantiate the `Rack::Builder`.
7
+ #
8
+ # @example
9
+ # get { halt build { use Rack::ContentLength; run proc { |env| Rack::Response.new("Hello!").finish } } }
10
+ #
11
+ def build(&blk)
12
+ run Rack::Builder.new(&blk).to_app
13
+ end
14
+
15
+ # Creates an ad-hoc Rack application within the context of a Rack::Builder that immediately halts when done.
16
+ # @param (see #build)
17
+ #
18
+ # @example
19
+ # get { halt build { use Rack::ContentLength; run proc { |env| Rack::Response.new("Hello!").finish } } }
20
+ #
21
+ def build!(&blk)
22
+ halt build(&blk)
23
+ end
24
+
25
+ # Runs a rack application. You must either use `app` or `blk`.
26
+ # @param [#call] app The application to call.
27
+ # @yield [env] The block to yield to
28
+ #
29
+ #
30
+ # @example
31
+ # get { halt run proc { |env| Renee::Core::Response.new("Hello!").finish } }
32
+ #
33
+ def run(app = nil, &blk)
34
+ raise "You cannot supply both a block and an app" unless app.nil? ^ blk.nil?
35
+ (app || blk).call(env)
36
+ end
37
+
38
+ # Runs a rack application and halts immediately.
39
+ # @param (see #run)
40
+ #
41
+ # @see #run!
42
+ # @example
43
+ # get { run proc { |env| Renee::Core::Response.new("Hello!").finish } }
44
+ #
45
+ def run!(app = nil, &blk)
46
+ halt run(app, &blk)
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,56 @@
1
+ module Renee
2
+ class Core
3
+ module ClassMethods
4
+ def use(mw, *args, &blk)
5
+ middlewares << [mw, args, blk]
6
+ end
7
+
8
+ def middlewares
9
+ @middlewares ||= []
10
+ end
11
+ end
12
+
13
+ # This module deals with the Rack#call compilance. It defines #call and also defines several critical methods
14
+ # used by interaction by other application modules.
15
+ module RequestContext
16
+ attr_reader :env, :request, :detected_extension
17
+
18
+ # Provides a rack interface compliant call method.
19
+ # @param[Hash] env The rack environment.
20
+ def call(e)
21
+ initialize_plugins
22
+ idx = 0
23
+ next_app = proc do |env|
24
+ if idx == self.class.middlewares.size
25
+ @env, @request = env, Rack::Request.new(env)
26
+ @detected_extension = env['PATH_INFO'][/\.([^\.\/]+)$/, 1]
27
+ # TODO clear template cache in development? `template_cache.clear`
28
+ out = catch(:halt) do
29
+ begin
30
+ self.class.before_blocks.each { |b| instance_eval(&b) }
31
+ instance_eval(&self.class.application_block)
32
+ rescue ClientError => e
33
+ e.response ? instance_eval(&e.response) : halt("There was an error with your request", 400)
34
+ rescue NotMatchedError => e
35
+ # unmatched, continue on
36
+ end
37
+ Renee::Core::Response.new("Not found", 404).finish
38
+ end
39
+ self.class.after_blocks.each { |a| out = instance_exec(out, &a) }
40
+ out
41
+ else
42
+ middleware = self.class.middlewares[idx]
43
+ idx += 1
44
+ middleware[0].new(next_app, *middleware[1], &middleware[2]).call(env)
45
+ end
46
+ end
47
+ next_app[e]
48
+ end # call
49
+
50
+ def initialize_plugins
51
+ self.class.init_blocks.each { |init_block| self.class.class_eval(&init_block) }
52
+ self.class.send(:define_method, :initialize_plugins) { }
53
+ end
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,112 @@
1
+ module Renee
2
+ class Core
3
+ # Collection of useful methods for responding within a {Renee::Core} app.
4
+ module Responding
5
+ # Codes used by Symbol lookup in interpret_response.
6
+ # @example
7
+ # halt :unauthorized # would return a 401.
8
+ #
9
+ HTTP_CODES = {
10
+ :ok => 200,
11
+ :created => 201,
12
+ :accepted => 202,
13
+ :no_content => 204,
14
+ :no_content => 204,
15
+ :bad_request => 400,
16
+ :unauthorized => 401,
17
+ :payment_required => 403,
18
+ :not_found => 404,
19
+ :method_not_found => 405,
20
+ :not_acceptable => 406,
21
+ :gone => 410,
22
+ :error => 500,
23
+ :not_implemented => 501}.freeze
24
+
25
+ # Halts current processing to the top-level calling Renee application and uses that as a response.
26
+ # @param [Object...] response The response to use.
27
+ # @see #interpret_response
28
+ def halt(*response)
29
+ throw :halt, interpret_response(response.size == 1 ? response.first : response)
30
+ end
31
+
32
+ ##
33
+ # Creates a response by allowing the response header, body and status to be passed into the block.
34
+ #
35
+ # @param [Array] body The contents to return.
36
+ # @param [Integer] status The status code to return.
37
+ # @param [Hash] header The headers to return.
38
+ # @param [Proc] &blk The response options to specify
39
+ #
40
+ # @example
41
+ # respond { status 200; body "Yay!" }
42
+ # respond("Hello", 200, "foo" => "bar")
43
+ #
44
+ def respond(body=[], status=200, header={}, &blk)
45
+ response = Renee::Core::Response.new(body, status, header)
46
+ response.instance_eval(&blk) if block_given?
47
+ response.finish
48
+ end
49
+
50
+ ##
51
+ # Creates a response by allowing the response header, body and status to be passed into the block.
52
+ #
53
+ # @example
54
+ # respond! { status 200; body "Yay!" }
55
+ #
56
+ # @param (see #respond)
57
+ # @see #respond
58
+ def respond!(*args, &blk)
59
+ halt respond(*args, &blk)
60
+ end
61
+
62
+ # Interprets responses returns by #halt.
63
+ #
64
+ # * If it is a Symbol, it will be looked up in {HTTP_CODES}.
65
+ # * If it is a Symbol, it will use Rack::Response to return the value.
66
+ # * If it is a Symbol, it will either be used as a Rack response or as a body and status code.
67
+ # * If it is an Integer, it will use Rack::Response to return the status code.
68
+ # * Otherwise, #to_s will be called on it and it will be treated as a Symbol.
69
+ #
70
+ # @param [Object] response This can be either a Symbol, String, Array or any Object.
71
+ #
72
+ def interpret_response(response)
73
+ case response
74
+ when Array then
75
+ case response.size
76
+ when 3 then response
77
+ when 2 then Renee::Core::Response.new(response[1], HTTP_CODES[response[0]] || response[0]).finish
78
+ else raise "I don't know how to render #{response.inspect}"
79
+ end
80
+ when String then Renee::Core::Response.new(response).finish
81
+ when Integer then Renee::Core::Response.new("Status code #{response}", response).finish
82
+ when Symbol then interpret_response(HTTP_CODES[response] || response.to_s)
83
+ when Proc then instance_eval(&response)
84
+ else response # pass through response
85
+ end
86
+ end
87
+
88
+ # Returns a rack-based response for redirection.
89
+ # @param [String] path The URL to redirect to.
90
+ # @param [Integer] code The HTTP code to use.
91
+ # @example
92
+ # r = Renee.core { get { halt redirect '/index' } }
93
+ # r.call(Rack::MockResponse("/")) # => [302, {"Location" => "/index"}, []]
94
+ def redirect(path, code = 302)
95
+ response = ::Rack::Response.new
96
+ response.redirect(path, code)
97
+ response.finish
98
+ end
99
+
100
+ # Halts with a rack-based response for redirection.
101
+ # @see #redirect
102
+ # @param [String] path The URL to redirect to.
103
+ # @param [Integer] code The HTTP code to use.
104
+ # @example
105
+ # r = Renee.core { get { redirect! '/index' } }
106
+ # r.call(Rack::MockResponse("/")) # => [302, {"Location" => "/index"}, []]
107
+ def redirect!(path, code = 302)
108
+ halt redirect(path, code)
109
+ end
110
+ end
111
+ end
112
+ end
@@ -0,0 +1,78 @@
1
+ module Renee
2
+ class Core
3
+ # The response object for a Renee request. Inherits from the `Rack#Response` object.
4
+ class Response < Rack::Response
5
+ # Augment body to allow strings.
6
+ #
7
+ # @param [String] The contents for the response.
8
+ #
9
+ # @example
10
+ # res.body = "Hello"
11
+ #
12
+ # @api semipublic
13
+ def body=(value)
14
+ value = value.body while Rack::Response === value
15
+ @body = String === value ? [value.to_str] : value
16
+ end
17
+
18
+ # Alias status and body methods to allow redefinition
19
+ alias :status_attr :status
20
+ alias :status_attr= :status=
21
+ alias :body_attr :body
22
+ alias :body_attr= :body=
23
+
24
+ # Get or set the status of the response.
25
+ #
26
+ # @param [String] val The status code to return.
27
+ #
28
+ # @example
29
+ # res.status 400
30
+ # res.status => 400
31
+ #
32
+ # @api public
33
+ def status(val=nil)
34
+ val ? self.status_attr = val : self.status_attr
35
+ end
36
+
37
+ # Get or set the body of the response.
38
+ #
39
+ # @param [String] val The contents to return.
40
+ #
41
+ # @example
42
+ # res.body "hello"
43
+ # res.body => "hello"
44
+ #
45
+ # @api public
46
+ def body(val=nil)
47
+ val ? self.body_attr = val : self.body_attr
48
+ end
49
+
50
+ # Get or set the headers of the response.
51
+ #
52
+ # @param [Hash] attrs The contents to return.
53
+ #
54
+ # @example
55
+ # res.headers :foo => "bar"
56
+ # res.headers => { :foo => "bar" }
57
+ #
58
+ # @api public
59
+ def headers(attrs={})
60
+ attrs ? attrs.each { |k, v| self[k.to_s] = v } : self.header
61
+ end
62
+
63
+ # Finishs the response based on the accumulated options.
64
+ # Calculates the size of the body content length and removes headers for 1xx status codes.
65
+ def finish
66
+ if status.to_i / 100 == 1
67
+ headers.delete "Content-Length"
68
+ headers.delete "Content-Type"
69
+ elsif Array === body and not [204, 304].include?(status.to_i)
70
+ headers["Content-Length"] = body.inject(0) { |l, p| l + Rack::Utils.bytesize(p) }.to_s
71
+ end
72
+
73
+ status, headers, result = super
74
+ [status, headers, result]
75
+ end
76
+ end
77
+ end
78
+ end