wee 0.1.0 → 0.3.1
Sign up to get free protection for your applications and to get access to all the features.
- data/INSTALL +7 -0
- data/README +268 -0
- data/Rakefile +26 -0
- data/TODO +116 -0
- data/benchmark/Centrino1300/result.2000.counter.action +45 -0
- data/benchmark/Centrino1300/result.2000.counter.render +43 -0
- data/benchmark/Centrino1300/result.2000.filehandler +43 -0
- data/benchmark/Centrino600/result.2000.counter.action +47 -0
- data/benchmark/Centrino600/result.2000.counter.render +45 -0
- data/benchmark/Centrino600/result.2000.filehandler +43 -0
- data/benchmark/Makefile +48 -0
- data/benchmark/bench.sh +24 -0
- data/benchmark/counter.rb +96 -0
- data/benchmark/filehandler.rb +6 -0
- data/doc/rdoc/classes/Array.html +172 -0
- data/doc/rdoc/classes/Cache.html +126 -0
- data/doc/rdoc/classes/Cache/StorageCache.html +320 -0
- data/doc/rdoc/classes/Cache/Strategy.html +128 -0
- data/doc/rdoc/classes/Cache/Strategy/CapacityBounded.html +269 -0
- data/doc/rdoc/classes/Cache/Strategy/LFU.html +238 -0
- data/doc/rdoc/classes/Cache/Strategy/LFU/Item.html +111 -0
- data/doc/rdoc/classes/Cache/Strategy/LRU.html +238 -0
- data/doc/rdoc/classes/Cache/Strategy/LRU/Item.html +111 -0
- data/doc/rdoc/classes/Cache/Strategy/Unbounded.html +225 -0
- data/doc/rdoc/classes/Cache/Strategy/Unbounded/Item.html +111 -0
- data/doc/rdoc/classes/Enumerable.html +146 -0
- data/doc/rdoc/classes/LiteralMethod.html +196 -0
- data/doc/rdoc/classes/Object.html +178 -0
- data/doc/rdoc/classes/String.html +172 -0
- data/doc/rdoc/classes/Struct.html +174 -0
- data/doc/rdoc/classes/Wee.html +160 -0
- data/doc/rdoc/classes/Wee/AnswerDecoration.html +182 -0
- data/doc/rdoc/classes/Wee/Application.html +337 -0
- data/doc/rdoc/classes/Wee/Brush.html +245 -0
- data/doc/rdoc/classes/Wee/Brush/ActionCallbackMixin.html +149 -0
- data/doc/rdoc/classes/Wee/Brush/ActionMixin.html +146 -0
- data/doc/rdoc/classes/Wee/Brush/ActionURLCallbackMixin.html +157 -0
- data/doc/rdoc/classes/Wee/Brush/AnchorTag.html +210 -0
- data/doc/rdoc/classes/Wee/Brush/AssignMixin.html +141 -0
- data/doc/rdoc/classes/Wee/Brush/CallbackMixin.html +141 -0
- data/doc/rdoc/classes/Wee/Brush/FormTag.html +225 -0
- data/doc/rdoc/classes/Wee/Brush/GenericEncodedTextBrush.html +176 -0
- data/doc/rdoc/classes/Wee/Brush/GenericTagBrush.html +283 -0
- data/doc/rdoc/classes/Wee/Brush/GenericTextBrush.html +176 -0
- data/doc/rdoc/classes/Wee/Brush/ImageButtonTag.html +195 -0
- data/doc/rdoc/classes/Wee/Brush/InputCallbackMixin.html +149 -0
- data/doc/rdoc/classes/Wee/Brush/InputTag.html +172 -0
- data/doc/rdoc/classes/Wee/Brush/Page.html +193 -0
- data/doc/rdoc/classes/Wee/Brush/SelectListTag.html +267 -0
- data/doc/rdoc/classes/Wee/Brush/SelectOptionTag.html +177 -0
- data/doc/rdoc/classes/Wee/Brush/SubmitButtonTag.html +154 -0
- data/doc/rdoc/classes/Wee/Brush/TableDataTag.html +173 -0
- data/doc/rdoc/classes/Wee/Brush/TableHeaderTag.html +146 -0
- data/doc/rdoc/classes/Wee/Brush/TableRowTag.html +277 -0
- data/doc/rdoc/classes/Wee/Brush/TableTag.html +146 -0
- data/doc/rdoc/classes/Wee/Brush/TextAreaTag.html +229 -0
- data/doc/rdoc/classes/Wee/Brush/TextInputTag.html +154 -0
- data/doc/rdoc/classes/Wee/Callback.html +231 -0
- data/doc/rdoc/classes/Wee/CallbackRegistry.html +308 -0
- data/doc/rdoc/classes/Wee/CallbackStream.html +227 -0
- data/doc/rdoc/classes/Wee/Canvas.html +235 -0
- data/doc/rdoc/classes/Wee/Component.html +933 -0
- data/doc/rdoc/classes/Wee/Context.html +111 -0
- data/doc/rdoc/classes/Wee/Decoration.html +338 -0
- data/doc/rdoc/classes/Wee/Delegate.html +247 -0
- data/doc/rdoc/classes/Wee/ErrorPage.html +175 -0
- data/doc/rdoc/classes/Wee/ErrorResponse.html +180 -0
- data/doc/rdoc/classes/Wee/GenericResponse.html +162 -0
- data/doc/rdoc/classes/Wee/HtmlCanvas.html +751 -0
- data/doc/rdoc/classes/Wee/HtmlWriter.html +351 -0
- data/doc/rdoc/classes/Wee/LiteralMethodCallback.html +180 -0
- data/doc/rdoc/classes/Wee/MethodCallback.html +193 -0
- data/doc/rdoc/classes/Wee/Page.html +111 -0
- data/doc/rdoc/classes/Wee/Presenter.html +521 -0
- data/doc/rdoc/classes/Wee/RedirectResponse.html +150 -0
- data/doc/rdoc/classes/Wee/RefreshResponse.html +157 -0
- data/doc/rdoc/classes/Wee/RenderingContext.html +111 -0
- data/doc/rdoc/classes/Wee/Request.html +268 -0
- data/doc/rdoc/classes/Wee/RequestHandler.html +336 -0
- data/doc/rdoc/classes/Wee/Response.html +260 -0
- data/doc/rdoc/classes/Wee/Session.html +469 -0
- data/doc/rdoc/classes/Wee/SimpleIdGenerator.html +198 -0
- data/doc/rdoc/classes/Wee/Snapshot.html +211 -0
- data/doc/rdoc/classes/Wee/StateHolder.html +149 -0
- data/doc/rdoc/classes/Wee/StateRegistry.html +434 -0
- data/doc/rdoc/classes/Wee/StateRegistry/Snapshot.html +320 -0
- data/doc/rdoc/classes/Wee/StateRegistry/WithObject.html +153 -0
- data/doc/rdoc/classes/Wee/Utils.html +111 -0
- data/doc/rdoc/classes/Wee/Utils/LRUCache.html +148 -0
- data/doc/rdoc/classes/Wee/ValueHolder.html +220 -0
- data/doc/rdoc/classes/Wee/WEBrickAdaptor.html +330 -0
- data/doc/rdoc/created.rid +1 -0
- data/doc/rdoc/files/INSTALL.html +118 -0
- data/doc/rdoc/files/README.html +466 -0
- data/doc/rdoc/files/lib/cache/cache_rb.html +101 -0
- data/doc/rdoc/files/lib/wee/adaptors/webrick_rb.html +108 -0
- data/doc/rdoc/files/lib/wee/application_rb.html +112 -0
- data/doc/rdoc/files/lib/wee/callback_rb.html +107 -0
- data/doc/rdoc/files/lib/wee/component_ext_rb.html +101 -0
- data/doc/rdoc/files/lib/wee/component_rb.html +109 -0
- data/doc/rdoc/files/lib/wee/context_rb.html +101 -0
- data/doc/rdoc/files/lib/wee/core/callback_rb.html +115 -0
- data/doc/rdoc/files/lib/wee/core/component_rb.html +108 -0
- data/doc/rdoc/files/lib/wee/core/decoration_rb.html +133 -0
- data/doc/rdoc/files/lib/wee/core/presenter_rb.html +112 -0
- data/doc/rdoc/files/lib/wee/core/snapshot_rb.html +113 -0
- data/doc/rdoc/files/lib/wee/core/valueholder_rb.html +110 -0
- data/doc/rdoc/files/lib/wee/core_rb.html +131 -0
- data/doc/rdoc/files/lib/wee/decoration_rb.html +101 -0
- data/doc/rdoc/files/lib/wee/holder_rb.html +101 -0
- data/doc/rdoc/files/lib/wee/html_canvas_rb.html +108 -0
- data/doc/rdoc/files/lib/wee/html_writer_rb.html +108 -0
- data/doc/rdoc/files/lib/wee/idgen_rb.html +101 -0
- data/doc/rdoc/files/lib/wee/page_rb.html +101 -0
- data/doc/rdoc/files/lib/wee/presenter_rb.html +112 -0
- data/doc/rdoc/files/lib/wee/renderer/html/brushes_rb.html +101 -0
- data/doc/rdoc/files/lib/wee/renderer/html/canvas_rb.html +101 -0
- data/doc/rdoc/files/lib/wee/renderer/html/writer_rb.html +108 -0
- data/doc/rdoc/files/lib/wee/rendering/html/brushes_rb.html +101 -0
- data/doc/rdoc/files/lib/wee/rendering/html/canvas_rb.html +101 -0
- data/doc/rdoc/files/lib/wee/rendering/html/writer_rb.html +108 -0
- data/doc/rdoc/files/lib/wee/request_rb.html +113 -0
- data/doc/rdoc/files/lib/wee/requesthandler_rb.html +101 -0
- data/doc/rdoc/files/lib/wee/response_rb.html +108 -0
- data/doc/rdoc/files/lib/wee/session_rb.html +109 -0
- data/doc/rdoc/files/lib/wee/snapshot_ext_rb.html +101 -0
- data/doc/rdoc/files/lib/wee/snapshot_rb.html +107 -0
- data/doc/rdoc/files/lib/wee/state_registry_rb.html +110 -0
- data/doc/rdoc/files/lib/wee/stuff_rb.html +144 -0
- data/doc/rdoc/files/lib/wee/utils/cache_rb.html +108 -0
- data/doc/rdoc/files/lib/wee/webrick_rb.html +108 -0
- data/doc/rdoc/files/lib/wee_rb.html +132 -0
- data/doc/rdoc/fr_class_index.html +93 -0
- data/doc/rdoc/fr_file_index.html +51 -0
- data/doc/rdoc/fr_method_index.html +242 -0
- data/doc/rdoc/index.html +24 -0
- data/doc/rdoc/rdoc-style.css +208 -0
- data/examples/ObjectSpaceBrowser.rb +199 -0
- data/examples/calendar.rb +366 -0
- data/examples/cc.rb +94 -0
- data/examples/draw.rb +91 -0
- data/examples/example.rb +223 -0
- data/examples/test.rb +66 -0
- data/examples/window.rb +53 -0
- data/lib/cache/cache.rb +9 -0
- data/lib/wee.rb +18 -8
- data/lib/wee/adaptors/webrick.rb +73 -0
- data/lib/wee/application.rb +69 -71
- data/lib/wee/context.rb +2 -12
- data/lib/wee/core.rb +15 -0
- data/lib/wee/core/callback.rb +108 -0
- data/lib/wee/core/component.rb +314 -0
- data/lib/wee/core/decoration.rb +129 -0
- data/lib/wee/core/presenter.rb +132 -0
- data/lib/wee/core/snapshot.rb +21 -0
- data/lib/wee/core/valueholder.rb +19 -0
- data/lib/wee/idgen.rb +13 -0
- data/lib/wee/page.rb +1 -1
- data/lib/wee/renderer/html/brushes.rb +435 -0
- data/lib/wee/renderer/html/canvas.rb +148 -0
- data/lib/wee/{html_writer.rb → renderer/html/writer.rb} +31 -16
- data/lib/wee/request.rb +57 -0
- data/lib/wee/requesthandler.rb +77 -0
- data/lib/wee/response.rb +77 -0
- data/lib/wee/session.rb +70 -64
- data/lib/wee/{snapshot.rb → snapshot_ext.rb} +4 -4
- data/test/components/calltest.rb +16 -0
- data/test/components/counter.rb +17 -0
- data/test/components/messagebox.rb +15 -0
- data/test/components/page.rb +14 -0
- data/test/components/page_decoration.rb +7 -0
- data/test/stress.rb +64 -0
- data/test/test_component.rb +106 -0
- data/test/test_html_canvas.rb +25 -0
- data/test/test_html_writer.rb +27 -0
- data/test/test_request.rb +13 -0
- data/test/utils/cross.rb +65 -0
- data/test/utils/generic_plotter.rb +28 -0
- data/test/utils/gnuplot.rb +31 -0
- data/test/utils/measure_memory.rb +9 -0
- data/test/utils/memory_plotter.rb +10 -0
- data/test/utils/object_plotter.rb +10 -0
- data/test/utils/webrick_background.rb +31 -0
- data/wee.gemspec +22 -0
- metadata +222 -18
- data/lib/wee/component.rb +0 -126
- data/lib/wee/delegate_decoration.rb +0 -22
- data/lib/wee/handler_registry.rb +0 -89
- data/lib/wee/holder.rb +0 -14
- data/lib/wee/html_canvas.rb +0 -379
- data/lib/wee/state_registry.rb +0 -173
- data/lib/wee/stuff.rb +0 -29
- data/lib/wee/webrick.rb +0 -15
data/INSTALL
ADDED
data/README
ADDED
@@ -0,0 +1,268 @@
|
|
1
|
+
= Wee Web Framework
|
2
|
+
|
3
|
+
== Copyright and License
|
4
|
+
|
5
|
+
Copyright (c) 2004, 2005 by Michael Neumann (mneumann@ntecs.de).
|
6
|
+
|
7
|
+
Released under the same terms of license as Ruby. Some files under directory
|
8
|
+
<tt>examples/</tt> might be copyrighted by third parties and licensed under
|
9
|
+
different terms.
|
10
|
+
|
11
|
+
== Status and Bugs
|
12
|
+
|
13
|
+
Wee is not considered production ready! It should only be used for small
|
14
|
+
things.
|
15
|
+
|
16
|
+
Known Bugs:
|
17
|
+
|
18
|
+
* Continuations leak memory!
|
19
|
+
* Sessions get never reclaimed (easy to fix).
|
20
|
+
|
21
|
+
== Introduction
|
22
|
+
|
23
|
+
Wee is a light-weight, very high-level and modern web-framework that makes
|
24
|
+
<b>W</b>eb <b>e</b>ngineering <b>e</b>asy. It mainly inherits many ideas and
|
25
|
+
features from Seaside2[http://beta4.com/seaside2], but was written from scratch
|
26
|
+
without ever looking at the Seaside (or any other) sources. All code was
|
27
|
+
developed from ideas and lots of discussions with Avi Bryant.
|
28
|
+
|
29
|
+
== Features
|
30
|
+
|
31
|
+
=== Reusable components
|
32
|
+
|
33
|
+
Wee has _real_ components, which are like widgets in a GUI. Once written, you
|
34
|
+
can use them everywhere. They are completely independent and do not interfere
|
35
|
+
with other components. Components encapsulate state, a view and actions. Of
|
36
|
+
course you can use an external model or use templates for rendering.
|
37
|
+
|
38
|
+
=== Backtracking
|
39
|
+
|
40
|
+
See the <i>What is backtracking?</i> section below. In short, backtracking lets
|
41
|
+
the browser's back and forward-button play well together with your application.
|
42
|
+
|
43
|
+
=== Clean and concise
|
44
|
+
|
45
|
+
Wee is well thought out, is written in *and* supports clean and concise code.
|
46
|
+
Furthermore I think most parts are now very well documented.
|
47
|
+
|
48
|
+
=== Abstract core
|
49
|
+
|
50
|
+
The core of Wee is completely independent of both HTTP and HTML. That means,
|
51
|
+
with little effort, you should be able to render other formats than HTML and
|
52
|
+
use other communication protocols like SOAP, XML-RPC, Email, GUI or Console.
|
53
|
+
|
54
|
+
=== Templating-independent
|
55
|
+
|
56
|
+
Wee does not depend on a special templating-engine. You can use a different
|
57
|
+
templating engine for each component if you want.
|
58
|
+
|
59
|
+
=== Powerful programmatic HTML generation
|
60
|
+
|
61
|
+
Wee ships with an easy to use and very powerful programmatic html-generation
|
62
|
+
library. For example you can create a select list easily with this piece of
|
63
|
+
code:
|
64
|
+
|
65
|
+
# select an object from these items
|
66
|
+
items = [1, 2, 3, 4]
|
67
|
+
|
68
|
+
# the labels shown to the user
|
69
|
+
labels = items.map {|i| i.to_s}
|
70
|
+
|
71
|
+
# render it
|
72
|
+
r.select_list(items).labels(labels).callback {|choosen| p choosen}
|
73
|
+
|
74
|
+
# render a multi-select list, with objects 2 and 4 selected
|
75
|
+
r.select_list(items).multi.labels(labels).selected([2,4])
|
76
|
+
|
77
|
+
The callback is called with the selected objects from the _items_ array. Items
|
78
|
+
can be any object, e.g. whole components:
|
79
|
+
|
80
|
+
labels = ["msg1", "msg2"]
|
81
|
+
items = labels.collect {|m| MessageBox.new(m)}
|
82
|
+
r.select_list(items).labels(labels).callback {|choosen| call choosen.first}
|
83
|
+
|
84
|
+
=== Continuation based (Optional)
|
85
|
+
|
86
|
+
<b>IMPORTANT:</b> <i>The current implementation of continuations in Ruby might lead
|
87
|
+
to memory leaks, if you use continuations. Furthermore, if you use
|
88
|
+
continuations, it's no longer possible to store the session state to disk.</i>
|
89
|
+
|
90
|
+
Continuation-based frameworks are also known as _modal_ frameworks. You can
|
91
|
+
write code like the one shown below (taken from one of Avi's emails) where each
|
92
|
+
method displays a new page:
|
93
|
+
|
94
|
+
def checkout
|
95
|
+
billing = getAddress("Billing Address")
|
96
|
+
if useSeparateShippingAddress()
|
97
|
+
shipping = getAddress("Shipping Address")
|
98
|
+
else
|
99
|
+
shipping = billing
|
100
|
+
end
|
101
|
+
payment = getPaymentInfo()
|
102
|
+
showConfirmation(billing, shipping, payment)
|
103
|
+
end
|
104
|
+
|
105
|
+
Try to implement the same in a non-continuation based framework and show me
|
106
|
+
your code... ;-)
|
107
|
+
|
108
|
+
=== Fully Marshallable (drops Continuation support)
|
109
|
+
|
110
|
+
If you don't need continuations, Wee can be made fully marshallable. It is not
|
111
|
+
yet fully marshallable (it was in the past), but it can be made, if required.
|
112
|
+
|
113
|
+
== Observations and Limitations
|
114
|
+
|
115
|
+
* Using continuations (might) lead to memory leaks!
|
116
|
+
|
117
|
+
* When using continuations for cross-component calls, it's impossible to
|
118
|
+
store a session to disk (at least in Ruby). This problem is partly addressed
|
119
|
+
by checkpointing provided by operating systems like
|
120
|
+
DragonFly[www.dragonflybsd.org]. But with this approach it's still impossible
|
121
|
+
to store sessions _selectively_ to disk.
|
122
|
+
|
123
|
+
* Each session runs in it's own (light-weigth) thread (this is a neccessity
|
124
|
+
when using continuations).
|
125
|
+
|
126
|
+
* Only one action callback can be invoked per request (a former version of Wee
|
127
|
+
was able to invoke multiple callback, and answer even from multiple
|
128
|
+
components at the same time, but this was removed, due to the unreliability of
|
129
|
+
continuations in Ruby).
|
130
|
+
|
131
|
+
* Components are thread-safe, as a fresh components-tree is created for each
|
132
|
+
session and requests inside a session are serialized.
|
133
|
+
|
134
|
+
== What is backtracking?
|
135
|
+
|
136
|
+
If you want, you can make the back-button of your browser work correctly
|
137
|
+
together with your web-application. Imagine you have a simple counter
|
138
|
+
application, which shows the current count and two links _inc_ and _dec_ with
|
139
|
+
which you can increase or decrease the current count. Starting with an inital
|
140
|
+
count of 0, you increase the counter up to 8, then click three times the back
|
141
|
+
button of your browser (now displays 5) and finally decrease by one, then the
|
142
|
+
counter really shows the expected 4, instead of 7 (as clicking the back button
|
143
|
+
does usually not send a HTTP request, and the last state of your application
|
144
|
+
was 8).
|
145
|
+
|
146
|
+
Only individual objects are backtracked, those of which you explicitly take a
|
147
|
+
snapshot, not the whole component. That's the easiest (from an application
|
148
|
+
programmers perspective) and most flexible way. And its fast and uses less
|
149
|
+
memory.
|
150
|
+
|
151
|
+
You can decide yourself whether you want infinite backtracking or only
|
152
|
+
backtracking up to n pages, with whatever replacement strategy you want, least
|
153
|
+
recently used (LRU), least frequently used (LFU) etc.
|
154
|
+
|
155
|
+
== Decorations
|
156
|
+
|
157
|
+
Decorations are used to modify the look and behaviour of a component, without
|
158
|
+
modifying the components tree. A component can have more than one decoration.
|
159
|
+
This is implemented as a linked list of decorations (Wee::Decoration#owner
|
160
|
+
points to the next decoration). Wee::Component#decoration points to the first
|
161
|
+
decoration in the chain or to the component itself, if no decorations were
|
162
|
+
specified. We actually use a Wee::ValueHolder for the <tt>@decoration</tt>
|
163
|
+
instance variable of class Wee::Component to be able to easily backtrack it
|
164
|
+
(required if you want to "undo" component calls).
|
165
|
+
|
166
|
+
== The anatomy of a request/response cycle
|
167
|
+
|
168
|
+
The request/response cycle in Wee is actually split into two separate phases
|
169
|
+
or steps. Depending on the point-of-view (given that a page is rendered and
|
170
|
+
the user clicks on a link or button), the first phase is to invoke an action
|
171
|
+
(a "callback"). Then in the second phase, a new page is rendered and sent
|
172
|
+
back to the user. So the two steps are:
|
173
|
+
|
174
|
+
1. invoke callbacks (action phase)
|
175
|
+
|
176
|
+
2. render new page and display (render phase)
|
177
|
+
|
178
|
+
These two phases repeat permanently. Which tasks are performed in each of them, is briefly listed below:
|
179
|
+
|
180
|
+
<b>Action:</b>
|
181
|
+
|
182
|
+
1. restore snapshot (if not up-to-date)
|
183
|
+
|
184
|
+
2. invoke actions
|
185
|
+
|
186
|
+
3. backtrack state
|
187
|
+
|
188
|
+
4. update url -> redirect to render phase (not yet)
|
189
|
+
|
190
|
+
<b>Render:</b>
|
191
|
+
|
192
|
+
1. restore snapshot (if not up-to-date)
|
193
|
+
|
194
|
+
2. render
|
195
|
+
|
196
|
+
For each session there is at most one request handled at the same time. That
|
197
|
+
means, that there is either one action request or one render request handled.
|
198
|
+
Why? Because we have only one components tree, which we update on action
|
199
|
+
requests. As Wee allows to go back in time, we have to restore this components
|
200
|
+
tree to a certain point in time before we can handle an action or render
|
201
|
+
request. This disallows to handle e.g. two render requests simultaneous.
|
202
|
+
|
203
|
+
=== Action Phase (Invoking Callbacks)
|
204
|
+
|
205
|
+
Possible sources for callbacks are links (anchors) and all kinds of
|
206
|
+
form-elements like submit buttons, input-fields etc. There are two different
|
207
|
+
kinds of callbacks:
|
208
|
+
|
209
|
+
* Input callbacks (input-fields)
|
210
|
+
|
211
|
+
* Action callbacks (anchor, submit-button)
|
212
|
+
|
213
|
+
The distinction between input and action callbacks is important, as action
|
214
|
+
callbacks might depend on values of input-fields being assigned to instance
|
215
|
+
variables of the controlling component. Hence, Wee first invokes all input
|
216
|
+
callbacks before any action callback is triggered.
|
217
|
+
|
218
|
+
There are two methods related to callback processing:
|
219
|
+
|
220
|
+
* Wee::Component#process_callbacks_chain
|
221
|
+
|
222
|
+
* Wee::Presenter#process_callbacks
|
223
|
+
|
224
|
+
Note that each Wee::Component is also a Wee::Presenter, whereas a
|
225
|
+
Wee::Decoration is not a Component (but a Presenter)!
|
226
|
+
|
227
|
+
Method <i>process_callbacks_chain</i> invokes <i>process_callbacks</i> for
|
228
|
+
it's first decoration, or if the component has no decorations, the method is
|
229
|
+
called for the component itself. As such, <i>process_callbacks_chain</i>
|
230
|
+
is important to avoid entering an infinite loop (a method calling itself). What
|
231
|
+
decorations are, is discussed elsewhere.
|
232
|
+
|
233
|
+
Method <i>process_callbacks</i> of class Component first invokes all input
|
234
|
+
callbacks specified for this component, then calls
|
235
|
+
<i>process_callbacks_chain</i> for all of it's child components. This ensures,
|
236
|
+
that all input callbacks are triggered before the first action callback is
|
237
|
+
run. Finally, it invokes all of it's action callbacks.
|
238
|
+
|
239
|
+
=== Rendering Phase
|
240
|
+
|
241
|
+
The rendering phase is assumed to be side-effect free! So, you as a
|
242
|
+
programmer should take care to meet this assumption.
|
243
|
+
|
244
|
+
Similar as in the callback-step, there are two methods related to rendering a
|
245
|
+
page:
|
246
|
+
|
247
|
+
* Wee::Component#do_render_chain
|
248
|
+
|
249
|
+
* Wee::Presenter#do_render
|
250
|
+
|
251
|
+
Method <i>Component#do_render_chain</i> starts rendering the decoration chain by
|
252
|
+
calling <i>Presenter#do_render</i> for the first decoration of the component or
|
253
|
+
for the component itself if no decorations were specified. Method
|
254
|
+
<i>Presenter#do_render</i> then generates the desired output which gets sent to
|
255
|
+
the user. Note that method <i>do_render</i> might call other components'
|
256
|
+
<i>do_render_chain</i> methods to display those components "inside" itself
|
257
|
+
(usually a component does this for it's child components, but this has to be
|
258
|
+
implemented by the programmer).
|
259
|
+
|
260
|
+
=== Further Reads
|
261
|
+
|
262
|
+
In this order:
|
263
|
+
|
264
|
+
* Wee::Presenter
|
265
|
+
* Wee::Component
|
266
|
+
* Wee::Decoration
|
267
|
+
* Wee::Delegate
|
268
|
+
* Wee::AnswerDecoration
|
data/Rakefile
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'rake/rdoctask'
|
2
|
+
require 'rake/testtask'
|
3
|
+
|
4
|
+
Rake::RDocTask.new do |rd|
|
5
|
+
rd.main = "README"
|
6
|
+
rd.rdoc_dir = 'doc/tmp'
|
7
|
+
rd.rdoc_files.include('lib/**/*.rb', 'README', 'INSTALL')
|
8
|
+
rd.options << '--all --inline-source'
|
9
|
+
end
|
10
|
+
|
11
|
+
task :rdoc do
|
12
|
+
sh 'cpdup -o doc/tmp doc/rdoc'
|
13
|
+
end
|
14
|
+
|
15
|
+
Rake::TestTask.new do |t|
|
16
|
+
t.test_files = FileList['test/test*.rb']
|
17
|
+
t.verbose = true
|
18
|
+
end
|
19
|
+
|
20
|
+
task :package do
|
21
|
+
sh 'gem build wee.gemspec'
|
22
|
+
end
|
23
|
+
|
24
|
+
task :clean => [:clobber_rdoc]
|
25
|
+
|
26
|
+
task :default => [:test, :rdoc, :clean]
|
data/TODO
ADDED
@@ -0,0 +1,116 @@
|
|
1
|
+
* call method #backtrack from backtrack_state. you don't need to call super for #backtrack (at least for direct subclasses of Component).
|
2
|
+
* call method #setup from initialize. same reason as for #backtrack.
|
3
|
+
|
4
|
+
* initialize the component inside the handler thread, not from within Session#initialize
|
5
|
+
|
6
|
+
* renamexxx_chain methods to: component_xxx, e.g.
|
7
|
+
- process_callbacks/process_callback_chain to process_callbacks/component_process_callbacks
|
8
|
+
- ... to backtrack_state/component_backtrack_state
|
9
|
+
- render/render_chain to render/component_render
|
10
|
+
|
11
|
+
* callback -> core, how is the callback registry best done?
|
12
|
+
|
13
|
+
* Context.... reduce
|
14
|
+
|
15
|
+
* root_for -> script style etc.
|
16
|
+
|
17
|
+
* Application == Dispatcher... collection of Session classes (or RequestHandlers)
|
18
|
+
|
19
|
+
* file-comments != class-comments... remove them
|
20
|
+
|
21
|
+
application.template_manager = {
|
22
|
+
My => {'html' => RDocTemplate.new('view/html/file.tmpl'), 'wap' => RDocTemplate.new('view/wap/file.tmpl')}
|
23
|
+
}
|
24
|
+
|
25
|
+
either this way, or reversed: flavour/style => template-manager
|
26
|
+
|
27
|
+
class My < TemplatedComponent
|
28
|
+
def action_blah
|
29
|
+
end
|
30
|
+
def action_blub
|
31
|
+
end
|
32
|
+
|
33
|
+
attr_accessor :blah
|
34
|
+
|
35
|
+
# run-time
|
36
|
+
def template_flavour
|
37
|
+
session.property['style'] || 'html'
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
view/html/filt.tmpl:
|
42
|
+
|
43
|
+
<form action="__action_blah">
|
44
|
+
<input name="__input__blah">
|
45
|
+
</form>
|
46
|
+
|
47
|
+
__action and __input get replaced
|
48
|
+
|
49
|
+
* unify RequestHandler/Session
|
50
|
+
|
51
|
+
* Wee = Web Engineering made Easy
|
52
|
+
|
53
|
+
callback.rb -> core
|
54
|
+
context -> core?
|
55
|
+
|
56
|
+
Wee::Callback: abstract
|
57
|
+
* values -> default_values
|
58
|
+
Wee::BlockCallback
|
59
|
+
* invoke -> call/[]
|
60
|
+
|
61
|
+
overthink CallbackStream
|
62
|
+
CallbackStream abstracts from the Request.
|
63
|
+
use only blocks as callbacks.
|
64
|
+
|
65
|
+
* different models:
|
66
|
+
|
67
|
+
M = Model, V = View, C = Controller
|
68
|
+
|
69
|
+
M: e.g. use ActiveRecord as model
|
70
|
+
V: use external templates
|
71
|
+
C: Wee::Component
|
72
|
+
|
73
|
+
MC: Wee::Component
|
74
|
+
V: external template
|
75
|
+
|
76
|
+
MVC: Wee::Component
|
77
|
+
|
78
|
+
* callbacks.create_callback_stream -> create_stream
|
79
|
+
|
80
|
+
* better webrick
|
81
|
+
|
82
|
+
* AbstractSession:
|
83
|
+
|
84
|
+
last_access: time of last access
|
85
|
+
|
86
|
+
expires_after: expires after n seconds of inactivity (Time.now - last_access > expires_after) if expires_after.not_nil?
|
87
|
+
expires_after = n_seconds
|
88
|
+
|
89
|
+
max_lifetime: how long may this session run in total? nil == infinity
|
90
|
+
max_lifetime =
|
91
|
+
|
92
|
+
Session#terminate: quits a session
|
93
|
+
|
94
|
+
Application.remove_session(self.session_id)
|
95
|
+
|
96
|
+
Session#session_id
|
97
|
+
Session#application
|
98
|
+
|
99
|
+
Application also stores other RequestHandlers. Session is one RequestHandler.
|
100
|
+
|
101
|
+
class RequestHandler
|
102
|
+
attr_reader :application
|
103
|
+
|
104
|
+
attr_reader :last_access
|
105
|
+
attr_accessor :expires_after, :max_lifetime
|
106
|
+
|
107
|
+
def alive?
|
108
|
+
returns true if it should not be terminated
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
* Decoration#owner: use a ValueHolder, too. and register it for being backtracked.
|
113
|
+
|
114
|
+
* mark_objects_for_backtracking() instead of state-registry (snapshot_objects)
|
115
|
+
|
116
|
+
* improve error messages
|
@@ -0,0 +1,45 @@
|
|
1
|
+
This is ApacheBench, Version 2.0.40-dev <$Revision: 1.121.2.8 $> apache-2.0
|
2
|
+
Copyright (c) 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
|
3
|
+
Copyright (c) 1998-2002 The Apache Software Foundation, http://www.apache.org/
|
4
|
+
|
5
|
+
Benchmarking localhost (be patient)
|
6
|
+
|
7
|
+
|
8
|
+
Server Software: WEBrick/1.3.1
|
9
|
+
Server Hostname: localhost
|
10
|
+
Server Port: 2000
|
11
|
+
|
12
|
+
Document Path: /counter/s:1/p:0/h:1
|
13
|
+
Document Length: 62 bytes
|
14
|
+
|
15
|
+
Concurrency Level: 1
|
16
|
+
Time taken for tests: 12.63163 seconds
|
17
|
+
Complete requests: 2000
|
18
|
+
Failed requests: 1991
|
19
|
+
(Connect: 0, Length: 1991, Exceptions: 0)
|
20
|
+
Write errors: 0
|
21
|
+
Non-2xx responses: 2000
|
22
|
+
Total transferred: 552679 bytes
|
23
|
+
HTML transferred: 133786 bytes
|
24
|
+
Requests per second: 165.79 [#/sec] (mean)
|
25
|
+
Time per request: 6.032 [ms] (mean)
|
26
|
+
Time per request: 6.032 [ms] (mean, across all concurrent requests)
|
27
|
+
Transfer rate: 44.68 [Kbytes/sec] received
|
28
|
+
|
29
|
+
Connection Times (ms)
|
30
|
+
min mean[+/-sd] median max
|
31
|
+
Connect: 0 0 0.4 0 9
|
32
|
+
Processing: 3 5 3.8 4 69
|
33
|
+
Waiting: 0 2 3.9 1 69
|
34
|
+
Total: 3 5 3.9 4 72
|
35
|
+
|
36
|
+
Percentage of the requests served within a certain time (ms)
|
37
|
+
50% 4
|
38
|
+
66% 4
|
39
|
+
75% 4
|
40
|
+
80% 5
|
41
|
+
90% 6
|
42
|
+
95% 15
|
43
|
+
98% 16
|
44
|
+
99% 18
|
45
|
+
100% 72 (longest request)
|