wee 0.7.0 → 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,7 +1,7 @@
1
1
  require 'time'
2
2
 
3
3
  class Wee::Response
4
- DEFAULT_HEADER = { 'Content-Type' => 'text/html' }.freeze
4
+ DEFAULT_HEADER = {}.freeze
5
5
 
6
6
  attr_accessor :status, :content
7
7
  attr_reader :header
@@ -17,6 +17,7 @@ class Wee::Response
17
17
  def initialize(mime_type = 'text/html', content='')
18
18
  @status = 200
19
19
  @header = DEFAULT_HEADER.dup
20
+ self.content_type = mime_type
20
21
  @content = content
21
22
  end
22
23
 
@@ -1,195 +1,194 @@
1
+ require 'wee/abstractsession'
1
2
  require 'wee/page'
2
- require 'thread'
3
3
 
4
- class Wee::Session < Wee::RequestHandler
5
- attr_accessor :root_component, :page_store
4
+ class Wee::Session < Wee::AbstractSession
6
5
 
7
- def self.current
8
- sess = Thread.current[:wee_session]
9
- raise "not in session" if sess.nil?
10
- return sess
11
- end
6
+ attr_accessor :root_component
7
+ attr_accessor :page_store
12
8
 
13
9
  def initialize(&block)
14
- Thread.current[:wee_session] = self
15
-
16
- @idgen = Wee::SimpleIdGenerator.new
17
-
18
- # to serialize the requests we need a mutex
19
- @mutex = Mutex.new
20
-
21
- block.call(self)
22
-
23
- raise ArgumentError, "No root component specified" if @root_component.nil?
24
- raise ArgumentError, "No page_store specified" if @page_store.nil?
25
-
26
- @initial_snapshot = snapshot()
27
-
28
10
  super()
29
- ensure
30
- Thread.current[:wee_session] = nil
11
+ setup(&block)
31
12
  end
32
13
 
33
- def snapshot
34
- @root_component.backtrack_state_chain(snap = Wee::Snapshot.new)
35
- return snap.freeze
14
+ def current_callbacks
15
+ @page.callbacks
36
16
  end
37
17
 
38
- # called by application to send the session a request
39
-
40
- def handle_request(context)
41
- @mutex.synchronize do
42
- begin
43
- Thread.current[:wee_session] = self
44
- @context = context
45
- super
46
- awake
47
- process_request
48
- sleep
49
- rescue Exception => exn
50
- set_response(context, Wee::ErrorResponse.new(exn))
51
- ensure
52
- Thread.current[:wee_session] = nil
53
- @context = nil
54
- @page = nil
55
- end
56
- end
57
- end
18
+ # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
19
+ # :section: Request processing/handling
20
+ # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
58
21
 
59
- def create_page(snapshot)
60
- idgen = Wee::SimpleIdGenerator.new
61
- page = Wee::Page.new(snapshot, Wee::CallbackRegistry.new(idgen))
62
- end
22
+ protected
63
23
 
64
- # Is called before process_request is invoked
65
- # Can be used to setup e.g. a database connection.
66
- def awake
67
- end
24
+ def setup(&block)
25
+ @idgen = Wee::SimpleIdGenerator.new
68
26
 
69
- # Is called after process_request is run
70
- # Can be used to release e.g. a database connection.
71
- def sleep
27
+ with_session do
28
+ block.call(self) if block
29
+ raise ArgumentError, "No root component specified" if @root_component.nil?
30
+ raise ArgumentError, "No page_store specified" if @page_store.nil?
31
+
32
+ @initial_snapshot = snapshot()
33
+ end
72
34
  end
73
35
 
36
+ # The main routine where the request is processed.
37
+
74
38
  def process_request
75
39
  if @context.request.page_id.nil?
76
40
 
77
41
  # No page_id was specified in the URL. This means that we start with a
78
42
  # fresh component and a fresh page_id, then redirect to render itself.
79
43
 
80
- handle_new_page_view(@context, @initial_snapshot)
44
+ handle_new_page
81
45
 
82
46
  elsif @page = @page_store.fetch(@context.request.page_id, false)
83
47
 
84
48
  # A valid page_id was specified and the corresponding page exists.
85
49
 
86
- @page.snapshot.restore if @context.request.page_id != @snapshot_page_id
87
-
88
- p @context.request.fields if $DEBUG
89
-
90
- if @context.request.fields.empty?
50
+ handle_existing_page
91
51
 
92
- # No action/inputs were specified -> render page
93
- #
94
- # 1. Reset the action/input fields (as they are regenerated in the
95
- # rendering process).
96
- # 2. Render the page (respond).
97
- # 3. Store the page back into the store
98
-
99
- @page = create_page(@page.snapshot) # remove all action/input handlers
100
- respond(@context, @page.callbacks) # render
101
- @page_store[@context.request.page_id] = @page # store
102
-
103
- else
52
+ else
104
53
 
105
- # Actions/inputs were specified.
106
- #
107
- # We process the request and invoke actions/inputs. Then we generate a
108
- # new page view.
54
+ # A page_id was specified in the URL, but there's no page for it in the
55
+ # page store. Either the page has timed out, or an invalid page_id was
56
+ # specified.
109
57
 
110
- callback_stream = Wee::CallbackStream.new(@page.callbacks, @context.request.fields)
58
+ handle_invalid_page
111
59
 
112
- if callback_stream.all_of_type(:action).size > 1
113
- raise "Not allowed to specify more than one action callback"
114
- end
60
+ end
61
+ end
115
62
 
116
- live_update_response = catch(:wee_live_update) {
117
- catch(:wee_back_to_session) {
118
- @root_component.process_callbacks_chain(callback_stream)
119
- }
120
- nil
121
- }
63
+ def handle_new_page
64
+ handle_new_page_view(@context, @initial_snapshot)
65
+ end
122
66
 
123
- if live_update_response
124
- # replace existing page with new snapshot
125
- @page.snapshot = self.snapshot
126
- @page_store[@context.request.page_id] = @page
127
- @snapshot_page_id = @context.request.page_id
128
- set_response(@context, live_update_response)
129
- else
130
- handle_new_page_view(@context)
131
- end
67
+ def handle_existing_page
68
+ @page.snapshot.restore if @context.request.page_id != @snapshot_page_id
132
69
 
133
- end
70
+ p @context.request.fields if $DEBUG
134
71
 
72
+ if @context.request.render?
73
+ handle_render_phase
135
74
  else
136
-
137
- # A page_id was specified in the URL, but there's no page for it in the
138
- # page store. Either the page has timed out, or an invalid page_id was
139
- # specified.
140
- #
141
- # TODO:: Display an "invalid page or page timed out" message, which
142
- # forwards to /app/session-id
143
-
144
- raise "Not yet implemented"
145
-
75
+ handle_callback_phase
146
76
  end
147
77
  end
148
78
 
149
- def current_context
150
- @context
79
+ def handle_invalid_page
80
+ # TODO:: Display an "invalid page or page timed out" message, which
81
+ # forwards to /app/session-id
82
+ raise "Not yet implemented"
151
83
  end
152
84
 
153
- def current_callbacks
154
- @page.callbacks
85
+ def handle_render_phase
86
+ # No action/inputs were specified -> render page
87
+ #
88
+ # 1. Reset the action/input fields (as they are regenerated in the
89
+ # rendering process).
90
+ # 2. Render the page (respond).
91
+ # 3. Store the page back into the store
92
+
93
+ @page = create_page(@page.snapshot) # remove all action/input handlers
94
+ respond(@context, @page.callbacks) # render
95
+ @page_store[@context.request.page_id] = @page # store
155
96
  end
156
97
 
157
- # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
158
- # :section: Properties
159
- # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
98
+ def handle_callback_phase
99
+ # Actions/inputs were specified.
100
+ #
101
+ # We process the request and invoke actions/inputs. Then we generate a
102
+ # new page view.
160
103
 
161
- attr_accessor :properties
104
+ callback_stream = Wee::CallbackStream.new(@page.callbacks, @context.request.fields)
105
+ send_response = invoke_callbacks(callback_stream)
162
106
 
163
- # Returns an "owned" property for the given +klass+.
107
+ post_callbacks_hook()
164
108
 
165
- def get_property(prop, klass)
166
- if @properties
167
- @properties.fetch(klass, {})[prop]
109
+ if send_response
110
+ # replace existing page with new snapshot
111
+ @page.snapshot = self.snapshot
112
+ @page_store[@context.request.page_id] = @page
113
+ @snapshot_page_id = @context.request.page_id
114
+
115
+ # and send response
116
+ set_response(@context, send_response)
168
117
  else
169
- nil
118
+ handle_new_page_view(@context)
170
119
  end
171
120
  end
172
121
 
173
- private
122
+ # This method triggers two tree traversals of process_callbacks on the root
123
+ # component. First, all input callbacks are invoked, then in the second
124
+ # traversal, the first found action callback is invoked (there's only ever
125
+ # one per request) and then the traversal is stopped
126
+ #
127
+ # NOTE: Input callbacks should never call other components!
128
+ #
129
+ # Returns nil or send_response in case of a premature response.
130
+
131
+ def invoke_callbacks(callback_stream)
132
+ if callback_stream.all_of_type(:action).size > 1
133
+ raise "Not allowed to specify more than one action callback"
134
+ end
135
+
136
+ send_response = catch(:wee_send_response) {
137
+ catch(:wee_back_to_session) {
138
+ # invoke input callbacks
139
+ @root_component.process_callbacks_chain {|this|
140
+ callback_stream.with_callbacks_for(this, :input) { |callback, value|
141
+ callback.call(value)
142
+ }
143
+ }
144
+
145
+ # invoke first found action callback. only the first action callback is invoked.
146
+ @root_component.process_callbacks_chain {|this|
147
+ callback_stream.with_callbacks_for(this, :action) { |callback, value|
148
+ callback.call
149
+ throw :wee_back_to_session
150
+ }
151
+ }
152
+ }
153
+ nil
154
+ }
155
+ end
174
156
 
175
157
  def handle_new_page_view(context, snapshot=nil)
176
158
  new_page_id = @idgen.next.to_s
177
159
  new_page = create_page(snapshot || self.snapshot())
178
160
  @page_store[new_page_id] = new_page
179
161
  @snapshot_page_id = new_page_id
180
- redirect_url = context.request.build_url(context.request.request_handler_id, new_page_id)
162
+ redirect_url = context.request.build_url(:page_id => new_page_id)
181
163
  set_response(context, Wee::RedirectResponse.new(redirect_url))
182
164
  end
183
165
 
184
- def set_response(context, response)
185
- context.response = response
186
- end
187
-
188
166
  def respond(context, callbacks)
167
+ pre_respond_hook
189
168
  set_response(context, Wee::GenericResponse.new('text/html', ''))
190
169
 
191
170
  rctx = Wee::RenderingContext.new(context.request, context.response, callbacks, Wee::HtmlWriter.new(context.response.content))
192
171
  @root_component.do_render_chain(rctx)
193
172
  end
194
173
 
174
+ def pre_respond_hook
175
+ end
176
+
177
+ def post_callbacks_hook
178
+ end
179
+
180
+ # Take a snapshot of the root component and return it.
181
+
182
+ def snapshot
183
+ @root_component.backtrack_state_chain(snap = Wee::Snapshot.new)
184
+ return snap.freeze
185
+ end
186
+
187
+ # Return a new Wee::Page object with the given snapshot assigned.
188
+
189
+ def create_page(snapshot)
190
+ idgen = Wee::SimpleIdGenerator.new
191
+ page = Wee::Page.new(snapshot, Wee::CallbackRegistry.new(idgen))
192
+ end
193
+
195
194
  end
@@ -5,10 +5,38 @@ require 'wee/request'
5
5
  class Test_Request < Test::Unit::TestCase
6
6
  def test_parse
7
7
  d = Wee::Request::DELIM
8
- req = Wee::Request.new('/app', "/app/...#{d}req_handler_id/page_id", nil, nil, nil)
8
+ req = Wee::Request.new('/app', "/app/info#{d}req_handler_id/page_id", nil, nil, nil)
9
+ assert_equal 'info', req.info
9
10
  assert_equal 'req_handler_id', req.request_handler_id
10
11
  assert_equal 'page_id', req.page_id
11
- assert_equal "/app/#{d}a/b?c", req.build_url('a', 'b', 'c')
12
- assert_equal "/app/#{d}req_handler_id/b", req.build_url('req_handler_id', 'b')
12
+ end
13
+
14
+ def test_fields
15
+ fields = {
16
+ 'a' => 1,
17
+ 'b' => 2,
18
+ 'a.x' => 3,
19
+ 'a.y' => 4,
20
+ }
21
+
22
+ parsed = {
23
+ 'a' => {nil => 1, 'x' => 3, 'y' => 4},
24
+ 'b' => 2
25
+ }
26
+
27
+ req = Wee::Request.new('/app', "/app", nil, fields, nil)
28
+ assert_equal parsed, req.fields
29
+ end
30
+
31
+ def test_build_url
32
+ d = Wee::Request::DELIM
33
+ req = Wee::Request.new('/app', "/app/info#{d}req_handler_id/page_id", nil, nil, nil)
34
+
35
+ assert_equal "/app/info#{d}req_handler_id/page_id?c", req.build_url(:callback_id => 'c')
36
+
37
+ assert_equal "/app/info#{d}a/b?c", req.build_url(:request_handler_id => 'a', :page_id => 'b', :callback_id => 'c')
38
+ assert_equal "/app/info#{d}req_handler_id/b", req.build_url(:request_handler_id => 'req_handler_id', :page_id => 'b')
39
+
40
+ assert_equal "/app/info", req.build_url(:request_handler_id => nil, :page_id => nil)
13
41
  end
14
42
  end
metadata CHANGED
@@ -1,10 +1,10 @@
1
1
  --- !ruby/object:Gem::Specification
2
- rubygems_version: 0.8.4
2
+ rubygems_version: 0.8.6
3
3
  specification_version: 1
4
4
  name: wee
5
5
  version: !ruby/object:Gem::Version
6
- version: 0.7.0
7
- date: 2005-02-01
6
+ version: 0.8.0
7
+ date: 2005-04-04
8
8
  summary: Wee is a framework for building highly dynamic web applications.
9
9
  require_paths:
10
10
  - lib
@@ -33,8 +33,8 @@ files:
33
33
  - bin
34
34
  - benchmark
35
35
  - examples
36
- - wee.gemspec
37
36
  - Rakefile
37
+ - wee.gemspec
38
38
  - TODO
39
39
  - INSTALL
40
40
  - ChangeLog
@@ -44,8 +44,8 @@ files:
44
44
  - test/components
45
45
  - test/stressed_application.rb
46
46
  - test/test_html_canvas.rb
47
- - test/test_html_writer.rb
48
47
  - test/stress_and_measure.rb
48
+ - test/test_html_writer.rb
49
49
  - test/test_component.rb
50
50
  - test/stress.rb
51
51
  - test/test_request.rb
@@ -80,8 +80,8 @@ files:
80
80
  - doc/rdoc/files/lib/wee/pageless
81
81
  - doc/rdoc/files/lib/wee/renderer
82
82
  - doc/rdoc/files/lib/wee/continuation
83
- - doc/rdoc/files/lib/wee/adaptors
84
83
  - doc/rdoc/files/lib/wee/rendering
84
+ - doc/rdoc/files/lib/wee/adaptors
85
85
  - doc/rdoc/files/lib/wee/skeleton
86
86
  - doc/rdoc/files/lib/wee/idgen
87
87
  - doc/rdoc/files/lib/wee/databases
@@ -121,32 +121,32 @@ files:
121
121
  - doc/rdoc/files/lib/wee/core/callback_rb.html
122
122
  - doc/rdoc/files/lib/wee/core/snapshot_rb.html
123
123
  - doc/rdoc/files/lib/wee/core/component_rb.html
124
- - doc/rdoc/files/lib/wee/core/presenter_rb.html
125
124
  - doc/rdoc/files/lib/wee/core/decoration_rb.html
125
+ - doc/rdoc/files/lib/wee/core/presenter_rb.html
126
126
  - doc/rdoc/files/lib/wee/pageless/application_rb.html
127
127
  - doc/rdoc/files/lib/wee/pageless/session_rb.html
128
128
  - doc/rdoc/files/lib/wee/pageless/request_rb.html
129
129
  - doc/rdoc/files/lib/wee/renderer/html
130
- - doc/rdoc/files/lib/wee/renderer/html/canvas_rb.html
131
130
  - doc/rdoc/files/lib/wee/renderer/html/brushes_rb.html
131
+ - doc/rdoc/files/lib/wee/renderer/html/canvas_rb.html
132
132
  - doc/rdoc/files/lib/wee/renderer/html/writer_rb.html
133
133
  - doc/rdoc/files/lib/wee/continuation/core
134
134
  - doc/rdoc/files/lib/wee/continuation/session_rb.html
135
135
  - doc/rdoc/files/lib/wee/continuation/core/component_rb.html
136
- - doc/rdoc/files/lib/wee/adaptors/webrick_rb.html
137
136
  - doc/rdoc/files/lib/wee/rendering/html
138
137
  - doc/rdoc/files/lib/wee/rendering/html/brushes_rb.html
139
138
  - doc/rdoc/files/lib/wee/rendering/html/canvas_rb.html
140
139
  - doc/rdoc/files/lib/wee/rendering/html/writer_rb.html
140
+ - doc/rdoc/files/lib/wee/adaptors/webrick_rb.html
141
141
  - doc/rdoc/files/lib/wee/skeleton/og
142
142
  - doc/rdoc/files/lib/wee/skeleton/simple
143
143
  - doc/rdoc/files/lib/wee/skeleton/og/models
144
- - doc/rdoc/files/lib/wee/skeleton/og/conf
145
144
  - doc/rdoc/files/lib/wee/skeleton/og/components
145
+ - doc/rdoc/files/lib/wee/skeleton/og/conf
146
146
  - doc/rdoc/files/lib/wee/skeleton/og/run_rb.html
147
147
  - doc/rdoc/files/lib/wee/skeleton/og/models/recipe_rb.html
148
- - doc/rdoc/files/lib/wee/skeleton/og/conf/db_rb.html
149
148
  - doc/rdoc/files/lib/wee/skeleton/og/components/main_rb.html
149
+ - doc/rdoc/files/lib/wee/skeleton/og/conf/db_rb.html
150
150
  - doc/rdoc/files/lib/wee/skeleton/simple/components
151
151
  - doc/rdoc/files/lib/wee/skeleton/simple/run_rb.html
152
152
  - doc/rdoc/files/lib/wee/skeleton/simple/components/main_rb.html
@@ -191,22 +191,22 @@ files:
191
191
  - doc/rdoc/classes/Wee/PageDecoration.html
192
192
  - doc/rdoc/classes/Wee/RequestHandler.html
193
193
  - doc/rdoc/classes/Wee/Decoration.html
194
- - doc/rdoc/classes/Wee/WEBrickAdaptor.html
194
+ - doc/rdoc/classes/Wee/AnswerDecoration.html
195
195
  - doc/rdoc/classes/Wee/MessageBox.html
196
196
  - doc/rdoc/classes/Wee/Response.html
197
197
  - doc/rdoc/classes/Wee/Snapshot.html
198
- - doc/rdoc/classes/Wee/CallbackStream.html
199
198
  - doc/rdoc/classes/Wee/HtmlWriter.html
200
- - doc/rdoc/classes/Wee/PagelessApplication.html
201
- - doc/rdoc/classes/Wee/AnswerDecoration.html
199
+ - doc/rdoc/classes/Wee/WEBrickAdaptor.html
200
+ - doc/rdoc/classes/Wee/PagelessRequest.html
201
+ - doc/rdoc/classes/Wee/CallbackStream.html
202
202
  - doc/rdoc/classes/Wee/StateRegistry.html
203
203
  - doc/rdoc/classes/Wee/Delegate.html
204
204
  - doc/rdoc/classes/Wee/ValueHolder.html
205
- - doc/rdoc/classes/Wee/FormDecoration.html
206
205
  - doc/rdoc/classes/Wee/Canvas.html
207
- - doc/rdoc/classes/Wee/PagelessRequest.html
208
- - doc/rdoc/classes/Wee/StateHolder.html
206
+ - doc/rdoc/classes/Wee/FormDecoration.html
209
207
  - doc/rdoc/classes/Wee/RedirectResponse.html
208
+ - doc/rdoc/classes/Wee/StateHolder.html
209
+ - doc/rdoc/classes/Wee/PagelessApplication.html
210
210
  - doc/rdoc/classes/Wee/RenderingContext.html
211
211
  - doc/rdoc/classes/Wee/Brush.html
212
212
  - doc/rdoc/classes/Wee/Context.html
@@ -221,8 +221,8 @@ files:
221
221
  - doc/rdoc/classes/Wee/Utils.html
222
222
  - doc/rdoc/classes/Wee/Component.html
223
223
  - doc/rdoc/classes/Wee/Application.html
224
- - doc/rdoc/classes/Wee/PagelessSession.html
225
224
  - doc/rdoc/classes/Wee/Presenter.html
225
+ - doc/rdoc/classes/Wee/PagelessSession.html
226
226
  - doc/rdoc/classes/Wee/ErrorResponse.html
227
227
  - doc/rdoc/classes/Wee/Md5IdGenerator.html
228
228
  - doc/rdoc/classes/Wee/Utils/LRUCache.html
@@ -298,6 +298,7 @@ files:
298
298
  - lib/wee/utils.rb
299
299
  - lib/wee/pageless.rb
300
300
  - lib/wee/template.rb
301
+ - lib/wee/abstractsession.rb
301
302
  - lib/wee/continuation.rb
302
303
  - lib/wee/page.rb
303
304
  - lib/wee/skeleton/og
@@ -322,14 +323,14 @@ files:
322
323
  - lib/wee/idgen/md5.rb
323
324
  - lib/wee/databases/og
324
325
  - lib/wee/databases/og.rb
326
+ - lib/wee/databases/og/old_scaffolder.rb
325
327
  - lib/wee/databases/og/application.rb
326
328
  - lib/wee/databases/og/session.rb
327
- - lib/wee/databases/og/old_scaffolder.rb
328
329
  - lib/wee/databases/og/scaffolder.rb
329
330
  - lib/wee/core/component.rb
330
331
  - lib/wee/core/snapshot.rb
331
- - lib/wee/core/presenter.rb
332
332
  - lib/wee/core/decoration.rb
333
+ - lib/wee/core/presenter.rb
333
334
  - lib/wee/core/valueholder.rb
334
335
  - lib/wee/core/callback.rb
335
336
  - lib/wee/utils/autoreload.rb
@@ -339,12 +340,13 @@ files:
339
340
  - lib/wee/pageless/session.rb
340
341
  - lib/wee/pageless/request.rb
341
342
  - lib/wee/renderer/html
342
- - lib/wee/renderer/html/canvas.rb
343
343
  - lib/wee/renderer/html/brushes.rb
344
+ - lib/wee/renderer/html/canvas.rb
344
345
  - lib/wee/renderer/html/writer.rb
345
346
  - lib/wee/continuation/core
346
347
  - lib/wee/continuation/session.rb
347
348
  - lib/wee/continuation/core/component.rb
349
+ - lib/wee/adaptors/fastcgi.rb
348
350
  - lib/wee/adaptors/webrick.rb
349
351
  - lib/cache/cache.rb
350
352
  - bin/wee
@@ -358,19 +360,22 @@ files:
358
360
  - benchmark/Centrino1300/result.2000.counter.render
359
361
  - benchmark/Centrino1300/result.2000.filehandler
360
362
  - benchmark/Centrino600/result.2000.counter.action
361
- - benchmark/Centrino600/result.2000.filehandler
362
363
  - benchmark/Centrino600/result.2000.counter.render
364
+ - benchmark/Centrino600/result.2000.filehandler
365
+ - examples/ajax
363
366
  - examples/og-test.rb
364
367
  - examples/draw.rb
365
368
  - examples/hw.rb
366
369
  - examples/test.rb
367
370
  - examples/live-update.rb
368
- - examples/cc.rb
369
371
  - examples/window.rb
372
+ - examples/cc.rb
370
373
  - examples/ObjectSpaceBrowser.rb
371
- - examples/calendar.rb
372
374
  - examples/calculator.rb
375
+ - examples/calendar.rb
373
376
  - examples/example.rb
377
+ - examples/ajax/ajax.rb
378
+ - examples/ajax/ajax.js
374
379
  test_files: []
375
380
  rdoc_options: []
376
381
  extra_rdoc_files: []