wee 0.7.0 → 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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