wee 0.7.0 → 0.8.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.
- data/ChangeLog +96 -0
- data/README +2 -5
- data/examples/ObjectSpaceBrowser.rb +24 -42
- data/examples/ajax/ajax.js +444 -0
- data/examples/ajax/ajax.rb +31 -0
- data/examples/calculator.rb +1 -3
- data/examples/cc.rb +9 -29
- data/examples/live-update.rb +1 -1
- data/examples/test.rb +2 -2
- data/examples/window.rb +1 -1
- data/lib/wee.rb +1 -1
- data/lib/wee/abstractsession.rb +96 -0
- data/lib/wee/adaptors/fastcgi.rb +76 -0
- data/lib/wee/adaptors/webrick.rb +3 -3
- data/lib/wee/application.rb +7 -4
- data/lib/wee/core/callback.rb +2 -0
- data/lib/wee/core/component.rb +46 -24
- data/lib/wee/core/decoration.rb +5 -5
- data/lib/wee/core/presenter.rb +43 -27
- data/lib/wee/core/valueholder.rb +1 -1
- data/lib/wee/databases/og/scaffolder.rb +0 -1
- data/lib/wee/pageless/application.rb +8 -4
- data/lib/wee/pageless/request.rb +17 -5
- data/lib/wee/pageless/session.rb +38 -52
- data/lib/wee/renderer/html/brushes.rb +7 -1
- data/lib/wee/renderer/html/canvas.rb +1 -1
- data/lib/wee/request.rb +68 -7
- data/lib/wee/response.rb +2 -1
- data/lib/wee/session.rb +128 -129
- data/test/test_request.rb +31 -3
- metadata +30 -25
data/lib/wee/core/decoration.rb
CHANGED
@@ -44,8 +44,8 @@ class Wee::Decoration < Wee::Presenter
|
|
44
44
|
|
45
45
|
# Forwards method call to the next decoration in the chain.
|
46
46
|
|
47
|
-
def process_callbacks(
|
48
|
-
@owner.process_callbacks(
|
47
|
+
def process_callbacks(&block)
|
48
|
+
@owner.process_callbacks(&block)
|
49
49
|
end
|
50
50
|
|
51
51
|
# Forwards method call to the next decoration in the chain.
|
@@ -93,8 +93,8 @@ class Wee::Delegate < Wee::Decoration
|
|
93
93
|
# Forwards method to the corresponding top-level *chain* method of the
|
94
94
|
# _delegate_ component.
|
95
95
|
|
96
|
-
def process_callbacks(
|
97
|
-
@delegate.process_callbacks_chain(
|
96
|
+
def process_callbacks(&block)
|
97
|
+
@delegate.process_callbacks_chain(&block)
|
98
98
|
end
|
99
99
|
|
100
100
|
# Forwards method to the corresponding top-level *chain* method of the
|
@@ -128,7 +128,7 @@ class Wee::AnswerDecoration < Wee::Decoration
|
|
128
128
|
|
129
129
|
attr_accessor :on_answer
|
130
130
|
|
131
|
-
def process_callbacks(
|
131
|
+
def process_callbacks(&block)
|
132
132
|
args = catch(:wee_answer) { super; nil }
|
133
133
|
if args != nil
|
134
134
|
# return to the calling component
|
data/lib/wee/core/presenter.rb
CHANGED
@@ -75,30 +75,12 @@ class Wee::Presenter
|
|
75
75
|
|
76
76
|
# Process all callbacks specified for this presenter.
|
77
77
|
#
|
78
|
-
#
|
79
|
-
#
|
80
|
-
#
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
# [+callback_stream+]
|
85
|
-
# An object of class CallbackStream
|
86
|
-
|
87
|
-
def process_callbacks(callback_stream) # :yields:
|
88
|
-
# invoke input callbacks
|
89
|
-
callback_stream.with_callbacks_for(self, :input) { |callback, value|
|
90
|
-
callback.call(value)
|
91
|
-
}
|
92
|
-
|
93
|
-
# enable subclasses to add behaviour, e.g. a Component class will invoke
|
94
|
-
# process_callbacks_chain for each child in the block.
|
95
|
-
yield if block_given?
|
96
|
-
|
97
|
-
# invoke action callback. only the first action callback is invoked.
|
98
|
-
callback_stream.with_callbacks_for(self, :action) { |callback, value|
|
99
|
-
callback.call
|
100
|
-
throw :wee_back_to_session
|
101
|
-
}
|
78
|
+
# [+block+]
|
79
|
+
# Specifies the action to be taken (e.g. whether to invoke input or action
|
80
|
+
# callbacks).
|
81
|
+
|
82
|
+
def process_callbacks(&block)
|
83
|
+
block.call(self)
|
102
84
|
end
|
103
85
|
|
104
86
|
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
@@ -129,17 +111,51 @@ class Wee::Presenter
|
|
129
111
|
Wee::Session.current
|
130
112
|
end
|
131
113
|
|
114
|
+
# Send a premature response.
|
115
|
+
|
116
|
+
protected
|
117
|
+
|
118
|
+
def send_response(response)
|
119
|
+
throw :wee_send_response, response
|
120
|
+
end
|
121
|
+
|
122
|
+
# Call the block inside a rendering environment, then send the response prematurely.
|
123
|
+
|
124
|
+
def send_render_response(&block)
|
125
|
+
# Generate a response
|
126
|
+
response = Wee::GenericResponse.new('text/html', '')
|
127
|
+
|
128
|
+
# Get the current context we are in
|
129
|
+
context = session.current_context
|
130
|
+
|
131
|
+
# A rendering context is needed to use 'r' (if you want, you can simply
|
132
|
+
# omit this and just return the response with some html/xml filled in.
|
133
|
+
rendering_context = Wee::RenderingContext.new(
|
134
|
+
context.request,
|
135
|
+
context.response,
|
136
|
+
session.current_callbacks,
|
137
|
+
Wee::HtmlWriter.new(response.content))
|
138
|
+
|
139
|
+
with_renderer_for(rendering_context, &block)
|
140
|
+
|
141
|
+
send_response(response)
|
142
|
+
end
|
143
|
+
|
144
|
+
|
132
145
|
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
133
146
|
# :section: Properties
|
134
147
|
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
135
148
|
|
136
|
-
|
149
|
+
public
|
150
|
+
|
151
|
+
def properties() @__properties end
|
152
|
+
def properties=(props) @__properties = props end
|
137
153
|
|
138
154
|
# Returns an "owned" property.
|
139
155
|
|
140
156
|
def get_property(prop)
|
141
|
-
if
|
142
|
-
|
157
|
+
if self.properties
|
158
|
+
self.properties[prop]
|
143
159
|
else
|
144
160
|
nil
|
145
161
|
end
|
data/lib/wee/core/valueholder.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# Implements a value holder. Useful for backtracking the reference assigned to
|
2
2
|
# an instance variable (not the object itself!). An example where this is used
|
3
|
-
# is the <tt>@
|
3
|
+
# is the <tt>@__decoration</tt> attribute of class Wee::Component.
|
4
4
|
|
5
5
|
class Wee::ValueHolder
|
6
6
|
attr_accessor :value
|
@@ -1,9 +1,13 @@
|
|
1
|
+
require 'cgi'
|
2
|
+
|
1
3
|
class Wee::PagelessApplication < Wee::Application
|
2
4
|
def request_handler_expired(context)
|
3
|
-
context.response = Wee::RedirectResponse.new(context.request.
|
4
|
-
|
5
|
-
|
6
|
-
|
5
|
+
context.response = Wee::RedirectResponse.new(context.request.build_url(
|
6
|
+
:request_handler_id => nil,
|
7
|
+
:page_id => nil))
|
8
|
+
|
9
|
+
cookie = CGI::Cookie.new('SID', '')
|
10
|
+
cookie.expires = Time.at(0)
|
7
11
|
context.response.cookies << cookie
|
8
12
|
end
|
9
13
|
end
|
data/lib/wee/pageless/request.rb
CHANGED
@@ -1,15 +1,27 @@
|
|
1
1
|
class Wee::PagelessRequest < Wee::Request
|
2
|
+
private
|
2
3
|
|
3
|
-
def
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
4
|
+
def pageless?
|
5
|
+
true
|
6
|
+
end
|
7
|
+
|
8
|
+
def make_request_path(request_handler_id, page_id)
|
9
|
+
""
|
8
10
|
end
|
9
11
|
|
10
12
|
def parse_path
|
11
13
|
if sid = @cookies.find {|c| c.name == 'SID'}
|
12
14
|
@request_handler_id = sid.value
|
13
15
|
end
|
16
|
+
|
17
|
+
full_app_path = @path
|
18
|
+
|
19
|
+
if full_app_path == @app_path
|
20
|
+
@info = nil
|
21
|
+
elsif full_app_path[0, @app_path.size] == @app_path and full_app_path[@app_path.size] == ?/
|
22
|
+
@info = full_app_path[@app_path.size+1..-1]
|
23
|
+
else
|
24
|
+
raise "dispatched to wrong handler"
|
25
|
+
end
|
14
26
|
end
|
15
27
|
end
|
data/lib/wee/pageless/session.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'thread'
|
2
|
+
require 'cgi'
|
2
3
|
|
3
4
|
# A session class, which does not have a page-store and as such cannot
|
4
5
|
# backtrack.
|
@@ -10,77 +11,62 @@ class Wee::PagelessSession < Wee::Session
|
|
10
11
|
attr_accessor :callbacks
|
11
12
|
alias current_callbacks callbacks
|
12
13
|
|
13
|
-
def
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
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
|
14
|
+
def setup(&block)
|
15
|
+
with_session do
|
16
|
+
block.call(self) if block
|
17
|
+
raise ArgumentError, "No root component specified" if @root_component.nil?
|
18
|
+
end
|
26
19
|
end
|
27
20
|
|
28
|
-
|
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
|
21
|
+
# The main routine where the request is processed.
|
39
22
|
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
else
|
23
|
+
def process_request
|
24
|
+
handle_existing_page
|
25
|
+
end
|
45
26
|
|
46
|
-
|
47
|
-
|
48
|
-
# We process the request and invoke actions/inputs. Then we generate a
|
49
|
-
# new page view.
|
27
|
+
def handle_existing_page
|
28
|
+
p @context.request.fields if $DEBUG
|
50
29
|
|
51
|
-
|
30
|
+
if @context.request.render?
|
31
|
+
handle_render_phase
|
32
|
+
else
|
33
|
+
handle_callback_phase
|
34
|
+
end
|
35
|
+
end
|
52
36
|
|
53
|
-
|
54
|
-
|
55
|
-
|
37
|
+
def handle_render_phase
|
38
|
+
new_callbacks = Wee::CallbackRegistry.new(Wee::SimpleIdGenerator.new)
|
39
|
+
respond(@context, new_callbacks) # render
|
40
|
+
self.callbacks = new_callbacks
|
41
|
+
end
|
56
42
|
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
}
|
43
|
+
def handle_callback_phase
|
44
|
+
# Actions/inputs were specified.
|
45
|
+
#
|
46
|
+
# We process the request and invoke actions/inputs. Then we generate a
|
47
|
+
# new page view.
|
63
48
|
|
64
|
-
|
65
|
-
|
66
|
-
else
|
67
|
-
handle_new_page_view(@context)
|
68
|
-
end
|
49
|
+
callback_stream = Wee::CallbackStream.new(self.callbacks, @context.request.fields)
|
50
|
+
send_response = invoke_callbacks(callback_stream)
|
69
51
|
|
70
|
-
|
52
|
+
post_callbacks_hook()
|
71
53
|
|
54
|
+
if send_response
|
55
|
+
set_response(@context, send_response) # @context.response = send_response
|
56
|
+
else
|
57
|
+
handle_new_page_view(@context)
|
58
|
+
end
|
72
59
|
end
|
73
60
|
|
74
61
|
private
|
75
62
|
|
76
63
|
def handle_new_page_view(context)
|
77
|
-
redirect_url = context.request.build_url
|
64
|
+
redirect_url = context.request.build_url
|
78
65
|
set_response(context, Wee::RedirectResponse.new(redirect_url))
|
79
66
|
end
|
80
67
|
|
81
68
|
def set_response(context, response)
|
82
|
-
|
83
|
-
response.cookies << WEBrick::Cookie.new('SID', self.id)
|
69
|
+
response.cookies << CGI::Cookie.new('SID', self.id)
|
84
70
|
response.header.delete('Expire')
|
85
71
|
response.header['Pragma'] = 'No-Cache'
|
86
72
|
super
|
@@ -151,6 +151,12 @@ class Brush::GenericTagBrush < Brush
|
|
151
151
|
onclick("javascript: document.location.href='#{ url }';")
|
152
152
|
end
|
153
153
|
|
154
|
+
def onclick_update(update_id, symbol=nil, *args, &block)
|
155
|
+
raise ArgumentError if symbol and block
|
156
|
+
url = @canvas.url_for_callback(to_callback(symbol, args, block))
|
157
|
+
onclick("javascript: new Ajax.Updater('#{ update_id }', '#{ url }', {method:'get'});")
|
158
|
+
end
|
159
|
+
|
154
160
|
# This method construct the css-class attribute by looking up the property
|
155
161
|
# from the current component.
|
156
162
|
|
@@ -455,7 +461,7 @@ class Brush::FormTag < Brush::GenericTagBrush
|
|
455
461
|
unless @attributes.has_key?('action')
|
456
462
|
req = @canvas.rendering_context.request
|
457
463
|
# TODO?
|
458
|
-
@attributes['action'] = req.build_url
|
464
|
+
@attributes['action'] = req.build_url
|
459
465
|
end
|
460
466
|
super
|
461
467
|
end
|
data/lib/wee/request.rb
CHANGED
@@ -6,12 +6,16 @@
|
|
6
6
|
|
7
7
|
class Wee::Request
|
8
8
|
|
9
|
-
DELIM = '
|
9
|
+
DELIM = '/___/'
|
10
10
|
|
11
11
|
attr_accessor :request_handler_id
|
12
12
|
attr_reader :page_id, :fields, :cookies
|
13
13
|
|
14
|
+
# The part of the URL that is user-defineable
|
15
|
+
attr_accessor :info
|
16
|
+
|
14
17
|
def initialize(app_path, path, headers, fields, cookies)
|
18
|
+
raise ArgumentError if app_path[-1] == ?/
|
15
19
|
@app_path, @path, @headers, @cookies = app_path, path, headers, cookies
|
16
20
|
parse_fields(fields)
|
17
21
|
parse_path
|
@@ -21,17 +25,51 @@ class Wee::Request
|
|
21
25
|
@app_path
|
22
26
|
end
|
23
27
|
|
24
|
-
|
28
|
+
# Is this an action request?
|
29
|
+
def action?
|
30
|
+
not render?
|
31
|
+
end
|
32
|
+
|
33
|
+
# Is this a render request?
|
34
|
+
def render?
|
35
|
+
self.fields.empty?
|
36
|
+
end
|
37
|
+
|
38
|
+
def build_url(hash={})
|
39
|
+
default = {
|
40
|
+
:request_handler_id => self.request_handler_id,
|
41
|
+
:page_id => self.page_id,
|
42
|
+
:info => self.info
|
43
|
+
}
|
44
|
+
hash = default.update(hash)
|
45
|
+
|
46
|
+
request_handler_id = hash[:request_handler_id]
|
47
|
+
page_id = hash[:page_id]
|
48
|
+
callback_id = hash[:callback_id]
|
49
|
+
info = hash[:info]
|
50
|
+
|
25
51
|
raise ArgumentError if request_handler_id.nil? and not page_id.nil?
|
52
|
+
if not pageless?
|
53
|
+
raise ArgumentError if page_id.nil? and not callback_id.nil?
|
54
|
+
end
|
26
55
|
|
27
|
-
|
56
|
+
# build request path, e.g. /___/req-id/page-id
|
57
|
+
req_path = make_request_path(request_handler_id, page_id)
|
28
58
|
|
29
|
-
|
59
|
+
# build the whole url
|
60
|
+
url = ""
|
30
61
|
url << @app_path
|
31
|
-
|
32
|
-
|
33
|
-
|
62
|
+
|
63
|
+
raise if url[-1] == ?/ # sanity check
|
64
|
+
|
65
|
+
if info
|
66
|
+
url << '/'
|
67
|
+
url << info
|
34
68
|
end
|
69
|
+
url << req_path
|
70
|
+
|
71
|
+
url << '/' if info.nil? and req_path.empty?
|
72
|
+
|
35
73
|
url << ('?' + callback_id) if callback_id
|
36
74
|
|
37
75
|
return url
|
@@ -39,6 +77,20 @@ class Wee::Request
|
|
39
77
|
|
40
78
|
private
|
41
79
|
|
80
|
+
def pageless?
|
81
|
+
false
|
82
|
+
end
|
83
|
+
|
84
|
+
def make_request_path(request_handler_id, page_id)
|
85
|
+
arr = [request_handler_id, page_id].compact
|
86
|
+
req_path =
|
87
|
+
if arr.empty?
|
88
|
+
""
|
89
|
+
else
|
90
|
+
DELIM + arr.join('/')
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
42
94
|
def parse_fields(fields)
|
43
95
|
fields ||= Hash.new
|
44
96
|
@fields = Hash.new
|
@@ -62,6 +114,15 @@ class Wee::Request
|
|
62
114
|
|
63
115
|
def parse_path
|
64
116
|
full_app_path, req_path = @path.split(DELIM, 2)
|
117
|
+
|
118
|
+
if full_app_path == @app_path
|
119
|
+
@info = nil
|
120
|
+
elsif full_app_path[0, @app_path.size] == @app_path and full_app_path[@app_path.size] == ?/
|
121
|
+
@info = full_app_path[@app_path.size+1..-1]
|
122
|
+
else
|
123
|
+
raise "dispatched to wrong handler"
|
124
|
+
end
|
125
|
+
|
65
126
|
@request_handler_id = @page_id = nil
|
66
127
|
@request_handler_id, @page_id = req_path.split('/', 2) if req_path
|
67
128
|
end
|