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.
@@ -44,8 +44,8 @@ class Wee::Decoration < Wee::Presenter
44
44
 
45
45
  # Forwards method call to the next decoration in the chain.
46
46
 
47
- def process_callbacks(callback_stream)
48
- @owner.process_callbacks(callback_stream)
47
+ def process_callbacks(&block)
48
+ @owner.process_callbacks(&block)
49
49
  end
50
50
 
51
51
  # Forwards method call to the next decoration in the chain.
@@ -93,8 +93,8 @@ class Wee::Delegate < Wee::Decoration
93
93
  # Forwards method to the corresponding top-level *chain* method of the
94
94
  # _delegate_ component.
95
95
 
96
- def process_callbacks(callback_stream)
97
- @delegate.process_callbacks_chain(callback_stream)
96
+ def process_callbacks(&block)
97
+ @delegate.process_callbacks_chain(&block)
98
98
  end
99
99
 
100
100
  # Forwards method to the corresponding top-level *chain* method of the
@@ -128,7 +128,7 @@ class Wee::AnswerDecoration < Wee::Decoration
128
128
 
129
129
  attr_accessor :on_answer
130
130
 
131
- def process_callbacks(callback_stream)
131
+ def process_callbacks(&block)
132
132
  args = catch(:wee_answer) { super; nil }
133
133
  if args != nil
134
134
  # return to the calling component
@@ -75,30 +75,12 @@ class Wee::Presenter
75
75
 
76
76
  # Process all callbacks specified for this presenter.
77
77
  #
78
- # At first, this method invokes all input callbacks of this presenter, then
79
- # it calls the block if one was given (used by subclasses). Finally, the
80
- # action callback is invoked (there's only one per request).
81
- #
82
- # NOTE: Input callbacks should never call other components!
83
- #
84
- # [+callback_stream+]
85
- # An object of class CallbackStream
86
-
87
- def process_callbacks(callback_stream) # :yields:
88
- # invoke input callbacks
89
- callback_stream.with_callbacks_for(self, :input) { |callback, value|
90
- callback.call(value)
91
- }
92
-
93
- # enable subclasses to add behaviour, e.g. a Component class will invoke
94
- # process_callbacks_chain for each child in the block.
95
- yield if block_given?
96
-
97
- # invoke action callback. only the first action callback is invoked.
98
- callback_stream.with_callbacks_for(self, :action) { |callback, value|
99
- callback.call
100
- throw :wee_back_to_session
101
- }
78
+ # [+block+]
79
+ # Specifies the action to be taken (e.g. whether to invoke input or action
80
+ # callbacks).
81
+
82
+ def process_callbacks(&block)
83
+ block.call(self)
102
84
  end
103
85
 
104
86
  # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@@ -129,17 +111,51 @@ class Wee::Presenter
129
111
  Wee::Session.current
130
112
  end
131
113
 
114
+ # Send a premature response.
115
+
116
+ protected
117
+
118
+ def send_response(response)
119
+ throw :wee_send_response, response
120
+ end
121
+
122
+ # Call the block inside a rendering environment, then send the response prematurely.
123
+
124
+ def send_render_response(&block)
125
+ # Generate a response
126
+ response = Wee::GenericResponse.new('text/html', '')
127
+
128
+ # Get the current context we are in
129
+ context = session.current_context
130
+
131
+ # A rendering context is needed to use 'r' (if you want, you can simply
132
+ # omit this and just return the response with some html/xml filled in.
133
+ rendering_context = Wee::RenderingContext.new(
134
+ context.request,
135
+ context.response,
136
+ session.current_callbacks,
137
+ Wee::HtmlWriter.new(response.content))
138
+
139
+ with_renderer_for(rendering_context, &block)
140
+
141
+ send_response(response)
142
+ end
143
+
144
+
132
145
  # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
133
146
  # :section: Properties
134
147
  # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
135
148
 
136
- attr_accessor :properties
149
+ public
150
+
151
+ def properties() @__properties end
152
+ def properties=(props) @__properties = props end
137
153
 
138
154
  # Returns an "owned" property.
139
155
 
140
156
  def get_property(prop)
141
- if @properties
142
- @properties[prop]
157
+ if self.properties
158
+ self.properties[prop]
143
159
  else
144
160
  nil
145
161
  end
@@ -1,6 +1,6 @@
1
1
  # Implements a value holder. Useful for backtracking the reference assigned to
2
2
  # an instance variable (not the object itself!). An example where this is used
3
- # is the <tt>@decoration</tt> attribute of class Wee::Component.
3
+ # is the <tt>@__decoration</tt> attribute of class Wee::Component.
4
4
 
5
5
  class Wee::ValueHolder
6
6
  attr_accessor :value
@@ -5,7 +5,6 @@ class OgScaffolder < Wee::Component
5
5
  def initialize(domain_class)
6
6
  super()
7
7
  @domain_class = domain_class
8
- # DON'T use @properties here as it is already used by Wee
9
8
  @props = @domain_class.__props.reject {|a| a.name == 'oid'}
10
9
  end
11
10
 
@@ -1,9 +1,13 @@
1
+ require 'cgi'
2
+
1
3
  class Wee::PagelessApplication < Wee::Application
2
4
  def request_handler_expired(context)
3
- context.response = Wee::RedirectResponse.new(context.request.application_path)
4
- # TODO: depends on WEBrick
5
- cookie = WEBrick::Cookie.new('SID', '')
6
- cookie.max_age = 0
5
+ context.response = Wee::RedirectResponse.new(context.request.build_url(
6
+ :request_handler_id => nil,
7
+ :page_id => nil))
8
+
9
+ cookie = CGI::Cookie.new('SID', '')
10
+ cookie.expires = Time.at(0)
7
11
  context.response.cookies << cookie
8
12
  end
9
13
  end
@@ -1,15 +1,27 @@
1
1
  class Wee::PagelessRequest < Wee::Request
2
+ private
2
3
 
3
- def build_url(request_handler_id=nil, page_id=nil, callback_id=nil)
4
- url = ""
5
- url << @app_path
6
- url << ('?' + callback_id) if callback_id
7
- return url
4
+ def pageless?
5
+ true
6
+ end
7
+
8
+ def make_request_path(request_handler_id, page_id)
9
+ ""
8
10
  end
9
11
 
10
12
  def parse_path
11
13
  if sid = @cookies.find {|c| c.name == 'SID'}
12
14
  @request_handler_id = sid.value
13
15
  end
16
+
17
+ full_app_path = @path
18
+
19
+ if full_app_path == @app_path
20
+ @info = nil
21
+ elsif full_app_path[0, @app_path.size] == @app_path and full_app_path[@app_path.size] == ?/
22
+ @info = full_app_path[@app_path.size+1..-1]
23
+ else
24
+ raise "dispatched to wrong handler"
25
+ end
14
26
  end
15
27
  end
@@ -1,4 +1,5 @@
1
1
  require 'thread'
2
+ require 'cgi'
2
3
 
3
4
  # A session class, which does not have a page-store and as such cannot
4
5
  # backtrack.
@@ -10,77 +11,62 @@ class Wee::PagelessSession < Wee::Session
10
11
  attr_accessor :callbacks
11
12
  alias current_callbacks callbacks
12
13
 
13
- def initialize(&block)
14
- Thread.current[:wee_session] = self
15
-
16
- # to serialize the requests we need a mutex
17
- @mutex = Mutex.new
18
-
19
- block.call(self)
20
-
21
- raise ArgumentError, "No root component specified" if @root_component.nil?
22
-
23
- super()
24
- ensure
25
- Thread.current[:wee_session] = nil
14
+ def setup(&block)
15
+ with_session do
16
+ block.call(self) if block
17
+ raise ArgumentError, "No root component specified" if @root_component.nil?
18
+ end
26
19
  end
27
20
 
28
- def process_request
29
- p @context.request.fields if $DEBUG
30
-
31
- if @context.request.fields.empty?
32
-
33
- # No action/inputs were specified -> render page
34
- #
35
- # 1. Reset the action/input fields (as they are regenerated in the
36
- # rendering process).
37
- # 2. Render the page (respond).
38
- # 3. Store the page back into the store
21
+ # The main routine where the request is processed.
39
22
 
40
- new_callbacks = Wee::CallbackRegistry.new(Wee::SimpleIdGenerator.new)
41
- respond(@context, new_callbacks) # render
42
- self.callbacks = new_callbacks
43
-
44
- else
23
+ def process_request
24
+ handle_existing_page
25
+ end
45
26
 
46
- # Actions/inputs were specified.
47
- #
48
- # We process the request and invoke actions/inputs. Then we generate a
49
- # new page view.
27
+ def handle_existing_page
28
+ p @context.request.fields if $DEBUG
50
29
 
51
- callback_stream = Wee::CallbackStream.new(self.callbacks, @context.request.fields)
30
+ if @context.request.render?
31
+ handle_render_phase
32
+ else
33
+ handle_callback_phase
34
+ end
35
+ end
52
36
 
53
- if callback_stream.all_of_type(:action).size > 1
54
- raise "Not allowed to specify more than one action callback"
55
- end
37
+ def handle_render_phase
38
+ new_callbacks = Wee::CallbackRegistry.new(Wee::SimpleIdGenerator.new)
39
+ respond(@context, new_callbacks) # render
40
+ self.callbacks = new_callbacks
41
+ end
56
42
 
57
- live_update_response = catch(:wee_live_update) {
58
- catch(:wee_back_to_session) {
59
- @root_component.process_callbacks_chain(callback_stream)
60
- }
61
- nil
62
- }
43
+ def handle_callback_phase
44
+ # Actions/inputs were specified.
45
+ #
46
+ # We process the request and invoke actions/inputs. Then we generate a
47
+ # new page view.
63
48
 
64
- if live_update_response
65
- @context.response = live_update_response
66
- else
67
- handle_new_page_view(@context)
68
- end
49
+ callback_stream = Wee::CallbackStream.new(self.callbacks, @context.request.fields)
50
+ send_response = invoke_callbacks(callback_stream)
69
51
 
70
- end
52
+ post_callbacks_hook()
71
53
 
54
+ if send_response
55
+ set_response(@context, send_response) # @context.response = send_response
56
+ else
57
+ handle_new_page_view(@context)
58
+ end
72
59
  end
73
60
 
74
61
  private
75
62
 
76
63
  def handle_new_page_view(context)
77
- redirect_url = context.request.build_url(context.request.request_handler_id, nil)
64
+ redirect_url = context.request.build_url
78
65
  set_response(context, Wee::RedirectResponse.new(redirect_url))
79
66
  end
80
67
 
81
68
  def set_response(context, response)
82
- # TODO: depends on WEBrick!
83
- response.cookies << WEBrick::Cookie.new('SID', self.id)
69
+ response.cookies << CGI::Cookie.new('SID', self.id)
84
70
  response.header.delete('Expire')
85
71
  response.header['Pragma'] = 'No-Cache'
86
72
  super
@@ -151,6 +151,12 @@ class Brush::GenericTagBrush < Brush
151
151
  onclick("javascript: document.location.href='#{ url }';")
152
152
  end
153
153
 
154
+ def onclick_update(update_id, symbol=nil, *args, &block)
155
+ raise ArgumentError if symbol and block
156
+ url = @canvas.url_for_callback(to_callback(symbol, args, block))
157
+ onclick("javascript: new Ajax.Updater('#{ update_id }', '#{ url }', {method:'get'});")
158
+ end
159
+
154
160
  # This method construct the css-class attribute by looking up the property
155
161
  # from the current component.
156
162
 
@@ -455,7 +461,7 @@ class Brush::FormTag < Brush::GenericTagBrush
455
461
  unless @attributes.has_key?('action')
456
462
  req = @canvas.rendering_context.request
457
463
  # TODO?
458
- @attributes['action'] = req.build_url(req.request_handler_id, req.page_id)
464
+ @attributes['action'] = req.build_url
459
465
  end
460
466
  super
461
467
  end
@@ -76,7 +76,7 @@ class HtmlCanvas < Canvas
76
76
 
77
77
  def url_for_callback_id(callback_id)
78
78
  req = self.rendering_context.request
79
- url = req.build_url(req.request_handler_id, req.page_id, callback_id)
79
+ url = req.build_url(:callback_id => callback_id)
80
80
  return url
81
81
  end
82
82
 
@@ -6,12 +6,16 @@
6
6
 
7
7
  class Wee::Request
8
8
 
9
- DELIM = '=/'
9
+ DELIM = '/___/'
10
10
 
11
11
  attr_accessor :request_handler_id
12
12
  attr_reader :page_id, :fields, :cookies
13
13
 
14
+ # The part of the URL that is user-defineable
15
+ attr_accessor :info
16
+
14
17
  def initialize(app_path, path, headers, fields, cookies)
18
+ raise ArgumentError if app_path[-1] == ?/
15
19
  @app_path, @path, @headers, @cookies = app_path, path, headers, cookies
16
20
  parse_fields(fields)
17
21
  parse_path
@@ -21,17 +25,51 @@ class Wee::Request
21
25
  @app_path
22
26
  end
23
27
 
24
- def build_url(request_handler_id=nil, page_id=nil, callback_id=nil)
28
+ # Is this an action request?
29
+ def action?
30
+ not render?
31
+ end
32
+
33
+ # Is this a render request?
34
+ def render?
35
+ self.fields.empty?
36
+ end
37
+
38
+ def build_url(hash={})
39
+ default = {
40
+ :request_handler_id => self.request_handler_id,
41
+ :page_id => self.page_id,
42
+ :info => self.info
43
+ }
44
+ hash = default.update(hash)
45
+
46
+ request_handler_id = hash[:request_handler_id]
47
+ page_id = hash[:page_id]
48
+ callback_id = hash[:callback_id]
49
+ info = hash[:info]
50
+
25
51
  raise ArgumentError if request_handler_id.nil? and not page_id.nil?
52
+ if not pageless?
53
+ raise ArgumentError if page_id.nil? and not callback_id.nil?
54
+ end
26
55
 
27
- arr = [request_handler_id, page_id].compact
56
+ # build request path, e.g. /___/req-id/page-id
57
+ req_path = make_request_path(request_handler_id, page_id)
28
58
 
29
- url = ""
59
+ # build the whole url
60
+ url = ""
30
61
  url << @app_path
31
- unless arr.empty?
32
- url << '/' if url[-1,1] != '/' # /appXXX -> /app/XXX
33
- url << (DELIM + arr.join('/'))
62
+
63
+ raise if url[-1] == ?/ # sanity check
64
+
65
+ if info
66
+ url << '/'
67
+ url << info
34
68
  end
69
+ url << req_path
70
+
71
+ url << '/' if info.nil? and req_path.empty?
72
+
35
73
  url << ('?' + callback_id) if callback_id
36
74
 
37
75
  return url
@@ -39,6 +77,20 @@ class Wee::Request
39
77
 
40
78
  private
41
79
 
80
+ def pageless?
81
+ false
82
+ end
83
+
84
+ def make_request_path(request_handler_id, page_id)
85
+ arr = [request_handler_id, page_id].compact
86
+ req_path =
87
+ if arr.empty?
88
+ ""
89
+ else
90
+ DELIM + arr.join('/')
91
+ end
92
+ end
93
+
42
94
  def parse_fields(fields)
43
95
  fields ||= Hash.new
44
96
  @fields = Hash.new
@@ -62,6 +114,15 @@ class Wee::Request
62
114
 
63
115
  def parse_path
64
116
  full_app_path, req_path = @path.split(DELIM, 2)
117
+
118
+ if full_app_path == @app_path
119
+ @info = nil
120
+ elsif full_app_path[0, @app_path.size] == @app_path and full_app_path[@app_path.size] == ?/
121
+ @info = full_app_path[@app_path.size+1..-1]
122
+ else
123
+ raise "dispatched to wrong handler"
124
+ end
125
+
65
126
  @request_handler_id = @page_id = nil
66
127
  @request_handler_id, @page_id = req_path.split('/', 2) if req_path
67
128
  end