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.
@@ -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
@@ -60,9 +60,7 @@ if __FILE__ == $0
60
60
  require 'wee/utils'
61
61
 
62
62
  app = Wee::Utils.app_for {
63
- comp = RpnCalculator.new
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
@@ -1,8 +1,6 @@
1
1
  $LOAD_PATH.unshift << "../lib"
2
2
  require 'wee'
3
- require 'wee/webrick'
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').action(:answer, true)
15
+ r.submit_button.value('OK').callback(:answer, true)
18
16
  r.space
19
- r.submit_button.value('Cancel').action(:answer, false)
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.action(:click).with('show')
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
- File.open('pid', 'w+') {|f| f << $$}
87
- MyApplication.new {|app|
88
- app.name = 'Counter'
89
- app.path = '/app'
90
- app.session_class = MySession
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
@@ -38,7 +38,7 @@ class LiveUpdateTest < Wee::Component
38
38
  render_live_update
39
39
  end
40
40
 
41
- throw :wee_live_update, response
41
+ send_response(response)
42
42
  end
43
43
  end
44
44
 
@@ -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
@@ -9,7 +9,7 @@ class Wee::Window < Wee::Component
9
9
  @pos = pos
10
10
  end
11
11
 
12
- def process_callbacks(callback_stream)
12
+ def process_callbacks(&block)
13
13
  return if @status == :closed
14
14
  super
15
15
  end
data/lib/wee.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  module Wee
2
- Version = "0.7.0"
2
+ Version = "0.8.0"
3
3
  LibPath = File.dirname(__FILE__)
4
4
  end
5
5
 
@@ -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
@@ -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
@@ -107,13 +107,14 @@ class Wee::Application
107
107
  # :section: Properties
108
108
  # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
109
109
 
110
- attr_accessor :properties
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 @properties
116
- @properties.fetch(klass, {})[prop]
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!", context.request.application_path)
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
@@ -104,6 +104,8 @@ end
104
104
 
105
105
  # A serializable callback.
106
106
  class Wee::LiteralMethodCallback
107
+ attr_reader :obj
108
+
107
109
  def initialize(obj, method_id=:call, *args)
108
110
  @obj, @method_id = obj, method_id
109
111
  @args = args unless args.empty?
@@ -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
- # [+callback_stream+]
44
- # An object of class CallbackStream
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(callback_stream)
47
- decoration.process_callbacks(callback_stream)
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
- # All input callbacks of this component and it's child components are
54
- # processed/invoked before any of the action callbacks are processed/invoked.
55
- #
56
- # [+callback_stream+]
57
- # An object of class CallbackStream
58
-
59
- def process_callbacks(callback_stream)
60
- super do
61
- # process callbacks of all children
62
- children.each do |child|
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
- @decoration = Wee::ValueHolder.new(self)
81
- @children = []
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
- @children
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
- @decoration.value
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
- @decoration.value = d
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>@decoration</tt> is backtracked (which actually is a
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(@decoration)
295
+ snapshot.add(@__decoration)
274
296
  children.each do |child| child.backtrack_state_chain(snapshot) end
275
297
  end
276
298