Permalink
Browse files

Serializable #call; new meths #call! #call_inline

* Make Component#call (the non-continuation version) serializable, by
  using an instance of UnwindCall instead of a block.

* Introduce Component#call!, which selects either #call or #callcc
  depending on whether it's given a code block or not.

* Component#call_inline, shortcut for call!(BlockComponent.new{...}).
  This was formerly called #display.
  • Loading branch information...
1 parent 28820dc commit 089dd0089c37913960ffded32463e5ac7e0bf7cc @mneumann committed Jan 6, 2010
Showing with 41 additions and 16 deletions.
  1. +41 −16 lib/wee/call_answer.rb
View
@@ -18,11 +18,6 @@ def initialize(args) @args = args end
attr_accessor :answer_callback
- def initialize(&answer_callback)
- super()
- @answer_callback = answer_callback
- end
-
class Interceptor
attr_accessor :action_callback, :answer_callback
@@ -56,9 +51,9 @@ def process_callbacks(callbacks)
module CallAnswerMixin
#
- # Call another component. The calling component is neither rendered nor are
- # it's callbacks processed until the called component answers using method
- # #answer.
+ # Call another component (without using continuations). The calling
+ # component is neither rendered nor are it's callbacks processed
+ # until the called component answers using method #answer.
#
# [+component+]
# The component to be called.
@@ -83,23 +78,37 @@ module CallAnswerMixin
# <tt>return_callback</tt>.
#
def call(component, &return_callback)
- delegate = Wee::Delegate.new(component)
- answer = Wee::AnswerDecoration.new {|answ|
- remove_decoration(delegate)
- component.remove_decoration(answer)
- return_callback.call(*answ.args) if return_callback
- }
+ delegate = Delegate.new(component)
+ answer = AnswerDecoration.new
+ answer.answer_callback = UnwindCall.new(self, component, delegate, answer, &return_callback)
add_decoration(delegate)
component.add_decoration(answer)
session.send_response(nil)
end
+ #
+ # Reverts the changes made due to Component#call. Is called when
+ # Component#call 'answers'.
+ #
+ class UnwindCall
+ def initialize(calling, called, delegate, answer, &return_callback)
+ @calling, @called, @delegate, @answer = calling, called, delegate, answer
+ @return_callback = return_callback
+ end
+
+ def call(answ)
+ @calling.remove_decoration(@delegate)
+ @called.remove_decoration(@answer)
+ @return_callback.call(*answ.args) if @return_callback
+ end
+ end
+
#
# Similar to method #call, but using continuations.
#
def callcc(component)
- delegate = Wee::Delegate.new(component)
- answer = Wee::AnswerDecoration.new
+ delegate = Delegate.new(component)
+ answer = AnswerDecoration.new
add_decoration(delegate)
component.add_decoration(answer)
@@ -122,6 +131,22 @@ def callcc(component)
end
end
+ #
+ # Chooses one of #call or #callcc depending on whether a block is
+ # given or not.
+ #
+ def call!(comp, &block)
+ if block
+ call comp, &block
+ else
+ callcc comp
+ end
+ end
+
+ def call_inline(&render_block)
+ callcc BlockComponent.new(&render_block)
+ end
+
#
# Return from a called component.
#

0 comments on commit 089dd00

Please sign in to comment.