wee 0.7.0 → 0.8.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'wee'
|
3
|
+
require 'wee/adaptors/webrick'
|
4
|
+
require 'wee/utils'
|
5
|
+
|
6
|
+
class AjaxTest < Wee::Component
|
7
|
+
|
8
|
+
def render
|
9
|
+
r.html {
|
10
|
+
r.head {
|
11
|
+
r.title("Ajax+Wee")
|
12
|
+
r.javascript.src('/js/ajax.js')
|
13
|
+
}
|
14
|
+
r.body {
|
15
|
+
r.h1 "Hello World from Wee!"
|
16
|
+
r.anchor.id('tag').onclick_update('tag', :update).with('Halllllllooooo')
|
17
|
+
}
|
18
|
+
}
|
19
|
+
end
|
20
|
+
|
21
|
+
def update
|
22
|
+
send_render_response {
|
23
|
+
r.text "Live-updates works! This is no. #{ @live_updates += 1}"
|
24
|
+
}
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
Wee::WEBrickAdaptor.
|
29
|
+
register('/app' => Wee::Utils.app_for(AjaxTest)).
|
30
|
+
mount('/js', WEBrick::HTTPServlet::FileHandler, '.').
|
31
|
+
start
|
data/examples/calculator.rb
CHANGED
@@ -60,9 +60,7 @@ if __FILE__ == $0
|
|
60
60
|
require 'wee/utils'
|
61
61
|
|
62
62
|
app = Wee::Utils.app_for {
|
63
|
-
|
64
|
-
comp.add_decoration(Wee::PageDecoration.new('RPN Calculator'))
|
65
|
-
comp
|
63
|
+
RpnCalculator.new.add_decoration(Wee::PageDecoration.new('RPN Calculator'))
|
66
64
|
}
|
67
65
|
|
68
66
|
Wee::WEBrickAdaptor.register('/calc' => app).start
|
data/examples/cc.rb
CHANGED
@@ -1,8 +1,6 @@
|
|
1
1
|
$LOAD_PATH.unshift << "../lib"
|
2
2
|
require 'wee'
|
3
|
-
require 'wee/
|
4
|
-
require 'wee/utils/cache'
|
5
|
-
|
3
|
+
require 'wee/continuation'
|
6
4
|
|
7
5
|
class MessageBox < Wee::Component
|
8
6
|
def initialize(text)
|
@@ -14,9 +12,9 @@ class MessageBox < Wee::Component
|
|
14
12
|
r.break
|
15
13
|
r.text(@text)
|
16
14
|
r.form do
|
17
|
-
r.submit_button.value('OK').
|
15
|
+
r.submit_button.value('OK').callback(:answer, true)
|
18
16
|
r.space
|
19
|
-
r.submit_button.value('Cancel').
|
17
|
+
r.submit_button.value('Cancel').callback(:answer, false)
|
20
18
|
end
|
21
19
|
r.break
|
22
20
|
end
|
@@ -61,34 +59,16 @@ class MainPage < Wee::Component
|
|
61
59
|
r.page.title("Draw Test").with do
|
62
60
|
|
63
61
|
r.break
|
64
|
-
r.anchor.
|
65
|
-
r.render @msgbox
|
62
|
+
r.anchor.callback(:click).with('show')
|
66
63
|
end
|
67
64
|
end
|
68
65
|
|
69
66
|
end
|
70
67
|
|
71
|
-
class MySession < Wee::Session
|
72
|
-
def initialize
|
73
|
-
super do
|
74
|
-
self.root_component = MainPage.new
|
75
|
-
self.page_store = Wee::Utils::LRUCache.new(10) # backtrack up to 10 pages
|
76
|
-
end
|
77
|
-
end
|
78
|
-
end
|
79
|
-
|
80
|
-
class MyApplication < Wee::Application
|
81
|
-
def shutdown
|
82
|
-
end
|
83
|
-
end
|
84
|
-
|
85
68
|
if __FILE__ == $0
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
app.session_store = Wee::Utils::LRUCache.new(100)
|
92
|
-
app.dumpfile = ''
|
93
|
-
}.start
|
69
|
+
require 'wee/adaptors/webrick'
|
70
|
+
require 'wee/utils'
|
71
|
+
|
72
|
+
app = Wee::Utils.app_for(MainPage)
|
73
|
+
Wee::WEBrickAdaptor.register('/app' => app).start
|
94
74
|
end
|
data/examples/live-update.rb
CHANGED
data/examples/test.rb
CHANGED
@@ -1,6 +1,5 @@
|
|
1
1
|
$LOAD_PATH.unshift << "../lib"
|
2
2
|
require 'wee'
|
3
|
-
require 'wee/utils/cache'
|
4
3
|
|
5
4
|
class Counter < Wee::Component
|
6
5
|
def initialize(cnt)
|
@@ -53,11 +52,12 @@ class MySession < Wee::Session
|
|
53
52
|
end
|
54
53
|
|
55
54
|
if __FILE__ == $0
|
55
|
+
require 'wee/utils'
|
56
|
+
require 'wee/adaptors/webrick'
|
56
57
|
app = Wee::Application.new {|app|
|
57
58
|
app.default_request_handler { MySession.new }
|
58
59
|
app.id_generator = Wee::SimpleIdGenerator.new(rand(1_000_000))
|
59
60
|
app.max_request_handlers = 2
|
60
61
|
}
|
61
|
-
require 'wee/adaptors/webrick'
|
62
62
|
Wee::WEBrickAdaptor.register('/app' => app).start
|
63
63
|
end
|
data/examples/window.rb
CHANGED
data/lib/wee.rb
CHANGED
@@ -0,0 +1,96 @@
|
|
1
|
+
require 'thread'
|
2
|
+
|
3
|
+
class Wee::AbstractSession < Wee::RequestHandler
|
4
|
+
|
5
|
+
def self.current
|
6
|
+
Thread.current[:wee_session] || (raise "Not in session")
|
7
|
+
end
|
8
|
+
|
9
|
+
def initialize
|
10
|
+
# to serialize the requests we need a mutex
|
11
|
+
@mutex = Mutex.new
|
12
|
+
|
13
|
+
super()
|
14
|
+
end
|
15
|
+
|
16
|
+
# Returns the current context.
|
17
|
+
|
18
|
+
def current_context
|
19
|
+
@context
|
20
|
+
end
|
21
|
+
|
22
|
+
# Called by Wee::Application to send the session a request.
|
23
|
+
|
24
|
+
def handle_request(context)
|
25
|
+
with_session {
|
26
|
+
@mutex.synchronize {
|
27
|
+
begin
|
28
|
+
@context = context
|
29
|
+
super
|
30
|
+
awake
|
31
|
+
process_request
|
32
|
+
sleep
|
33
|
+
ensure
|
34
|
+
@context = nil # clean up
|
35
|
+
end
|
36
|
+
}
|
37
|
+
}
|
38
|
+
rescue Exception => exn
|
39
|
+
set_response(context, Wee::ErrorResponse.new(exn))
|
40
|
+
end
|
41
|
+
|
42
|
+
protected
|
43
|
+
|
44
|
+
def set_response(context, response)
|
45
|
+
context.response = response
|
46
|
+
end
|
47
|
+
|
48
|
+
protected
|
49
|
+
|
50
|
+
# Is called before process_request is invoked.
|
51
|
+
# Can be used to setup e.g. a database connection.
|
52
|
+
#
|
53
|
+
# OVERWRITE IT (if you like)!
|
54
|
+
|
55
|
+
def awake
|
56
|
+
end
|
57
|
+
|
58
|
+
# Is called after process_request is run.
|
59
|
+
# Can be used to release e.g. a database connection.
|
60
|
+
#
|
61
|
+
# OVERWRITE IT (if you like)!
|
62
|
+
|
63
|
+
def sleep
|
64
|
+
end
|
65
|
+
|
66
|
+
private
|
67
|
+
|
68
|
+
# The block is run inside a session.
|
69
|
+
|
70
|
+
def with_session
|
71
|
+
Thread.current[:wee_session] = self
|
72
|
+
yield
|
73
|
+
ensure
|
74
|
+
Thread.current[:wee_session] = nil
|
75
|
+
end
|
76
|
+
|
77
|
+
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
78
|
+
# :section: Properties
|
79
|
+
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
80
|
+
|
81
|
+
public
|
82
|
+
|
83
|
+
def properties() @__properties end
|
84
|
+
def properties=(props) @__properties = props end
|
85
|
+
|
86
|
+
# Returns an "owned" property for the given +klass+.
|
87
|
+
|
88
|
+
def get_property(prop, klass)
|
89
|
+
if self.properties
|
90
|
+
self.properties.fetch(klass, {})[prop]
|
91
|
+
else
|
92
|
+
nil
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
require 'fcgi'
|
2
|
+
|
3
|
+
Socket.do_not_reverse_lookup = true
|
4
|
+
|
5
|
+
# A FastCGI adaptor for Wee.
|
6
|
+
#
|
7
|
+
# Depends on ruby-fcgi (http://raa.ruby-lang.org/list.rhtml?name=fcgi) or via
|
8
|
+
# Rubygems (gem install fcgi).
|
9
|
+
#
|
10
|
+
# Example of usage:
|
11
|
+
#
|
12
|
+
# require 'wee/adaptors/fastcgi'
|
13
|
+
# Wee::FastCGIAdaptor.start('/app', application)
|
14
|
+
#
|
15
|
+
# == Setup FastCGI with Lighttpd
|
16
|
+
#
|
17
|
+
# # lighttpd.conf
|
18
|
+
# server.modules = (
|
19
|
+
# "mod_fastcgi"
|
20
|
+
# )
|
21
|
+
#
|
22
|
+
# fastcgi.server = (
|
23
|
+
# "/app" =>
|
24
|
+
# ( "fcgi" =>
|
25
|
+
# (
|
26
|
+
# "host" => 127.0.0.1",
|
27
|
+
# "port" => 3000,
|
28
|
+
# "check-local" => "disable"
|
29
|
+
# )
|
30
|
+
# )
|
31
|
+
# )
|
32
|
+
#
|
33
|
+
# Now start the Wee application (the file must be executable):
|
34
|
+
#
|
35
|
+
# spawn-fcgi -f ./run.rb -p 3000
|
36
|
+
#
|
37
|
+
# Finally start the lighttpd server:
|
38
|
+
#
|
39
|
+
# lighttpd -D -f lighttpd.conf
|
40
|
+
#
|
41
|
+
|
42
|
+
class Wee::FastCGIAdaptor
|
43
|
+
def self.start(mount_path, application, request_class=Wee::Request)
|
44
|
+
FCGI.each_cgi {|cgi|
|
45
|
+
query = Hash.new
|
46
|
+
|
47
|
+
# TODO: WEBrick like: return a string which has a to_list method!
|
48
|
+
cgi.params.each {|k, v|
|
49
|
+
raise if v.empty?
|
50
|
+
obj = v.first
|
51
|
+
obj.instance_variable_set("@__as_list", v)
|
52
|
+
def obj.as_list() @__as_list end
|
53
|
+
|
54
|
+
query[k] = obj
|
55
|
+
}
|
56
|
+
|
57
|
+
# TODO
|
58
|
+
header = []
|
59
|
+
|
60
|
+
context = Wee::Context.new(request_class.new(mount_path,
|
61
|
+
cgi.script_name, header, query, cgi.cookies))
|
62
|
+
|
63
|
+
application.handle_request(context)
|
64
|
+
|
65
|
+
header = {}
|
66
|
+
header['status'] = context.response.status.to_s
|
67
|
+
|
68
|
+
context.response.header.each { |k,v| header[k] = v }
|
69
|
+
if context.response.cookies?
|
70
|
+
header['cookie'] = context.response.cookies
|
71
|
+
end
|
72
|
+
|
73
|
+
cgi.out(header) { context.response.content }
|
74
|
+
}
|
75
|
+
end
|
76
|
+
end
|
data/lib/wee/adaptors/webrick.rb
CHANGED
@@ -1,10 +1,12 @@
|
|
1
1
|
require 'webrick'
|
2
2
|
|
3
|
+
Socket.do_not_reverse_lookup = true
|
4
|
+
|
3
5
|
# Example of usage:
|
4
6
|
#
|
5
7
|
# require 'wee/adaptors/webrick'
|
6
8
|
# s = WEBrick::HTTPServer.new(:Port => 2000)
|
7
|
-
# s.mount '/app', Wee::WEBrickAdaptor, application
|
9
|
+
# s.mount '/app', Wee::WEBrickAdaptor, '/app', application
|
8
10
|
#
|
9
11
|
# trap("INT") { s.shutdown; exit }
|
10
12
|
# s.start
|
@@ -20,8 +22,6 @@ require 'webrick'
|
|
20
22
|
# start(:Port => 2000)
|
21
23
|
#
|
22
24
|
|
23
|
-
Socket.do_not_reverse_lookup = true
|
24
|
-
|
25
25
|
class Wee::WEBrickAdaptor < WEBrick::HTTPServlet::AbstractServlet
|
26
26
|
|
27
27
|
# Convenience method
|
data/lib/wee/application.rb
CHANGED
@@ -107,13 +107,14 @@ class Wee::Application
|
|
107
107
|
# :section: Properties
|
108
108
|
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
109
109
|
|
110
|
-
|
110
|
+
def properties() @__properties end
|
111
|
+
def properties=(props) @__properties = props end
|
111
112
|
|
112
113
|
# Returns an "owned" property for the given +klass+.
|
113
114
|
|
114
115
|
def get_property(prop, klass)
|
115
|
-
if
|
116
|
-
|
116
|
+
if self.properties
|
117
|
+
self.properties.fetch(klass, {})[prop]
|
117
118
|
else
|
118
119
|
nil
|
119
120
|
end
|
@@ -136,7 +137,9 @@ class Wee::Application
|
|
136
137
|
end
|
137
138
|
|
138
139
|
def request_handler_expired(context)
|
139
|
-
context.response = Wee::RefreshResponse.new("Invalid or expired request handler!",
|
140
|
+
context.response = Wee::RefreshResponse.new("Invalid or expired request handler!",
|
141
|
+
context.request.build_url(:request_handler_id => nil,
|
142
|
+
:page_id => nil))
|
140
143
|
end
|
141
144
|
|
142
145
|
end
|
data/lib/wee/core/callback.rb
CHANGED
data/lib/wee/core/component.rb
CHANGED
@@ -40,28 +40,27 @@ class Wee::Component < Wee::Presenter
|
|
40
40
|
# #process_callbacks of the first decoration or the component itself if no
|
41
41
|
# decorations were specified.
|
42
42
|
#
|
43
|
-
# [+
|
44
|
-
#
|
43
|
+
# [+block+]
|
44
|
+
# Specifies the action to be taken (e.g. whether to invoke input or action
|
45
|
+
# callbacks).
|
45
46
|
|
46
|
-
def process_callbacks_chain(
|
47
|
-
decoration.process_callbacks(
|
47
|
+
def process_callbacks_chain(&block)
|
48
|
+
decoration.process_callbacks(&block)
|
48
49
|
end
|
49
50
|
|
50
51
|
# Process and invoke all callbacks specified for this component and all of
|
51
52
|
# it's child components.
|
52
53
|
#
|
53
|
-
#
|
54
|
-
#
|
55
|
-
#
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
child.process_callbacks_chain(callback_stream)
|
64
|
-
end
|
54
|
+
# [+block+]
|
55
|
+
# Specifies the action to be taken (e.g. whether to invoke input or action
|
56
|
+
# callbacks).
|
57
|
+
|
58
|
+
def process_callbacks(&block)
|
59
|
+
block.call(self)
|
60
|
+
|
61
|
+
# process callbacks of all children
|
62
|
+
children.each do |child|
|
63
|
+
child.process_callbacks_chain(&block)
|
65
64
|
end
|
66
65
|
end
|
67
66
|
|
@@ -77,20 +76,37 @@ class Wee::Component < Wee::Presenter
|
|
77
76
|
# +super+, before setting up anything else!
|
78
77
|
|
79
78
|
def initialize() # :notnew:
|
80
|
-
@
|
81
|
-
@
|
79
|
+
@__decoration = Wee::ValueHolder.new(self)
|
80
|
+
@__children = []
|
81
|
+
@__parent = nil
|
82
82
|
end
|
83
83
|
|
84
84
|
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
85
|
-
# :section: Children
|
85
|
+
# :section: Children/Composite
|
86
86
|
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
87
87
|
|
88
|
+
public
|
89
|
+
|
90
|
+
# Returns the parent component (or nil if it's the root component). Note
|
91
|
+
# that if you #call a component, the parent attribute will not be set
|
92
|
+
# automatically.
|
93
|
+
|
94
|
+
def parent
|
95
|
+
@__parent
|
96
|
+
end
|
97
|
+
|
98
|
+
# Reparents the component. You should not call this method yourself!
|
99
|
+
|
100
|
+
def parent=(new_parent)
|
101
|
+
@__parent = new_parent
|
102
|
+
end
|
103
|
+
|
88
104
|
protected
|
89
105
|
|
90
106
|
# Returns all direct child components collected in an array.
|
91
107
|
|
92
108
|
def children
|
93
|
-
@
|
109
|
+
@__children
|
94
110
|
end
|
95
111
|
|
96
112
|
# Add a child to the component. Example:
|
@@ -111,8 +127,14 @@ class Wee::Component < Wee::Presenter
|
|
111
127
|
# snapshot.add(self.children)
|
112
128
|
# end
|
113
129
|
#
|
130
|
+
# NOTE: Each component has exactly one parent component (or none in the case
|
131
|
+
# of the root component or when using #call). As such, you can't (and should
|
132
|
+
# not!) add a child more than once to another component.
|
133
|
+
#
|
114
134
|
|
115
135
|
def add_child(child)
|
136
|
+
raise "Child already has a parent!" if not child.parent.nil?
|
137
|
+
child.parent = self
|
116
138
|
self.children << child
|
117
139
|
child
|
118
140
|
end
|
@@ -127,13 +149,13 @@ class Wee::Component < Wee::Presenter
|
|
127
149
|
# +self+ if no decorations were specified for the component.
|
128
150
|
|
129
151
|
def decoration
|
130
|
-
@
|
152
|
+
@__decoration.value
|
131
153
|
end
|
132
154
|
|
133
155
|
# Set the pointer to the first decoration to +d+.
|
134
156
|
|
135
157
|
def decoration=(d)
|
136
|
-
@
|
158
|
+
@__decoration.value = d
|
137
159
|
end
|
138
160
|
|
139
161
|
# Iterates over all decorations (note that the component itself is excluded).
|
@@ -248,7 +270,7 @@ class Wee::Component < Wee::Presenter
|
|
248
270
|
# <i>marshal_load</i>). Overwrite them if you want to define special
|
249
271
|
# behaviour.
|
250
272
|
#
|
251
|
-
# By default only <tt>@
|
273
|
+
# By default only <tt>@__decoration</tt> is backtracked (which actually is a
|
252
274
|
# ValueHolder, as only the pointer changes not the decoration-object
|
253
275
|
# itself!).
|
254
276
|
#
|
@@ -270,7 +292,7 @@ class Wee::Component < Wee::Presenter
|
|
270
292
|
# An object of class Snapshot
|
271
293
|
|
272
294
|
def backtrack_state(snapshot)
|
273
|
-
snapshot.add(@
|
295
|
+
snapshot.add(@__decoration)
|
274
296
|
children.each do |child| child.backtrack_state_chain(snapshot) end
|
275
297
|
end
|
276
298
|
|