utopia 2.15.1 → 2.16.0

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 (257) hide show
  1. checksums.yaml +4 -4
  2. data/bake/utopia/{yarn.rb → node.rb} +7 -7
  3. data/lib/utopia/command.rb +2 -2
  4. data/lib/utopia/content/markup.rb +1 -1
  5. data/lib/utopia/content/node.rb +2 -2
  6. data/lib/utopia/content/response.rb +3 -3
  7. data/lib/utopia/controller.rb +0 -17
  8. data/lib/utopia/controller/base.rb +23 -3
  9. data/lib/utopia/controller/respond.rb +50 -107
  10. data/lib/utopia/extensions/array_split.rb +2 -2
  11. data/lib/utopia/http.rb +3 -3
  12. data/lib/utopia/middleware.rb +2 -2
  13. data/lib/utopia/path.rb +4 -4
  14. data/lib/utopia/redirection.rb +0 -2
  15. data/lib/utopia/responder.rb +76 -0
  16. data/lib/utopia/version.rb +1 -1
  17. metadata +71 -395
  18. data/.codeclimate.yml +0 -5
  19. data/.github/workflows/development.yml +0 -62
  20. data/.gitignore +0 -8
  21. data/.rspec +0 -4
  22. data/.yardopts +0 -2
  23. data/Gemfile +0 -28
  24. data/README.md +0 -90
  25. data/benchmark/call_vs_check.rb +0 -38
  26. data/benchmark/const_vs_hash.rb +0 -35
  27. data/benchmark/hash_vs_openstruct.rb +0 -54
  28. data/benchmark/string_vs_symbol.rb +0 -14
  29. data/benchmark/struct_vs_class.rb +0 -91
  30. data/docs/.nojekyll +0 -0
  31. data/docs/_components/jquery-litebox/jquery.litebox.css +0 -23
  32. data/docs/_components/jquery-litebox/jquery.litebox.gallery.css +0 -48
  33. data/docs/_components/jquery-litebox/jquery.litebox.js +0 -30
  34. data/docs/_components/jquery-syntax/base/jquery.syntax.brush.apache.css +0 -12
  35. data/docs/_components/jquery-syntax/base/jquery.syntax.brush.applescript.css +0 -5
  36. data/docs/_components/jquery-syntax/base/jquery.syntax.brush.assembly.css +0 -8
  37. data/docs/_components/jquery-syntax/base/jquery.syntax.brush.bash-script.css +0 -6
  38. data/docs/_components/jquery-syntax/base/jquery.syntax.brush.bash.css +0 -4
  39. data/docs/_components/jquery-syntax/base/jquery.syntax.brush.clang.css +0 -6
  40. data/docs/_components/jquery-syntax/base/jquery.syntax.brush.css.css +0 -14
  41. data/docs/_components/jquery-syntax/base/jquery.syntax.brush.diff.css +0 -16
  42. data/docs/_components/jquery-syntax/base/jquery.syntax.brush.html.css +0 -5
  43. data/docs/_components/jquery-syntax/base/jquery.syntax.brush.ocaml.css +0 -3
  44. data/docs/_components/jquery-syntax/base/jquery.syntax.brush.protobuf.css +0 -2
  45. data/docs/_components/jquery-syntax/base/jquery.syntax.brush.python.css +0 -6
  46. data/docs/_components/jquery-syntax/base/jquery.syntax.brush.ruby.css +0 -2
  47. data/docs/_components/jquery-syntax/base/jquery.syntax.brush.xml.css +0 -18
  48. data/docs/_components/jquery-syntax/base/jquery.syntax.core.css +0 -58
  49. data/docs/_components/jquery-syntax/base/jquery.syntax.editor.css +0 -6
  50. data/docs/_components/jquery-syntax/base/theme.js +0 -1
  51. data/docs/_components/jquery-syntax/bright/jquery.syntax.core.css +0 -27
  52. data/docs/_components/jquery-syntax/bright/theme.js +0 -1
  53. data/docs/_components/jquery-syntax/jquery.syntax.brush.apache.js +0 -3
  54. data/docs/_components/jquery-syntax/jquery.syntax.brush.applescript.js +0 -5
  55. data/docs/_components/jquery-syntax/jquery.syntax.brush.assembly.js +0 -3
  56. data/docs/_components/jquery-syntax/jquery.syntax.brush.bash-script.js +0 -4
  57. data/docs/_components/jquery-syntax/jquery.syntax.brush.bash.js +0 -2
  58. data/docs/_components/jquery-syntax/jquery.syntax.brush.basic.js +0 -5
  59. data/docs/_components/jquery-syntax/jquery.syntax.brush.clang.js +0 -5
  60. data/docs/_components/jquery-syntax/jquery.syntax.brush.csharp.js +0 -4
  61. data/docs/_components/jquery-syntax/jquery.syntax.brush.css.js +0 -5
  62. data/docs/_components/jquery-syntax/jquery.syntax.brush.diff.js +0 -2
  63. data/docs/_components/jquery-syntax/jquery.syntax.brush.go.js +0 -3
  64. data/docs/_components/jquery-syntax/jquery.syntax.brush.haskell.js +0 -3
  65. data/docs/_components/jquery-syntax/jquery.syntax.brush.html.js +0 -4
  66. data/docs/_components/jquery-syntax/jquery.syntax.brush.io.js +0 -3
  67. data/docs/_components/jquery-syntax/jquery.syntax.brush.java.js +0 -4
  68. data/docs/_components/jquery-syntax/jquery.syntax.brush.javascript.js +0 -3
  69. data/docs/_components/jquery-syntax/jquery.syntax.brush.kai.js +0 -2
  70. data/docs/_components/jquery-syntax/jquery.syntax.brush.lisp.js +0 -2
  71. data/docs/_components/jquery-syntax/jquery.syntax.brush.lua.js +0 -3
  72. data/docs/_components/jquery-syntax/jquery.syntax.brush.nginx.js +0 -2
  73. data/docs/_components/jquery-syntax/jquery.syntax.brush.ocaml.js +0 -4
  74. data/docs/_components/jquery-syntax/jquery.syntax.brush.ooc.js +0 -4
  75. data/docs/_components/jquery-syntax/jquery.syntax.brush.pascal.js +0 -4
  76. data/docs/_components/jquery-syntax/jquery.syntax.brush.perl5.js +0 -3
  77. data/docs/_components/jquery-syntax/jquery.syntax.brush.php-script.js +0 -4
  78. data/docs/_components/jquery-syntax/jquery.syntax.brush.php.js +0 -2
  79. data/docs/_components/jquery-syntax/jquery.syntax.brush.plain.js +0 -2
  80. data/docs/_components/jquery-syntax/jquery.syntax.brush.protobuf.js +0 -3
  81. data/docs/_components/jquery-syntax/jquery.syntax.brush.python.js +0 -5
  82. data/docs/_components/jquery-syntax/jquery.syntax.brush.ruby.js +0 -5
  83. data/docs/_components/jquery-syntax/jquery.syntax.brush.scala.js +0 -4
  84. data/docs/_components/jquery-syntax/jquery.syntax.brush.smalltalk.js +0 -2
  85. data/docs/_components/jquery-syntax/jquery.syntax.brush.sql.js +0 -4
  86. data/docs/_components/jquery-syntax/jquery.syntax.brush.super-collider.js +0 -3
  87. data/docs/_components/jquery-syntax/jquery.syntax.brush.swift.js +0 -3
  88. data/docs/_components/jquery-syntax/jquery.syntax.brush.trenni.js +0 -2
  89. data/docs/_components/jquery-syntax/jquery.syntax.brush.xml.js +0 -4
  90. data/docs/_components/jquery-syntax/jquery.syntax.brush.yaml.js +0 -2
  91. data/docs/_components/jquery-syntax/jquery.syntax.cache.js +0 -7
  92. data/docs/_components/jquery-syntax/jquery.syntax.core.js +0 -34
  93. data/docs/_components/jquery-syntax/jquery.syntax.editor.js +0 -11
  94. data/docs/_components/jquery-syntax/jquery.syntax.js +0 -8
  95. data/docs/_components/jquery-syntax/jquery.syntax.min.js +0 -13
  96. data/docs/_components/jquery-syntax/paper/jquery.syntax.core.css +0 -31
  97. data/docs/_components/jquery-syntax/paper/theme.js +0 -1
  98. data/docs/_components/jquery/jquery.js +0 -10872
  99. data/docs/_components/jquery/jquery.min.js +0 -2
  100. data/docs/_components/jquery/jquery.min.map +0 -1
  101. data/docs/_components/jquery/jquery.slim.js +0 -8777
  102. data/docs/_components/jquery/jquery.slim.min.js +0 -2
  103. data/docs/_components/jquery/jquery.slim.min.map +0 -1
  104. data/docs/_static/icon.png +0 -0
  105. data/docs/_static/site.css +0 -191
  106. data/docs/development-environment-setup/index.html +0 -54
  107. data/docs/faq/what-is-xnode/index.html +0 -73
  108. data/docs/index.html +0 -86
  109. data/docs/javascript/index.html +0 -108
  110. data/docs/middleware/content/index.html +0 -58
  111. data/docs/middleware/controller/actions/index.html +0 -111
  112. data/docs/middleware/controller/index.html +0 -98
  113. data/docs/middleware/controller/rewrite/index.html +0 -105
  114. data/docs/middleware/localization/index.html +0 -53
  115. data/docs/middleware/redirection/index.html +0 -55
  116. data/docs/middleware/session/index.html +0 -65
  117. data/docs/middleware/static/index.html +0 -51
  118. data/docs/server-setup/index.html +0 -87
  119. data/docs/testing/index.html +0 -53
  120. data/docs/updating-utopia/index.html +0 -102
  121. data/docs/your-first-page/index.html +0 -74
  122. data/materials/utopia.png +0 -0
  123. data/materials/utopia.svg +0 -1
  124. data/spec/mock_node.rb +0 -16
  125. data/spec/spec_helper.rb +0 -13
  126. data/spec/utopia/command_spec.rb +0 -164
  127. data/spec/utopia/content/document_spec.rb +0 -60
  128. data/spec/utopia/content/links/bar/index.xnode +0 -0
  129. data/spec/utopia/content/links/bar/parent/child/index.en.xnode +0 -0
  130. data/spec/utopia/content/links/bar/parent/child/index.ja.xnode +0 -0
  131. data/spec/utopia/content/links/bar/parent/links.yaml +0 -2
  132. data/spec/utopia/content/links/foo/index.xnode +0 -0
  133. data/spec/utopia/content/links/foo/links.yaml +0 -2
  134. data/spec/utopia/content/links/foo/test.de.xnode +0 -0
  135. data/spec/utopia/content/links/foo/test.en.xnode +0 -0
  136. data/spec/utopia/content/links/index.xnode +0 -0
  137. data/spec/utopia/content/links/links.yaml +0 -18
  138. data/spec/utopia/content/links/redirect/links.yaml +0 -2
  139. data/spec/utopia/content/links/welcome.xnode +0 -0
  140. data/spec/utopia/content/links_spec.rb +0 -218
  141. data/spec/utopia/content/localized/five/index.en.xnode +0 -0
  142. data/spec/utopia/content/localized/four/index.en.xnode +0 -0
  143. data/spec/utopia/content/localized/four/index.zh.xnode +0 -0
  144. data/spec/utopia/content/localized/four/links.yaml +0 -4
  145. data/spec/utopia/content/localized/links.yaml +0 -13
  146. data/spec/utopia/content/localized/one.xnode +0 -0
  147. data/spec/utopia/content/localized/three/index.xnode +0 -0
  148. data/spec/utopia/content/localized/two.en.xnode +0 -0
  149. data/spec/utopia/content/localized/two.zh.xnode +0 -0
  150. data/spec/utopia/content/markup_spec.rb +0 -96
  151. data/spec/utopia/content/namespace_spec.rb +0 -45
  152. data/spec/utopia/content/node/lookup/content.xnode +0 -1
  153. data/spec/utopia/content/node/lookup/index.xnode +0 -1
  154. data/spec/utopia/content/node/ordered/first.xnode +0 -0
  155. data/spec/utopia/content/node/ordered/index.xnode +0 -0
  156. data/spec/utopia/content/node/ordered/links.yaml +0 -4
  157. data/spec/utopia/content/node/ordered/second.xnode +0 -0
  158. data/spec/utopia/content/node/related/foo.en.xnode +0 -0
  159. data/spec/utopia/content/node/related/foo.ja.xnode +0 -0
  160. data/spec/utopia/content/node/related/links.yaml +0 -4
  161. data/spec/utopia/content/node_spec.rb +0 -97
  162. data/spec/utopia/content/response_spec.rb +0 -54
  163. data/spec/utopia/content/tags_spec.rb +0 -82
  164. data/spec/utopia/content_spec.rb +0 -100
  165. data/spec/utopia/content_spec.ru +0 -6
  166. data/spec/utopia/content_spec/_heading.xnode +0 -1
  167. data/spec/utopia/content_spec/content/_show-value.xnode +0 -1
  168. data/spec/utopia/content_spec/content/links.yaml +0 -2
  169. data/spec/utopia/content_spec/content/test-partial.xnode +0 -1
  170. data/spec/utopia/content_spec/index.xnode +0 -1
  171. data/spec/utopia/content_spec/node/index.xnode +0 -1
  172. data/spec/utopia/content_spec/test.xnode +0 -10
  173. data/spec/utopia/controller/actions_spec.rb +0 -62
  174. data/spec/utopia/controller/middleware_spec.rb +0 -88
  175. data/spec/utopia/controller/middleware_spec.ru +0 -6
  176. data/spec/utopia/controller/middleware_spec/controller/controller.rb +0 -27
  177. data/spec/utopia/controller/middleware_spec/controller/index.xnode +0 -1
  178. data/spec/utopia/controller/middleware_spec/controller/nested/controller.rb +0 -7
  179. data/spec/utopia/controller/middleware_spec/empty/controller.rb +0 -0
  180. data/spec/utopia/controller/middleware_spec/redirect/controller.rb +0 -12
  181. data/spec/utopia/controller/middleware_spec/redirect/test/controller.rb +0 -9
  182. data/spec/utopia/controller/respond_spec.rb +0 -174
  183. data/spec/utopia/controller/respond_spec.ru +0 -12
  184. data/spec/utopia/controller/respond_spec/api/controller.rb +0 -28
  185. data/spec/utopia/controller/respond_spec/errors/controller.rb +0 -14
  186. data/spec/utopia/controller/respond_spec/errors/file-not-found.xnode +0 -8
  187. data/spec/utopia/controller/respond_spec/html/controller.rb +0 -11
  188. data/spec/utopia/controller/respond_spec/rewrite/controller.rb +0 -13
  189. data/spec/utopia/controller/rewrite_spec.rb +0 -80
  190. data/spec/utopia/controller/sequence_spec.rb +0 -135
  191. data/spec/utopia/controller/variables_spec.rb +0 -59
  192. data/spec/utopia/controller/websocket_spec.rb +0 -68
  193. data/spec/utopia/controller/websocket_spec.ru +0 -5
  194. data/spec/utopia/controller/websocket_spec/server/controller.rb +0 -11
  195. data/spec/utopia/exceptions/handler_spec.rb +0 -47
  196. data/spec/utopia/exceptions/handler_spec.ru +0 -8
  197. data/spec/utopia/exceptions/handler_spec/controller.rb +0 -19
  198. data/spec/utopia/exceptions/mailer_spec.rb +0 -43
  199. data/spec/utopia/exceptions/mailer_spec.ru +0 -10
  200. data/spec/utopia/extensions_spec.rb +0 -73
  201. data/spec/utopia/http/status_spec.rb +0 -44
  202. data/spec/utopia/locale_spec.rb +0 -58
  203. data/spec/utopia/localization_spec.rb +0 -92
  204. data/spec/utopia/localization_spec.ru +0 -15
  205. data/spec/utopia/localization_spec/controller.rb +0 -21
  206. data/spec/utopia/localization_spec/localized.de.txt +0 -1
  207. data/spec/utopia/localization_spec/localized.en.txt +0 -1
  208. data/spec/utopia/localization_spec/localized.ja.txt +0 -1
  209. data/spec/utopia/localization_spec/test.txt +0 -1
  210. data/spec/utopia/middleware_spec.rb +0 -31
  211. data/spec/utopia/path/matcher_spec.rb +0 -66
  212. data/spec/utopia/path_spec.rb +0 -207
  213. data/spec/utopia/performance_spec.rb +0 -92
  214. data/spec/utopia/performance_spec/cache/head/readme.txt +0 -1
  215. data/spec/utopia/performance_spec/cache/meta/readme.txt +0 -1
  216. data/spec/utopia/performance_spec/config.ru +0 -35
  217. data/spec/utopia/performance_spec/lib/readme.txt +0 -1
  218. data/spec/utopia/performance_spec/pages/_heading.xnode +0 -2
  219. data/spec/utopia/performance_spec/pages/_page.xnode +0 -26
  220. data/spec/utopia/performance_spec/pages/api/controller.rb +0 -8
  221. data/spec/utopia/performance_spec/pages/errors/exception.xnode +0 -5
  222. data/spec/utopia/performance_spec/pages/errors/file-not-found.xnode +0 -5
  223. data/spec/utopia/performance_spec/pages/links.yaml +0 -2
  224. data/spec/utopia/performance_spec/pages/welcome/index.xnode +0 -17
  225. data/spec/utopia/rack_helper.rb +0 -32
  226. data/spec/utopia/redirection_spec.rb +0 -77
  227. data/spec/utopia/redirection_spec.ru +0 -27
  228. data/spec/utopia/session_spec.rb +0 -189
  229. data/spec/utopia/session_spec.ru +0 -24
  230. data/spec/utopia/setup_spec.rb +0 -56
  231. data/spec/utopia/static_spec.rb +0 -49
  232. data/spec/utopia/static_spec.ru +0 -5
  233. data/spec/utopia/static_spec/test.txt +0 -1
  234. data/utopia.gemspec +0 -52
  235. data/wiki/Gemfile +0 -9
  236. data/wiki/config.ru +0 -7
  237. data/wiki/pages/development-environment-setup/index.md +0 -16
  238. data/wiki/pages/faq/links.yaml +0 -2
  239. data/wiki/pages/faq/what-is-xnode/index.md +0 -37
  240. data/wiki/pages/faq/what-is-xnode/links.yaml +0 -2
  241. data/wiki/pages/index.md +0 -35
  242. data/wiki/pages/javascript/index.md +0 -75
  243. data/wiki/pages/javascript/links.yaml +0 -2
  244. data/wiki/pages/links.yaml +0 -2
  245. data/wiki/pages/middleware/content/index.md +0 -21
  246. data/wiki/pages/middleware/controller/actions/index.md +0 -76
  247. data/wiki/pages/middleware/controller/index.md +0 -62
  248. data/wiki/pages/middleware/controller/links.yaml +0 -4
  249. data/wiki/pages/middleware/controller/rewrite/index.md +0 -69
  250. data/wiki/pages/middleware/localization/index.md +0 -16
  251. data/wiki/pages/middleware/redirection/index.md +0 -17
  252. data/wiki/pages/middleware/session/index.md +0 -29
  253. data/wiki/pages/middleware/static/index.md +0 -13
  254. data/wiki/pages/server-setup/index.md +0 -52
  255. data/wiki/pages/testing/index.md +0 -15
  256. data/wiki/pages/updating-utopia/index.md +0 -63
  257. data/wiki/pages/your-first-page/index.md +0 -38
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 642fe3cebd7ad176c3799e0f7f00c94578dcef9b5085e76db697d435983046f4
4
- data.tar.gz: 13e6d529f447a8eacf7a71b703bb9f1fa116f02a23b31d701a20697086213182
3
+ metadata.gz: ddb5cc8a1bb593d344e0d2f2c8bf315704f297ae1e8063b4d7c0e5f3d71f4014
4
+ data.tar.gz: '09ff4febe6dd06945a3725e0c1354402e23bf837026c5aa09b6c2106b482e00d'
5
5
  SHA512:
6
- metadata.gz: c0d1c8c6c1229282f5755b3359f8ec595edd3ac2f76c043e2e8a5db5821813a3d9f86eaf1f58767140d7c62af696369495802fef291877104d762580bb2bd9d6
7
- data.tar.gz: 0d9652569e0c9194e25d89d85e6b7caa97bc0a219d738dd489d666fc260a27ffb0475b1a62a96ba7b3b2c6f41c76c53819c44688150e0a2f75d40c1219671784
6
+ metadata.gz: 6a5a89b6bf438d72007dd8617085125aae4a038ee8267716361810e149f9488166323c299aea04baf69ebd54e630e20093c32ec8e016553b11ad46bfa54fe22c
7
+ data.tar.gz: bf6fcfe77a7423b39fabd019b40309c52db7a15284661243119d32c279d32d51d2467e4bff409cf6d53924baca9cc60d7788b00bbaf4f9986b65e2b0522e5dbd
@@ -6,18 +6,18 @@ def update
6
6
  require 'utopia/path'
7
7
 
8
8
  root = Pathname.new(context.root)
9
- yarn_package_root = root + "node_modules"
9
+ package_root = root + "node_modules"
10
10
 
11
11
  # This is a legacy path:
12
- unless yarn_package_root.directory?
13
- yarn_package_root = root + "lib/components"
12
+ unless package_root.directory?
13
+ package_root = root + "lib/components"
14
14
  end
15
15
 
16
- yarn_install_root = root + "public/_components"
16
+ install_root = root + "public/_components"
17
17
 
18
- yarn_package_root.children.select(&:directory?).collect(&:basename).each do |package_directory|
19
- install_path = yarn_install_root + package_directory
20
- package_path = yarn_package_root + package_directory
18
+ package_root.children.select(&:directory?).collect(&:basename).each do |package_directory|
19
+ install_path = install_root + package_directory
20
+ package_path = package_root + package_directory
21
21
 
22
22
  dist_path = package_path + 'dist'
23
23
 
@@ -28,8 +28,8 @@ require_relative 'command/environment'
28
28
 
29
29
  module Utopia
30
30
  module Command
31
- def self.call(*args)
32
- Top.call(*args)
31
+ def self.call(*arguments)
32
+ Top.call(*arguments)
33
33
  end
34
34
 
35
35
  # The top level utopia command.
@@ -40,7 +40,7 @@ module Utopia
40
40
  super key.to_sym, value
41
41
  end
42
42
 
43
- def fetch(key, *args, &block)
43
+ def fetch(key, *arguments, &block)
44
44
  key = key.to_sym
45
45
 
46
46
  super
@@ -128,12 +128,12 @@ module Utopia
128
128
 
129
129
  # This is a special context in which a limited set of well defined methods are exposed in the content view.
130
130
  Context = Struct.new(:document, :state) do
131
- def partial(*args, &block)
131
+ def partial(*arguments, &block)
132
132
  if block_given?
133
133
  state.defer(&block)
134
134
  else
135
135
  state.defer do |document|
136
- document.tag(*args)
136
+ document.tag(*arguments)
137
137
  end
138
138
  end
139
139
  end
@@ -23,9 +23,9 @@
23
23
  module Utopia
24
24
  class Content
25
25
  # Compatibility with older versions of rack:
26
- EXPIRES = 'Expires'.freeze
27
- CACHE_CONTROL = 'Cache-Control'.freeze
28
- CONTENT_TYPE = 'Content-Type'.freeze
26
+ EXPIRES = 'expires'.freeze
27
+ CACHE_CONTROL = 'cache-control'.freeze
28
+ CONTENT_TYPE = 'content-type'.freeze
29
29
  NO_CACHE = 'no-cache'.freeze
30
30
 
31
31
  # A basic content response, including useful defaults for typical HTML5 content.
@@ -33,20 +33,6 @@ require_relative 'controller/actions'
33
33
  require 'concurrent/map'
34
34
 
35
35
  module Utopia
36
- # A container for controller classes which are loaded from disk.
37
- module Controllers
38
- def self.class_name_for_controller(controller)
39
- controller.uri_path.to_a.collect{|_| _.capitalize}.join + "_#{controller.object_id}"
40
- end
41
-
42
- def self.define(klass)
43
- self.const_set(
44
- class_name_for_controller(klass),
45
- klass,
46
- )
47
- end
48
- end
49
-
50
36
  # A middleware which loads controller classes and invokes functionality based on the requested path.
51
37
  class Controller
52
38
  # The controller filename.
@@ -105,9 +91,6 @@ module Utopia
105
91
 
106
92
  klass.class_eval(File.read(controller_path), controller_path)
107
93
 
108
- # Give the controller a useful name:
109
- # Controllers.define(klass)
110
-
111
94
  # We lock down the controller class to prevent unsafe modifications:
112
95
  klass.freeze
113
96
 
@@ -24,6 +24,8 @@ require_relative '../http'
24
24
 
25
25
  module Utopia
26
26
  class Controller
27
+ CONTENT_TYPE = HTTP::CONTENT_TYPE
28
+
27
29
  # The base implementation of a controller class.
28
30
  class Base
29
31
  # A string which is the full path to the directory which contains the controller.
@@ -41,6 +43,24 @@ module Utopia
41
43
  self.const_get(:CONTROLLER)
42
44
  end
43
45
 
46
+ def self.inspect
47
+ "Controller#{self.uri_path}"
48
+ end
49
+
50
+ def self.to_s
51
+ self.inspect
52
+ end
53
+
54
+ def to_s
55
+ "\#<#{self.class}>"
56
+ end
57
+
58
+ def inspect
59
+ details = self.instance_variables.map{|name| " #{name}=#{self.instance_variable_get(name)}"}
60
+
61
+ "\#<#{self.class}#{details.join}>"
62
+ end
63
+
44
64
  class << self
45
65
  def freeze
46
66
  # This ensures that all class variables are frozen.
@@ -116,11 +136,11 @@ module Utopia
116
136
  end
117
137
 
118
138
  # Succeed the request and immediately respond.
119
- def succeed!(status: 200, headers: {}, **options)
139
+ def succeed!(status: 200, headers: {}, type: nil, **options)
120
140
  status = HTTP::Status.new(status, 200...300)
121
141
 
122
- if options[:type]
123
- headers[Rack::CONTENT_TYPE] = options[:type].to_s
142
+ if type
143
+ headers[CONTENT_TYPE] = type.to_s
124
144
  end
125
145
 
126
146
  body = body_for(status, headers, options)
@@ -21,7 +21,7 @@
21
21
  # THE SOFTWARE.
22
22
 
23
23
  require_relative '../http'
24
- require_relative '../path/matcher'
24
+ require_relative '../responder'
25
25
 
26
26
  module Utopia
27
27
  class Controller
@@ -31,139 +31,82 @@ module Utopia
31
31
  base.extend(ClassMethods)
32
32
  end
33
33
 
34
- module Converter
35
- def self.update_response(response, updated_headers)
36
- status, headers, body = response
34
+ module Handlers
35
+ module JSON
36
+ APPLICATION_JSON = HTTP::Accept::ContentType.new('application', 'json').freeze
37
37
 
38
- # Generate a new body:
39
- body = body.collect{|content| yield content}
40
-
41
- # Update the headers with the requested content type:
42
- headers = headers.merge(updated_headers)
43
-
44
- return [status, headers, body]
45
- end
46
-
47
- Callback = Struct.new(:content_type, :block) do
48
- def headers
49
- {HTTP::CONTENT_TYPE => self.content_type}
38
+ def self.split(*arguments)
39
+ APPLICATION_JSON.split(*arguments)
50
40
  end
51
41
 
52
- def split(*args)
53
- self.content_type.split(*args)
54
- end
55
-
56
- def call(context, response, media_range)
57
- Converter.update_response(response, headers) do |content|
58
- context.instance_exec(content, media_range, &block)
42
+ def self.call(context, request, media_range, object, **options)
43
+ if version = media_range.parameters['version']
44
+ options[:version] = version.to_s
59
45
  end
46
+
47
+ context.succeed! content: object.to_json(options), type: APPLICATION_JSON
60
48
  end
61
49
  end
62
50
 
63
- def self.new(*args)
64
- Callback.new(*args)
65
- end
66
-
67
- # To accept incoming requests with content-type JSON (e.g. POST with JSON data), consider using `Rack::PostBodyContentTypeParser`.
68
- module ToJSON
69
- APPLICATION_JSON = HTTP::Accept::ContentType.new('application', 'json', charset: 'utf-8').freeze
70
- HEADERS = {HTTP::CONTENT_TYPE => APPLICATION_JSON.to_s}.freeze
51
+ module Passthrough
52
+ WILDCARD = HTTP::Accept::MediaTypes::MediaRange.new('*', '*').freeze
71
53
 
72
- def self.content_type
73
- APPLICATION_JSON
54
+ def self.split(*arguments)
55
+ WILDCARD.split(*arguments)
74
56
  end
75
57
 
76
- def self.split(*args)
77
- self.content_type.split(*args)
78
- end
79
-
80
- def self.serialize(content, media_range)
81
- options = {}
82
-
83
- if version = media_range.parameters['version']
84
- options[:version] = version.to_s
85
- end
86
-
87
- return content.to_json(options)
88
- end
89
-
90
- def self.call(context, response, media_range)
91
- Converter.update_response(response, HEADERS) do |content|
92
- self.serialize(content, media_range)
93
- end
58
+ def self.call(context, request, media_range, object, **options)
59
+ # Do nothing.
94
60
  end
95
61
  end
96
62
  end
97
63
 
98
- module Passthrough
99
- WILDCARD = HTTP::Accept::MediaTypes::MediaRange.new('*', '*').freeze
100
-
101
- def self.split(*args)
102
- self.media_range.split(*args)
64
+ class Responder < Utopia::Responder
65
+ def with_json
66
+ @handlers << Handlers::JSON
103
67
  end
104
68
 
105
- def self.media_range
106
- WILDCARD
69
+ def with_passthrough
70
+ @handlers << Handlers::Passthrough
107
71
  end
108
72
 
109
- def self.call(context, response, media_range)
110
- return nil
73
+ def with(content_type, &block)
74
+ handle(content_type, &block)
111
75
  end
112
76
  end
113
77
 
114
- class Responder
115
- HTTP_ACCEPT = 'HTTP_ACCEPT'.freeze
116
- NOT_ACCEPTABLE_RESPONSE = [406, {}, []].freeze
117
-
118
- def initialize
119
- @converters = HTTP::Accept::MediaTypes::Map.new
78
+ module ClassMethods
79
+ def responds
80
+ @responder ||= Responder.new
120
81
  end
121
82
 
122
- def freeze
123
- @converters.freeze
124
-
125
- super
126
- end
83
+ alias respond responds
127
84
 
128
- # Add a converter for the specified content type. Call the block with the response content if the request accepts the specified content_type.
129
- def with(content_type, &block)
130
- @converters << Converter::Callback.new(content_type, block)
85
+ def respond_to(context, request)
86
+ @responder&.respond_to(context, request)
131
87
  end
132
88
 
133
- def with_passthrough
134
- @converters << Passthrough
135
- end
136
-
137
- # Add a converter for JSON when requests accept 'application/json'
138
- def with_json
139
- @converters << Converter::ToJSON
140
- end
141
-
142
- def call(context, request, path, response)
143
- # Parse the list of browser preferred content types and return ordered by priority:
144
- media_types = HTTP::Accept::MediaTypes.browser_preferred_media_types(request.env)
145
-
146
- converter, media_range = @converters.for(media_types)
147
-
148
- if converter
149
- converter.call(context, response, media_range)
150
- else
151
- NOT_ACCEPTABLE_RESPONSE
152
- end
89
+ def response_for(context, request, response)
90
+ @responder&.respond_to(context, request).with(*response[2])
153
91
  end
154
92
  end
155
93
 
156
- module ClassMethods
157
- def respond
158
- @responder ||= Responder.new
94
+ def respond_to(request)
95
+ self.class.respond_to(self, request)
96
+ end
97
+
98
+ def response_for(request, original_response)
99
+ response = catch(:response) do
100
+ self.class.response_for(self, request, original_response)
101
+
102
+ # If the above code did not throw a new response, we return the original:
103
+ return original_response
159
104
  end
160
105
 
161
- def response_for(context, request, path, response)
162
- if @responder
163
- @responder.call(context, request, path, response)
164
- else
165
- response
166
- end
106
+ # If the user called {Base#ignore!}, it's possible response is nil:
107
+ if response
108
+ # There was an updated response so merge it:
109
+ return [original_response[0], original_response[1].merge(response[1]), response[2] || original_response[2]]
167
110
  end
168
111
  end
169
112
 
@@ -173,11 +116,11 @@ module Utopia
173
116
  headers = response[1]
174
117
 
175
118
  # Don't try to convert the response if a content type was explicitly specified.
176
- unless headers[Rack::CONTENT_TYPE]
177
- response = self.class.response_for(self, request, path, response)
119
+ if headers[HTTP::CONTENT_TYPE]
120
+ return response
121
+ else
122
+ return self.response_for(request, response)
178
123
  end
179
-
180
- response
181
124
  end
182
125
  end
183
126
  end
@@ -23,8 +23,8 @@
23
23
  module Utopia
24
24
  module Extensions
25
25
  module ArraySplit
26
- def split_at(*args, &block)
27
- if middle = index(*args, &block)
26
+ def split_at(*arguments, &block)
27
+ if middle = index(*arguments, &block)
28
28
  [self[0...middle], self[middle], self[middle+1..-1]]
29
29
  else
30
30
  [[], nil, []]
@@ -90,9 +90,9 @@ module Utopia
90
90
  503 => 'Service Unavailable'.freeze
91
91
  }.merge(Rack::Utils::HTTP_STATUS_CODES)
92
92
 
93
- CONTENT_TYPE = 'Content-Type'.freeze
94
- LOCATION = 'Location'.freeze
95
- CACHE_CONTROL = 'Cache-Control'.freeze
93
+ CONTENT_TYPE = 'content-type'.freeze
94
+ LOCATION = 'location'.freeze
95
+ CACHE_CONTROL = 'cache-control'.freeze
96
96
 
97
97
  # A small HTTP status wrapper that verifies the status code within a given range.
98
98
  class Status
@@ -39,7 +39,7 @@ module Utopia
39
39
 
40
40
  # The same as {default_root} but returns an instance of {Path}.
41
41
  # @return [Path] The path as requested.
42
- def self.default_path(*args)
43
- Path[default_root(*args)]
42
+ def self.default_path(*arguments)
43
+ Path[default_root(*arguments)]
44
44
  end
45
45
  end
@@ -126,8 +126,8 @@ module Utopia
126
126
  @components = other_path.components.dup
127
127
  end
128
128
 
129
- def include?(*args)
130
- @components.include?(*args)
129
+ def include?(*arguments)
130
+ @components.include?(*arguments)
131
131
  end
132
132
 
133
133
  def directory?
@@ -200,8 +200,8 @@ module Utopia
200
200
  end
201
201
  end
202
202
 
203
- def with_prefix(*args)
204
- self.class.create(*args) + self
203
+ def with_prefix(*arguments)
204
+ self.class.create(*arguments) + self
205
205
  end
206
206
 
207
207
  # Computes the difference of the path.
@@ -54,8 +54,6 @@ module Utopia
54
54
  super
55
55
  end
56
56
 
57
- CONTENT_TYPE = 'Content-Type'.freeze
58
-
59
57
  def unhandled_error?(response)
60
58
  response[0] >= 400 && response[1].empty?
61
59
  end
@@ -0,0 +1,76 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright, 2012, by Samuel G. D. Williams. <http://www.codeotaku.com>
4
+ #
5
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ # of this software and associated documentation files (the "Software"), to deal
7
+ # in the Software without restriction, including without limitation the rights
8
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ # copies of the Software, and to permit persons to whom the Software is
10
+ # furnished to do so, subject to the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be included in
13
+ # all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ # THE SOFTWARE.
22
+
23
+ require_relative 'middleware'
24
+
25
+ module Utopia
26
+ class Responder
27
+ Handler = Struct.new(:content_type, :block) do
28
+ def split(*arguments)
29
+ self.content_type.split(*arguments)
30
+ end
31
+
32
+ def call(context, request, media_range, *arguments, **options)
33
+ context.instance_exec(media_range, *arguments, **options, &self.block)
34
+ end
35
+ end
36
+
37
+ Responds = Struct.new(:responder, :context, :request) do
38
+ # @todo Refactor `object` -> `*arguments`...
39
+ def with(object, **options)
40
+ responder.call(context, request, object, **options)
41
+ end
42
+ end
43
+
44
+ def initialize
45
+ @handlers = HTTP::Accept::MediaTypes::Map.new
46
+ end
47
+
48
+ attr :handlers
49
+
50
+ def freeze
51
+ @handlers.freeze
52
+
53
+ super
54
+ end
55
+
56
+ def call(context, request, *arguments, **options)
57
+ # Parse the list of browser preferred content types and return ordered by priority:
58
+ media_types = HTTP::Accept::MediaTypes.browser_preferred_media_types(request.env)
59
+
60
+ handler, media_range = @handlers.for(media_types)
61
+
62
+ if handler
63
+ handler.call(context, request, media_range, *arguments, **options)
64
+ end
65
+ end
66
+
67
+ # Add a converter for the specified content type. Call the block with the response content if the request accepts the specified content_type.
68
+ def handle(content_type, &block)
69
+ @handlers << Handler.new(content_type, block)
70
+ end
71
+
72
+ def respond_to(context, request)
73
+ Responds.new(self, context, request)
74
+ end
75
+ end
76
+ end