wee 0.5.0 → 0.6.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 (157) hide show
  1. data/ChangeLog +132 -0
  2. data/INSTALL +13 -3
  3. data/README +3 -3
  4. data/Rakefile +5 -1
  5. data/bin/wee +100 -0
  6. data/doc/rdoc/classes/Array.html +12 -12
  7. data/doc/rdoc/classes/Cache/StorageCache.html +38 -38
  8. data/doc/rdoc/classes/Cache/Strategy/CapacityBounded.html +30 -30
  9. data/doc/rdoc/classes/Cache/Strategy/LFU.html +24 -24
  10. data/doc/rdoc/classes/Cache/Strategy/LRU.html +24 -24
  11. data/doc/rdoc/classes/Cache/Strategy/Unbounded.html +24 -24
  12. data/doc/rdoc/classes/Enumerable.html +6 -6
  13. data/doc/rdoc/classes/Main.html +265 -0
  14. data/doc/rdoc/classes/Object.html +12 -12
  15. data/doc/rdoc/classes/OgApplication.html +2 -2
  16. data/doc/rdoc/classes/OgScaffolder.html +444 -64
  17. data/doc/rdoc/classes/OgScaffolder/Editor.html +490 -0
  18. data/doc/rdoc/classes/OgSession.html +4 -4
  19. data/doc/rdoc/classes/Recipe.html +113 -0
  20. data/doc/rdoc/classes/String.html +12 -12
  21. data/doc/rdoc/classes/Struct.html +12 -12
  22. data/doc/rdoc/classes/Wee.html +10 -1
  23. data/doc/rdoc/classes/Wee/AnswerDecoration.html +9 -9
  24. data/doc/rdoc/classes/Wee/Application.html +48 -47
  25. data/doc/rdoc/classes/Wee/Brush.html +19 -23
  26. data/doc/rdoc/classes/Wee/Brush/AnchorTag.html +17 -14
  27. data/doc/rdoc/classes/Wee/Brush/FileUploadTag.html +20 -14
  28. data/doc/rdoc/classes/Wee/Brush/FormTag.html +25 -21
  29. data/doc/rdoc/classes/Wee/Brush/GenericEncodedTextBrush.html +12 -12
  30. data/doc/rdoc/classes/Wee/Brush/GenericSingleTagBrush.html +7 -7
  31. data/doc/rdoc/classes/Wee/Brush/GenericTagBrush.html +234 -100
  32. data/doc/rdoc/classes/Wee/Brush/GenericTextBrush.html +12 -12
  33. data/doc/rdoc/classes/Wee/Brush/ImageButtonTag.html +28 -22
  34. data/doc/rdoc/classes/Wee/Brush/ImageTag.html +23 -24
  35. data/doc/rdoc/classes/Wee/Brush/InputTag.html +14 -14
  36. data/doc/rdoc/classes/Wee/Brush/JavascriptTag.html +7 -7
  37. data/doc/rdoc/classes/Wee/Brush/Page.html +14 -14
  38. data/doc/rdoc/classes/Wee/Brush/SelectListTag.html +33 -57
  39. data/doc/rdoc/classes/Wee/Brush/SelectListTag/SelectListCallback.html +154 -0
  40. data/doc/rdoc/classes/Wee/Brush/SelectOptionTag.html +7 -7
  41. data/doc/rdoc/classes/Wee/Brush/SubmitButtonTag.html +20 -14
  42. data/doc/rdoc/classes/Wee/Brush/TableDataTag.html +14 -14
  43. data/doc/rdoc/classes/Wee/Brush/TableHeaderTag.html +7 -7
  44. data/doc/rdoc/classes/Wee/Brush/TableRowTag.html +42 -42
  45. data/doc/rdoc/classes/Wee/Brush/TableTag.html +7 -7
  46. data/doc/rdoc/classes/Wee/Brush/TextAreaTag.html +27 -21
  47. data/doc/rdoc/classes/Wee/Brush/TextInputTag.html +20 -14
  48. data/doc/rdoc/classes/Wee/CallbackRegistry.html +64 -36
  49. data/doc/rdoc/classes/Wee/CallbackStream.html +21 -21
  50. data/doc/rdoc/classes/Wee/Canvas.html +24 -24
  51. data/doc/rdoc/classes/Wee/Component.html +179 -151
  52. data/doc/rdoc/classes/Wee/Component/OnAnswer.html +12 -12
  53. data/doc/rdoc/classes/Wee/Decoration.html +42 -42
  54. data/doc/rdoc/classes/Wee/Delegate.html +27 -27
  55. data/doc/rdoc/classes/Wee/ErrorResponse.html +14 -14
  56. data/doc/rdoc/classes/Wee/FormDecoration.html +6 -6
  57. data/doc/rdoc/classes/Wee/GenericResponse.html +7 -7
  58. data/doc/rdoc/classes/Wee/HtmlCanvas.html +326 -219
  59. data/doc/rdoc/classes/Wee/HtmlWriter.html +40 -40
  60. data/doc/rdoc/classes/Wee/LiteralMethodCallback.html +19 -19
  61. data/doc/rdoc/classes/Wee/Md5IdGenerator.html +181 -0
  62. data/doc/rdoc/classes/Wee/MessageBox.html +12 -12
  63. data/doc/rdoc/classes/Wee/PageDecoration.html +18 -18
  64. data/doc/rdoc/classes/Wee/PagelessApplication.html +152 -0
  65. data/doc/rdoc/classes/Wee/PagelessRequest.html +177 -0
  66. data/doc/rdoc/classes/Wee/PagelessSession.html +320 -0
  67. data/doc/rdoc/classes/Wee/Presenter.html +145 -89
  68. data/doc/rdoc/classes/Wee/RedirectResponse.html +7 -7
  69. data/doc/rdoc/classes/Wee/RefreshResponse.html +7 -7
  70. data/doc/rdoc/classes/Wee/Request.html +116 -50
  71. data/doc/rdoc/classes/Wee/RequestHandler.html +31 -31
  72. data/doc/rdoc/classes/Wee/Response.html +76 -28
  73. data/doc/rdoc/classes/Wee/Session.html +129 -506
  74. data/doc/rdoc/classes/Wee/SimpleIdGenerator.html +22 -40
  75. data/doc/rdoc/classes/Wee/Snapshot.html +19 -19
  76. data/doc/rdoc/classes/Wee/Utils.html +70 -17
  77. data/doc/rdoc/classes/Wee/Utils/LRUCache.html +6 -6
  78. data/doc/rdoc/classes/Wee/ValueHolder.html +18 -18
  79. data/doc/rdoc/classes/Wee/WEBrickAdaptor.html +82 -49
  80. data/doc/rdoc/classes/Wee/WrapperDecoration.html +6 -6
  81. data/doc/rdoc/created.rid +1 -1
  82. data/doc/rdoc/files/INSTALL.html +17 -5
  83. data/doc/rdoc/files/README.html +9 -11
  84. data/doc/rdoc/files/lib/wee/adaptors/webrick_rb.html +1 -1
  85. data/doc/rdoc/files/lib/wee/application_rb.html +1 -1
  86. data/doc/rdoc/files/lib/wee/components/page_decoration_rb.html +1 -1
  87. data/doc/rdoc/files/lib/wee/continuation/session_rb.html +1 -3
  88. data/doc/rdoc/files/lib/wee/core/callback_rb.html +1 -1
  89. data/doc/rdoc/files/lib/wee/core/component_rb.html +1 -1
  90. data/doc/rdoc/files/lib/wee/core_rb.html +3 -3
  91. data/doc/rdoc/files/lib/wee/databases/og/application_rb.html +101 -0
  92. data/doc/rdoc/files/lib/wee/databases/og/old_scaffolder_rb.html +101 -0
  93. data/doc/rdoc/files/lib/wee/databases/og/scaffolder_rb.html +108 -0
  94. data/doc/rdoc/files/lib/wee/databases/og/session_rb.html +101 -0
  95. data/doc/rdoc/files/lib/wee/databases/og_rb.html +4 -1
  96. data/doc/rdoc/files/lib/wee/idgen/md5_rb.html +115 -0
  97. data/doc/rdoc/files/lib/wee/idgen/simple_rb.html +107 -0
  98. data/doc/rdoc/files/lib/wee/pageless/application_rb.html +101 -0
  99. data/doc/rdoc/files/lib/wee/pageless/request_rb.html +101 -0
  100. data/doc/rdoc/files/lib/wee/pageless/session_rb.html +108 -0
  101. data/doc/rdoc/files/lib/wee/pageless_rb.html +110 -0
  102. data/doc/rdoc/files/lib/wee/renderer/html/brushes_rb.html +1 -1
  103. data/doc/rdoc/files/lib/wee/renderer/html/canvas_rb.html +8 -1
  104. data/doc/rdoc/files/lib/wee/request_rb.html +1 -1
  105. data/doc/rdoc/files/lib/wee/response_rb.html +1 -1
  106. data/doc/rdoc/files/lib/wee/session_rb.html +1 -1
  107. data/doc/rdoc/files/lib/wee/skeleton/og/components/main_rb.html +101 -0
  108. data/doc/rdoc/files/lib/wee/skeleton/og/conf/db_rb.html +114 -0
  109. data/doc/rdoc/files/lib/wee/skeleton/og/models/recipe_rb.html +101 -0
  110. data/doc/rdoc/files/lib/wee/skeleton/og/run_rb.html +115 -0
  111. data/doc/rdoc/files/lib/wee/skeleton/simple/components/main_rb.html +101 -0
  112. data/doc/rdoc/files/lib/wee/skeleton/simple/run_rb.html +111 -0
  113. data/doc/rdoc/files/lib/wee/template_rb.html +101 -0
  114. data/doc/rdoc/files/lib/wee/utils/autoreload_rb.html +1 -1
  115. data/doc/rdoc/files/lib/wee/utils/helper_rb.html +1 -1
  116. data/doc/rdoc/files/lib/wee_rb.html +4 -2
  117. data/doc/rdoc/fr_class_index.html +8 -4
  118. data/doc/rdoc/fr_file_index.html +17 -1
  119. data/doc/rdoc/fr_method_index.html +312 -267
  120. data/examples/live-update.rb +1 -1
  121. data/install.rb +14 -0
  122. data/lib/wee.rb +6 -2
  123. data/lib/wee/adaptors/webrick.rb +17 -5
  124. data/lib/wee/application.rb +2 -1
  125. data/lib/wee/continuation/session.rb +1 -146
  126. data/lib/wee/core/callback.rb +11 -5
  127. data/lib/wee/core/component.rb +14 -10
  128. data/lib/wee/databases/og.rb +3 -113
  129. data/lib/wee/databases/og/application.rb +3 -0
  130. data/lib/wee/databases/og/old_scaffolder.rb +98 -0
  131. data/lib/wee/databases/og/scaffolder.rb +174 -0
  132. data/lib/wee/databases/og/session.rb +9 -0
  133. data/lib/wee/idgen/md5.rb +21 -0
  134. data/lib/wee/{idgen.rb → idgen/simple.rb} +2 -4
  135. data/lib/wee/pageless.rb +3 -0
  136. data/lib/wee/pageless/application.rb +9 -0
  137. data/lib/wee/pageless/request.rb +15 -0
  138. data/lib/wee/pageless/session.rb +89 -0
  139. data/lib/wee/renderer/html/brushes.rb +100 -115
  140. data/lib/wee/renderer/html/canvas.rb +32 -2
  141. data/lib/wee/request.rb +36 -24
  142. data/lib/wee/response.rb +8 -1
  143. data/lib/wee/session.rb +13 -7
  144. data/lib/wee/skeleton/og/README +38 -0
  145. data/lib/wee/skeleton/og/components/main.rb +16 -0
  146. data/lib/wee/skeleton/og/conf/db.rb +8 -0
  147. data/lib/wee/skeleton/og/models/recipe.rb +5 -0
  148. data/lib/wee/skeleton/og/run.rb +23 -0
  149. data/lib/wee/skeleton/simple/README +32 -0
  150. data/lib/wee/skeleton/simple/components/main.rb +25 -0
  151. data/lib/wee/skeleton/simple/run.rb +12 -0
  152. data/lib/wee/template.rb +28 -0
  153. data/lib/wee/utils/autoreload.rb +29 -0
  154. data/lib/wee/utils/helper.rb +9 -5
  155. data/test/test_request.rb +4 -3
  156. data/wee.gemspec +3 -1
  157. metadata +91 -22
@@ -0,0 +1,3 @@
1
+ class OgApplication < Wee::Application
2
+ attr_accessor :db
3
+ end
@@ -0,0 +1,98 @@
1
+ class OgScaffolder < Wee::Component
2
+
3
+ def initialize(domain_class)
4
+ super()
5
+ @domain_class = domain_class
6
+ @attributes = domain_class.__props.map {|a| a.name}.reject {|a| a == 'oid'}
7
+ end
8
+
9
+ def delete(obj)
10
+ call Wee::MessageBox.new('Really delete?'), :confirm_delete, obj
11
+ end
12
+
13
+ def confirm_delete(confirmed, obj)
14
+ if confirmed
15
+ @objs.delete(obj)
16
+ obj.delete!
17
+ end
18
+ end
19
+
20
+ def edit(obj)
21
+ @edit = obj
22
+ end
23
+
24
+ def save(obj)
25
+ obj.save!
26
+ @edit = nil
27
+ end
28
+
29
+ def cancel
30
+ @objs.delete(@edit) if @edit and @edit.oid.nil?
31
+ @edit = nil
32
+ end
33
+
34
+ def refresh
35
+ @objs = @domain_class.all || []
36
+ end
37
+
38
+ def create
39
+ @objs << (@edit = @domain_class.new)
40
+ end
41
+
42
+ def render
43
+ refresh if @objs.nil?
44
+
45
+ r.h1 "#{ @domain_class } List"
46
+ r.anchor.callback { refresh }.with("Refresh")
47
+
48
+ r.form do
49
+ r.table.border(1).with {
50
+
51
+ r.table_row.with {
52
+ @attributes.each {|a|
53
+ r.table_header.with {
54
+ r.bold(a.capitalize)
55
+ }
56
+ }
57
+ r.table_header.with(" ")
58
+ }
59
+
60
+ @objs.each {|o|
61
+ r.table_row.with do
62
+ if @edit == o
63
+
64
+ @attributes.each { |attr|
65
+ r.table_data.with { r.text_input.callback {|v| o.send(attr+"=",v) }.value(o.send(attr)) }
66
+ }
67
+
68
+ r.table_data.with {
69
+ r.submit_button.callback { save(o) }.value("Save")
70
+ r.space
71
+ r.submit_button.callback { cancel() }.value("Cancel")
72
+ r.space
73
+ r.anchor.callback { delete(o) }.with("Delete")
74
+ }
75
+
76
+ else
77
+
78
+ @attributes.each { |attr|
79
+ r.table_data(o.send(attr))
80
+ }
81
+
82
+ r.table_data.with {
83
+ r.anchor.callback { edit(o) }.with("Edit")
84
+ r.space
85
+ r.anchor.callback { delete(o) }.with("Delete")
86
+ }
87
+
88
+ end
89
+ end
90
+ }
91
+ }
92
+ end
93
+
94
+ r.anchor.callback { create() }.with("Add new #{ @domain_class }")
95
+
96
+ end
97
+
98
+ end
@@ -0,0 +1,174 @@
1
+ # This is a Rails-like scaffolder for use with Og (http://navel.gr/nitro)
2
+ # domain objects.
3
+
4
+ class OgScaffolder < Wee::Component
5
+ def initialize(domain_class)
6
+ super()
7
+ @domain_class = domain_class
8
+ # DON'T use @properties here as it is already used by Wee
9
+ @props = @domain_class.__props.reject {|a| a.name == 'oid'}
10
+ end
11
+
12
+ def render
13
+ r.h1 "List #{ @domain_class }"
14
+ r.paragraph
15
+ r.table.border(1).with {
16
+ render_header
17
+ render_body
18
+ }
19
+ r.paragraph
20
+ r.anchor.callback(:add).with("Add new #{ @domain_class }")
21
+ end
22
+
23
+ def render_header
24
+ r.table_row.with {
25
+ @props.each {|prop|
26
+ render_property_header(prop)
27
+ }
28
+ render_action_header
29
+ }
30
+ end
31
+
32
+ def render_action_header
33
+ r.paragraph
34
+ r.table_header.with { r.space(2) } # the action column
35
+ end
36
+
37
+ def render_property_header(prop)
38
+ r.table_header.with {
39
+ r.bold(prop.name.to_s.capitalize)
40
+ }
41
+ end
42
+
43
+ def render_body
44
+ domain_objects.each {|obj| render_object(obj) }
45
+ end
46
+
47
+ def render_object(obj)
48
+ r.table_row {
49
+ @props.each {|prop| render_property(obj, prop) }
50
+ render_action(obj)
51
+ }
52
+ end
53
+
54
+ def render_action(obj)
55
+ r.table_data.with {
56
+ r.anchor.callback(:edit, obj).with("Edit")
57
+ r.space
58
+ r.anchor.callback(:destroy, obj).with("Destroy")
59
+ }
60
+ end
61
+
62
+ def render_property(obj, prop)
63
+ r.table_data(obj.send(prop.name).to_s)
64
+ end
65
+
66
+ def edit(obj)
67
+ call Editor.new(obj).add_decoration(Wee::FormDecoration.new)
68
+ end
69
+
70
+ def add
71
+ call Editor.new(@domain_class.new, "Create").
72
+ add_decoration(Wee::FormDecoration.new)
73
+ end
74
+
75
+ def destroy(obj)
76
+ call Wee::MessageBox.new('Do you really want to destroy the object?'),
77
+ :confirm_destroy, obj
78
+ end
79
+
80
+ def confirm_destroy(obj, confirmed)
81
+ obj.delete! if confirmed
82
+ end
83
+
84
+ def domain_objects
85
+ @domain_class.all || []
86
+ end
87
+ end
88
+
89
+ class OgScaffolder::Editor < Wee::Component
90
+
91
+ def initialize(domain_object, action="Edit")
92
+ super()
93
+ @domain_object = domain_object
94
+ @action = action
95
+ end
96
+
97
+ def render
98
+ render_header
99
+ each_property {|prop|
100
+ render_property(prop) unless prop.name == 'oid'
101
+ }
102
+ render_buttons
103
+ end
104
+
105
+ def render_header
106
+ r.h1 "#{ @action } #{ @domain_object.class }"
107
+ end
108
+
109
+ def render_property(prop)
110
+ render_label(prop)
111
+
112
+ if prop.klass.ancestors.include?(Numeric)
113
+ render_numeric(prop)
114
+ elsif prop.klass.ancestors.include?(String)
115
+ render_string(prop)
116
+ elsif prop.klass.ancestors.include?(TrueClass)
117
+ render_bool(prop)
118
+ end
119
+ end
120
+
121
+ def render_numeric(prop)
122
+ r.text_input.value(get_value_of(prop)).callback(:set_value_of, prop)
123
+ end
124
+
125
+ def render_string(prop)
126
+ if prop.meta[:ui] == :textarea
127
+ r.text_area.callback(:set_value_of, prop).with(get_value_of(prop))
128
+ else
129
+ r.text_input.value(get_value_of(prop)).callback(:set_value_of, prop)
130
+ end
131
+ end
132
+
133
+ def render_bool(prop)
134
+ selected = [ get_value_of(prop) ? true : false ]
135
+ r.select_list([true, false]).labels(["Yes", "No"]).selected(selected).
136
+ callback {|choosen| set_value_of(prop, choosen.first) }
137
+ end
138
+
139
+ def render_buttons
140
+ r.paragraph
141
+ r.submit_button.value('Save').callback(:save)
142
+ r.space
143
+ r.submit_button.value('Cancel').callback(:cancel)
144
+ end
145
+
146
+ def render_label(prop)
147
+ r.paragraph
148
+ r.text prop.name.capitalize
149
+ r.break
150
+ end
151
+
152
+ private
153
+
154
+ def each_property(&block)
155
+ @domain_object.class.__props.each(&block)
156
+ end
157
+
158
+ def get_value_of(prop)
159
+ @domain_object.send(prop.symbol)
160
+ end
161
+
162
+ def set_value_of(prop, value)
163
+ @domain_object.send(prop.symbol.to_s + "=", value)
164
+ end
165
+
166
+ def save
167
+ @domain_object.save!
168
+ answer @domain_object
169
+ end
170
+
171
+ def cancel
172
+ answer nil
173
+ end
174
+ end
@@ -0,0 +1,9 @@
1
+ class OgSession < Wee::Session
2
+ def awake
3
+ application.db.get_connection
4
+ end
5
+
6
+ def sleep
7
+ application.db.put_connection
8
+ end
9
+ end
@@ -0,0 +1,21 @@
1
+ # Returned ids might not be unique, but it should be very hard to guess the
2
+ # next id.
3
+
4
+ require 'digest/md5'
5
+
6
+ class Wee::Md5IdGenerator
7
+ def initialize(salt='wee')
8
+ @salt = salt
9
+ end
10
+
11
+ def next
12
+ now = Time.now
13
+ md5 = Digest::MD5.new
14
+ md5.update(now.to_s)
15
+ md5.update(now.usec.to_s)
16
+ md5.update(rand(0).to_s)
17
+ md5.update($$.to_s)
18
+ md5.update(@salt.to_s)
19
+ md5.hexdigest
20
+ end
21
+ end
@@ -1,12 +1,10 @@
1
+ # Returned ids are guaranteed to be unique, but they are easily guessable.
2
+
1
3
  class Wee::SimpleIdGenerator
2
4
  def initialize(initial_value=0)
3
5
  @value = initial_value
4
6
  end
5
7
 
6
- def current
7
- @value
8
- end
9
-
10
8
  def next
11
9
  @value += 1
12
10
  end
@@ -0,0 +1,3 @@
1
+ require 'wee/pageless/application'
2
+ require 'wee/pageless/session'
3
+ require 'wee/pageless/request'
@@ -0,0 +1,9 @@
1
+ class Wee::PagelessApplication < Wee::Application
2
+ def request_handler_expired(context)
3
+ context.response = Wee::RedirectResponse.new(context.request.application_path)
4
+ # TODO: depends on WEBrick
5
+ cookie = WEBrick::Cookie.new('SID', '')
6
+ cookie.max_age = 0
7
+ context.response.cookies << cookie
8
+ end
9
+ end
@@ -0,0 +1,15 @@
1
+ class Wee::PagelessRequest < Wee::Request
2
+
3
+ def build_url(request_handler_id=nil, page_id=nil, callback_id=nil)
4
+ url = ""
5
+ url << @app_path
6
+ url << ('?' + callback_id) if callback_id
7
+ return url
8
+ end
9
+
10
+ def parse_path
11
+ if sid = @cookies.find {|c| c.name == 'SID'}
12
+ @request_handler_id = sid.value
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,89 @@
1
+ require 'thread'
2
+
3
+ # A session class, which does not have a page-store and as such cannot
4
+ # backtrack.
5
+
6
+ class Wee::PagelessSession < Wee::Session
7
+ attr_accessor :root_component
8
+ undef page_store
9
+
10
+ attr_accessor :callbacks
11
+ alias current_callbacks callbacks
12
+
13
+ def initialize(&block)
14
+ Thread.current[:wee_session] = self
15
+
16
+ # to serialize the requests we need a mutex
17
+ @mutex = Mutex.new
18
+
19
+ block.call(self)
20
+
21
+ raise ArgumentError, "No root component specified" if @root_component.nil?
22
+
23
+ super()
24
+ ensure
25
+ Thread.current[:wee_session] = nil
26
+ end
27
+
28
+ def process_request
29
+ p @context.request.fields if $DEBUG
30
+
31
+ if @context.request.fields.empty?
32
+
33
+ # No action/inputs were specified -> render page
34
+ #
35
+ # 1. Reset the action/input fields (as they are regenerated in the
36
+ # rendering process).
37
+ # 2. Render the page (respond).
38
+ # 3. Store the page back into the store
39
+
40
+ new_callbacks = Wee::CallbackRegistry.new(Wee::SimpleIdGenerator.new)
41
+ respond(@context, new_callbacks) # render
42
+ self.callbacks = new_callbacks
43
+
44
+ else
45
+
46
+ # Actions/inputs were specified.
47
+ #
48
+ # We process the request and invoke actions/inputs. Then we generate a
49
+ # new page view.
50
+
51
+ callback_stream = Wee::CallbackStream.new(self.callbacks, @context.request.fields)
52
+
53
+ if callback_stream.all_of_type(:action).size > 1
54
+ raise "Not allowed to specify more than one action callback"
55
+ end
56
+
57
+ live_update_response = catch(:wee_live_update) {
58
+ catch(:wee_back_to_session) {
59
+ @root_component.process_callbacks_chain(callback_stream)
60
+ }
61
+ nil
62
+ }
63
+
64
+ if live_update_response
65
+ @context.response = live_update_response
66
+ else
67
+ handle_new_page_view(@context)
68
+ end
69
+
70
+ end
71
+
72
+ end
73
+
74
+ private
75
+
76
+ def handle_new_page_view(context)
77
+ redirect_url = context.request.build_url(context.request.request_handler_id, nil)
78
+ set_response(context, Wee::RedirectResponse.new(redirect_url))
79
+ end
80
+
81
+ def set_response(context, response)
82
+ # TODO: depends on WEBrick!
83
+ response.cookies << WEBrick::Cookie.new('SID', self.id)
84
+ response.header.delete('Expire')
85
+ response.header['Pragma'] = 'No-Cache'
86
+ super
87
+ end
88
+
89
+ end