utopia 0.12.6 → 1.0.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 (126) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +6 -2
  3. data/Gemfile +6 -0
  4. data/README.md +48 -14
  5. data/Rakefile +5 -0
  6. data/bin/utopia +132 -15
  7. data/lib/utopia.rb +13 -10
  8. data/lib/utopia/content.rb +140 -0
  9. data/lib/utopia/content/link.rb +124 -0
  10. data/lib/utopia/content/links.rb +228 -0
  11. data/lib/utopia/content/node.rb +387 -0
  12. data/lib/utopia/content/processor.rb +128 -0
  13. data/lib/utopia/content/tag.rb +102 -0
  14. data/lib/utopia/controller.rb +137 -0
  15. data/lib/utopia/controller/action.rb +112 -0
  16. data/lib/utopia/controller/base.rb +174 -0
  17. data/lib/utopia/{middleware/controller → controller}/variables.rb +36 -38
  18. data/lib/utopia/exception_handler.rb +79 -0
  19. data/lib/utopia/extensions/array.rb +2 -2
  20. data/lib/utopia/localization.rb +143 -0
  21. data/lib/utopia/mail_exceptions.rb +136 -0
  22. data/lib/utopia/middleware.rb +7 -22
  23. data/lib/utopia/path.rb +150 -60
  24. data/lib/utopia/redirector.rb +152 -0
  25. data/lib/utopia/{extensions/hash.rb → session.rb} +4 -6
  26. data/lib/utopia/session/encrypted_cookie.rb +46 -48
  27. data/lib/utopia/{middleware/directory_index.rb → session/lazy_hash.rb} +44 -27
  28. data/lib/utopia/static.rb +255 -0
  29. data/lib/utopia/tags/deferred.rb +12 -8
  30. data/lib/utopia/tags/environment.rb +18 -6
  31. data/lib/utopia/tags/node.rb +12 -8
  32. data/lib/utopia/tags/override.rb +12 -12
  33. data/lib/utopia/version.rb +1 -1
  34. data/setup/.bowerrc +3 -0
  35. data/{lib/utopia/setup → setup}/Gemfile +1 -1
  36. data/setup/Rakefile +4 -0
  37. data/{lib/utopia/setup → setup}/cache/head/readme.txt +0 -0
  38. data/{lib/utopia/setup → setup}/cache/meta/readme.txt +0 -0
  39. data/setup/config.ru +64 -0
  40. data/{lib/utopia/setup → setup}/lib/readme.txt +0 -0
  41. data/{lib/utopia/setup → setup}/pages/_heading.xnode +0 -0
  42. data/{lib/utopia/setup → setup}/pages/_page.xnode +1 -1
  43. data/{lib/utopia/setup → setup}/pages/_static/icon.png +0 -0
  44. data/setup/pages/_static/site.css +70 -0
  45. data/{lib/utopia/setup → setup}/pages/errors/exception.xnode +0 -0
  46. data/{lib/utopia/setup → setup}/pages/errors/file-not-found.xnode +0 -0
  47. data/{lib/utopia/setup → setup}/pages/links.yaml +0 -0
  48. data/setup/pages/welcome/index.xnode +17 -0
  49. data/{lib/utopia/setup → setup}/public/readme.txt +0 -0
  50. data/spec/utopia/content/link_spec.rb +108 -0
  51. data/spec/utopia/content/links/foo/index.xnode +0 -0
  52. data/spec/utopia/content/links/foo/links.yaml +2 -0
  53. data/spec/utopia/content/links/foo/test.de.xnode +0 -0
  54. data/spec/utopia/content/links/foo/test.en.xnode +0 -0
  55. data/spec/utopia/content/links/links.yaml +9 -0
  56. data/spec/utopia/content/links/welcome.xnode +0 -0
  57. data/spec/utopia/content/localized/five/index.en.xnode +0 -0
  58. data/spec/utopia/content/localized/four/index.en.xnode +0 -0
  59. data/spec/utopia/content/localized/four/index.zh.xnode +0 -0
  60. data/spec/utopia/content/localized/four/links.yaml +4 -0
  61. data/spec/utopia/content/localized/links.yaml +16 -0
  62. data/spec/utopia/content/localized/one.xnode +0 -0
  63. data/spec/utopia/content/localized/three/index.xnode +0 -0
  64. data/spec/utopia/content/localized/two.en.xnode +0 -0
  65. data/spec/utopia/content/localized/two.zh.xnode +0 -0
  66. data/spec/utopia/content/node/ordered/first.xnode +0 -0
  67. data/spec/utopia/content/node/ordered/index.xnode +0 -0
  68. data/spec/utopia/content/node/ordered/links.yaml +4 -0
  69. data/spec/utopia/content/node/ordered/second.xnode +0 -0
  70. data/spec/utopia/content/node/related/foo.en.xnode +0 -0
  71. data/spec/utopia/content/node/related/foo.ja.xnode +0 -0
  72. data/spec/utopia/content/node/related/links.yaml +4 -0
  73. data/spec/utopia/content/node_spec.rb +63 -0
  74. data/spec/utopia/{middleware/content_spec.rb → content/processor_spec.rb} +34 -23
  75. data/spec/utopia/content_spec.rb +87 -0
  76. data/spec/utopia/content_spec.ru +10 -0
  77. data/spec/utopia/{middleware/controller_spec.rb → controller_spec.rb} +61 -16
  78. data/spec/utopia/controller_spec.ru +4 -0
  79. data/spec/utopia/extensions_spec.rb +6 -17
  80. data/spec/utopia/localization_spec.rb +60 -0
  81. data/spec/utopia/localization_spec.ru +11 -0
  82. data/{lib/utopia/tags.rb → spec/utopia/middleware_spec.rb} +8 -14
  83. data/spec/utopia/{middleware/content_root → pages}/_heading.xnode +0 -0
  84. data/spec/utopia/pages/content/_show-value.xnode +1 -0
  85. data/spec/utopia/pages/content/test-partial.xnode +1 -0
  86. data/spec/utopia/pages/controller/controller.rb +28 -0
  87. data/spec/utopia/pages/controller/index.xnode +1 -0
  88. data/spec/utopia/pages/controller/nested/controller.rb +4 -0
  89. data/spec/utopia/{middleware/content_root → pages}/index.xnode +0 -0
  90. data/spec/utopia/pages/localized.de.txt +1 -0
  91. data/spec/utopia/pages/localized.en.txt +1 -0
  92. data/spec/utopia/pages/localized.jp.txt +1 -0
  93. data/spec/utopia/pages/node/index.xnode +1 -0
  94. data/spec/utopia/pages/test.txt +1 -0
  95. data/spec/utopia/path_spec.rb +109 -0
  96. data/spec/utopia/rack_spec.rb +2 -0
  97. data/spec/utopia/session_spec.rb +82 -0
  98. data/spec/utopia/session_spec.ru +20 -0
  99. data/spec/utopia/spec_helper.rb +16 -0
  100. data/{lib/utopia/extensions/string.rb → spec/utopia/static_spec.rb} +24 -15
  101. data/spec/utopia/static_spec.ru +4 -0
  102. data/utopia.gemspec +3 -3
  103. metadata +138 -54
  104. data/lib/utopia/extensions/regexp.rb +0 -33
  105. data/lib/utopia/link.rb +0 -288
  106. data/lib/utopia/middleware/all.rb +0 -33
  107. data/lib/utopia/middleware/content.rb +0 -157
  108. data/lib/utopia/middleware/content/node.rb +0 -386
  109. data/lib/utopia/middleware/content/processor.rb +0 -123
  110. data/lib/utopia/middleware/controller.rb +0 -130
  111. data/lib/utopia/middleware/controller/action.rb +0 -121
  112. data/lib/utopia/middleware/controller/base.rb +0 -184
  113. data/lib/utopia/middleware/exception_handler.rb +0 -80
  114. data/lib/utopia/middleware/localization.rb +0 -147
  115. data/lib/utopia/middleware/localization/name.rb +0 -69
  116. data/lib/utopia/middleware/mail_exceptions.rb +0 -138
  117. data/lib/utopia/middleware/redirector.rb +0 -146
  118. data/lib/utopia/middleware/requester.rb +0 -126
  119. data/lib/utopia/middleware/static.rb +0 -295
  120. data/lib/utopia/setup.rb +0 -60
  121. data/lib/utopia/setup/config.ru +0 -47
  122. data/lib/utopia/setup/pages/_static/background.png +0 -0
  123. data/lib/utopia/setup/pages/_static/site.css +0 -48
  124. data/lib/utopia/setup/pages/welcome/index.xnode +0 -7
  125. data/lib/utopia/tag.rb +0 -105
  126. data/lib/utopia/tags/all.rb +0 -34
@@ -1,123 +0,0 @@
1
- # Copyright, 2012, by Samuel G. D. Williams. <http://www.codeotaku.com>
2
- #
3
- # Permission is hereby granted, free of charge, to any person obtaining a copy
4
- # of this software and associated documentation files (the "Software"), to deal
5
- # in the Software without restriction, including without limitation the rights
6
- # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
- # copies of the Software, and to permit persons to whom the Software is
8
- # furnished to do so, subject to the following conditions:
9
- #
10
- # The above copyright notice and this permission notice shall be included in
11
- # all copies or substantial portions of the Software.
12
- #
13
- # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
- # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
- # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
- # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
- # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
- # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
- # THE SOFTWARE.
20
-
21
- require 'utopia/tag'
22
- require 'trenni/parser'
23
- require 'trenni/strings'
24
-
25
- module Utopia
26
- module Middleware
27
- class Content
28
- class Processor
29
- def self.parse_xml(xml_data, delegate)
30
- processor = self.new(delegate)
31
-
32
- processor.parse(xml_data)
33
- end
34
-
35
- class UnbalancedTagError < StandardError
36
- def initialize(scanner, start_position, current_tag, closing_tag)
37
- @scanner = scanner
38
- @start_position = start_position
39
- @current_tag = current_tag
40
- @closing_tag = closing_tag
41
-
42
- @starting_line = Trenni::Parser.line_at_offset(@scanner.string, @start_position)
43
- @ending_line = Trenni::Parser.line_at_offset(@scanner.string, @scanner.pos)
44
- end
45
-
46
- attr :scanner
47
- attr :start_position
48
- attr :current_tag
49
- attr :closing_tag
50
-
51
- def to_s
52
- "Unbalanced Tag Error. " \
53
- "Line #{@starting_line[:line_number]}: #{@current_tag} has been closed by #{@closing_tag} on line #{@ending_line[:line_number]}!"
54
- end
55
- end
56
-
57
- def initialize(delegate)
58
- @delegate = delegate
59
- @stack = []
60
-
61
- @parser = Trenni::Parser.new(self)
62
- end
63
-
64
- def parse(input)
65
- @parser.parse(input)
66
- end
67
-
68
- def begin_parse(scanner)
69
- @scanner = scanner
70
- end
71
-
72
- def text(text)
73
- @delegate.cdata(text)
74
- end
75
-
76
- def cdata(text)
77
- @delegate.cdata(Trenni::Strings::to_html(text))
78
- end
79
-
80
- def comment(text)
81
- @delegate.cdata("<!#{text}>")
82
- end
83
-
84
- def begin_tag(tag_name, begin_tag_type)
85
- if begin_tag_type == :opened
86
- @stack << [Tag.new(tag_name, {}), @scanner.pos]
87
- else
88
- current_tag, current_position = @stack.pop
89
-
90
- if (tag_name != current_tag.name)
91
- raise UnbalancedTagError.new(@scanner, current_position, current_tag.name, tag_name)
92
- end
93
-
94
- @delegate.tag_end(current_tag)
95
- end
96
- end
97
-
98
- def finish_tag(begin_tag_type, end_tag_type)
99
- if begin_tag_type == :opened # <...
100
- if end_tag_type == :closed # <.../>
101
- cur, pos = @stack.pop
102
- cur.closed = true
103
-
104
- @delegate.tag_complete(cur)
105
- elsif end_tag_type == :opened # <...>
106
- cur, pos = @stack.last
107
-
108
- @delegate.tag_begin(cur)
109
- end
110
- end
111
- end
112
-
113
- def attribute(name, value)
114
- @stack.last[0].attributes[name] = value
115
- end
116
-
117
- def instruction(content)
118
- cdata("<?#{content}?>")
119
- end
120
- end
121
- end
122
- end
123
- end
@@ -1,130 +0,0 @@
1
- # Copyright, 2012, by Samuel G. D. Williams. <http://www.codeotaku.com>
2
- #
3
- # Permission is hereby granted, free of charge, to any person obtaining a copy
4
- # of this software and associated documentation files (the "Software"), to deal
5
- # in the Software without restriction, including without limitation the rights
6
- # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
- # copies of the Software, and to permit persons to whom the Software is
8
- # furnished to do so, subject to the following conditions:
9
- #
10
- # The above copyright notice and this permission notice shall be included in
11
- # all copies or substantial portions of the Software.
12
- #
13
- # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
- # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
- # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
- # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
- # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
- # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
- # THE SOFTWARE.
20
-
21
- require_relative 'controller/variables'
22
- require_relative 'controller/action'
23
- require_relative 'controller/base'
24
-
25
- class Rack::Request
26
- def controller(&block)
27
- if block_given?
28
- env["utopia.controller"].instance_eval(&block)
29
- else
30
- env["utopia.controller"]
31
- end
32
- end
33
- end
34
-
35
- module Utopia
36
- module Middleware
37
- class Controller
38
- CONTROLLER_RB = "controller.rb".freeze
39
-
40
- def initialize(app, options = {})
41
- @app = app
42
- @root = options[:root] || Utopia::Middleware::default_root
43
-
44
- @controllers = {}
45
- @cache_controllers = (UTOPIA_ENV == :production)
46
- end
47
-
48
- attr :app
49
-
50
- def lookup_controller(path)
51
- if @cache_controllers
52
- return @controllers.fetch(path.to_s) do |key|
53
- @controllers[key] = load_controller_file(path)
54
- end
55
- else
56
- return load_controller_file(path)
57
- end
58
- end
59
-
60
- def load_controller_file(path)
61
- uri_path = path
62
- base_path = File.join(@root, uri_path.components)
63
-
64
- controller_path = File.join(base_path, CONTROLLER_RB)
65
- # puts "load_controller_file(#{path.inspect}) => #{controller_path}"
66
-
67
- if File.exist?(controller_path)
68
- klass = Class.new(Base)
69
- klass.const_set(:BASE_PATH, base_path)
70
- klass.const_set(:URI_PATH, uri_path)
71
- klass.const_set(:CONTROLLER, self)
72
-
73
- $LOAD_PATH.unshift(base_path)
74
-
75
- klass.class_eval(File.read(controller_path), controller_path)
76
-
77
- $LOAD_PATH.delete(base_path)
78
-
79
- return klass.new
80
- else
81
- return nil
82
- end
83
- end
84
-
85
- def invoke_controllers(variables, request, done = Set.new)
86
- path = Path.create(request.path_info)
87
- controller_path = Path.new
88
-
89
- path.descend do |controller_path|
90
- # puts "Invoke controller: #{controller_path}"
91
- if controller = lookup_controller(controller_path)
92
- # We only want to invoke controllers which have not already been invoked:
93
- unless done.include? controller
94
- # If we get throw :rewrite, location, the URL has been rewritten and we need to request again:
95
- location = catch(:rewrite) do
96
- # Invoke the controller and if it returns a result, send it back out:
97
- if result = controller.process!(request, path)
98
- return result
99
- end
100
- end
101
-
102
- if location
103
- request.env['PATH_INFO'] = location.to_s
104
-
105
- return invoke_controllers(variables, request, done)
106
- end
107
-
108
- done << controller
109
- end
110
- end
111
- end
112
-
113
- # No controller gave a useful result:
114
- return nil
115
- end
116
-
117
- def call(env)
118
- variables = (env["utopia.controller"] ||= Variables.new)
119
-
120
- request = Rack::Request.new(env)
121
-
122
- if result = invoke_controllers(variables, request)
123
- return result
124
- end
125
-
126
- return @app.call(env)
127
- end
128
- end
129
- end
130
- end
@@ -1,121 +0,0 @@
1
- # Copyright, 2014, by Samuel G. D. Williams. <http://www.codeotaku.com>
2
- #
3
- # Permission is hereby granted, free of charge, to any person obtaining a copy
4
- # of this software and associated documentation files (the "Software"), to deal
5
- # in the Software without restriction, including without limitation the rights
6
- # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
- # copies of the Software, and to permit persons to whom the Software is
8
- # furnished to do so, subject to the following conditions:
9
- #
10
- # The above copyright notice and this permission notice shall be included in
11
- # all copies or substantial portions of the Software.
12
- #
13
- # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
- # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
- # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
- # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
- # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
- # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
- # THE SOFTWARE.
20
-
21
- module Utopia
22
- module Middleware
23
- class Controller
24
- class Action < Hash
25
- attr_accessor :callback
26
- attr_accessor :options
27
-
28
- def callback?
29
- @callback != nil
30
- end
31
-
32
- def indirect?
33
- @options[:indirect]
34
- end
35
-
36
- def eql? other
37
- super and self.callback.eql? other.callback and self.options.eql? other.options
38
- end
39
-
40
- def hash
41
- [super, callback, options].hash
42
- end
43
-
44
- def == other
45
- super and (self.callback == other.callback) and (self.options == other.options)
46
- end
47
-
48
- protected
49
-
50
- def append(path, index, actions = [])
51
- # ** is greedy, it always matches if possible:
52
- if match_all = self[:**]
53
- # Match all remaining input:
54
- actions << match_all if match_all.callback?
55
- end
56
-
57
- if index < path.size
58
- name = path[index].to_sym
59
-
60
- if match_name = self[name]
61
- # Match the exact name:
62
- match_name.append(path, index+1, actions)
63
- end
64
-
65
- if match_one = self[:*]
66
- # Match one input:
67
- match_one.append(path, index+1, actions)
68
- end
69
- else
70
- # Got to end, matched completely:
71
- actions << self if self.callback?
72
- end
73
- end
74
-
75
- public
76
-
77
- # relative_path = 2014/mr-potato
78
- # actions => {:** => A}
79
- def select(relative_path)
80
- actions = []
81
-
82
- append(relative_path.reverse, 0, actions)
83
-
84
- # puts "select(#{relative_path}, #{self.inspect}) => #{actions.inspect}"
85
-
86
- return actions
87
- end
88
-
89
- def define(path, options = {}, &callback)
90
- current = self
91
-
92
- path.reverse.each do |name|
93
- current = (current[name.to_sym] ||= Action.new)
94
- end
95
-
96
- current.options = options
97
- current.callback = callback
98
-
99
- return current
100
- end
101
-
102
- def invoke!(controller, *arguments)
103
- if @options[:unbound]
104
- # This is the old code path for explicit methods.
105
- controller.instance_exec(controller, *arguments, &@callback)
106
- else
107
- controller.instance_exec(*arguments, &@callback)
108
- end
109
- end
110
-
111
- def inspect
112
- if callback?
113
- "<action " + super + ":#{callback.source_location}(#{options})>"
114
- else
115
- "<action " + super + ">"
116
- end
117
- end
118
- end
119
- end
120
- end
121
- end
@@ -1,184 +0,0 @@
1
- # Copyright, 2014, by Samuel G. D. Williams. <http://www.codeotaku.com>
2
- #
3
- # Permission is hereby granted, free of charge, to any person obtaining a copy
4
- # of this software and associated documentation files (the "Software"), to deal
5
- # in the Software without restriction, including without limitation the rights
6
- # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
- # copies of the Software, and to permit persons to whom the Software is
8
- # furnished to do so, subject to the following conditions:
9
- #
10
- # The above copyright notice and this permission notice shall be included in
11
- # all copies or substantial portions of the Software.
12
- #
13
- # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
- # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
- # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
- # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
- # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
- # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
- # THE SOFTWARE.
20
-
21
- require 'utopia/path'
22
- require 'utopia/http'
23
-
24
- module Utopia
25
- module Middleware
26
- class Controller
27
- class Base
28
- def self.base_path
29
- self.const_get(:BASE_PATH)
30
- end
31
-
32
- def self.uri_path
33
- self.const_get(:URI_PATH)
34
- end
35
-
36
- def self.controller
37
- self.const_get(:CONTROLLER)
38
- end
39
-
40
- class << self
41
- def require_local(path)
42
- require File.join(base_path, path)
43
- end
44
-
45
- def direct?(path)
46
- path.dirname == uri_path
47
- end
48
-
49
- def actions
50
- @actions ||= Action.new
51
- end
52
-
53
- def on(path, options = {}, &block)
54
- if Symbol === path
55
- path = ['**', path]
56
- end
57
-
58
- actions.define(Path[path].components, options, &block)
59
- end
60
-
61
- def lookup(path)
62
- possible_actions = actions.select((path - uri_path).components)
63
- end
64
-
65
- def method_added(name)
66
- if name.match(/^on_(.*)$/)
67
- warn "Method #{name} using legacy definition mechanism."
68
- on($1.split("_").join('/'), unbound: true, &name)
69
- end
70
- end
71
- end
72
-
73
- # Given a path, look up all matched actions.
74
- def lookup(path)
75
- self.class.lookup(path)
76
- end
77
-
78
- # Given a request, call associated actions if at least one exists.
79
- def passthrough(request, path)
80
- actions = lookup(path)
81
-
82
- if actions.size > 0
83
- variables = request.controller
84
- controller_clone = self.clone
85
-
86
- variables << controller_clone
87
-
88
- response = catch(:response) do
89
- # By default give nothing - i.e. keep on processing:
90
- actions.each do |action|
91
- action.invoke!(controller_clone, request, path)
92
- end and nil
93
- end
94
-
95
- if response
96
- return controller_clone.respond_with(*response)
97
- end
98
- end
99
-
100
- return nil
101
- end
102
-
103
- # Copy the instance variables from the previous controller to the next controller (usually only a few). This allows controllers to share effectively the same instance variables while still being separate classes/instances.
104
- def copy_instance_variables(from)
105
- from.instance_variables.each do |name|
106
- instance_variable_set(name, from.instance_variable_get(name))
107
- end
108
- end
109
-
110
- def call(env)
111
- self.class.controller.app.call(env)
112
- end
113
-
114
- def respond!(*args)
115
- throw :response, args
116
- end
117
-
118
- def ignore!
119
- throw :response, nil
120
- end
121
-
122
- def redirect! (target, status = 302)
123
- respond! :redirect => target.to_str, :status => status
124
- end
125
-
126
- def rewrite! location
127
- throw :rewrite, location.to_str
128
- end
129
-
130
- def fail!(error = :bad_request)
131
- respond! error
132
- end
133
-
134
- def success!(*args)
135
- respond! :success, *args
136
- end
137
-
138
- def respond_with(*args)
139
- return args[0] if args[0] == nil || Array === args[0]
140
-
141
- status = 200
142
- options = nil
143
-
144
- if Numeric === args[0] || Symbol === args[0]
145
- status = args[0]
146
- options = args[1] || {}
147
- else
148
- options = args[0]
149
- status = options[:status] || status
150
- end
151
-
152
- status = Utopia::HTTP::STATUS_CODES[status] || status
153
- headers = options[:headers] || {}
154
-
155
- if options[:type]
156
- headers['Content-Type'] ||= options[:type]
157
- end
158
-
159
- if options[:redirect]
160
- headers["Location"] = options[:redirect]
161
- status = 302 if status < 300 || status >= 400
162
- end
163
-
164
- body = []
165
- if options[:body]
166
- body = options[:body]
167
- elsif options[:content]
168
- body = [options[:content]]
169
- elsif status >= 300
170
- body = [Utopia::HTTP::STATUS_DESCRIPTIONS[status] || "Status #{status}"]
171
- end
172
-
173
- return [status, headers, body]
174
- end
175
-
176
- # Return nil if this controller didn't do anything. Request will keep on processing. Return a valid rack response if the controller can do so.
177
- def process!(request, path)
178
- # puts "process! #{request} #{path}"
179
- passthrough(request, path)
180
- end
181
- end
182
- end
183
- end
184
- end