renee 0.3.11 → 0.4.0.pre1

Sign up to get free protection for your applications and to get access to all the features.
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