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
@@ -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
|
|