[Borges-users] controller and delegate

Слепнев Владимир slepnev_v at rambler.ru
Mon Apr 12 14:00:07 EDT 2004


Hello,

1) Controller uses StateHolder to store the delegate, and that's 
wrong. If the controller is registered for backtracking, the @delegate 
instance variable will be backtracked automatically; if it isn't, 
what's the point?

2) Controller#delegate_to saves the previous delegate in a local 
variable 'saved', which stays in scope forever. I think this is 
responsible for part (not all) of SushiNet's memory problem. I don't 
think the previous delegate should be saved at all - can't imagine 
what for.

3) A question is whether the delegate of a controller registered for 
backtracking should also be backtracked. In the current version of 
Borges, this isn't done (only the value of @delegate is stored in 
StateHolder),and I'm not doing it either; but I'm not yet sure which 
way is the proper way.


Here's my take on Controller:


class Borges::Controller

   @@subclasses = []

   class << self
     alias orig_new new

     def new(*args, &block)
       inst = orig_new(*args, &block)
       inst.initialize_controller
       return inst
     end

     def inherited(klass)
       @@subclasses << klass
     end

     def all_subclasses
       return @@subclasses
     end
   end

   ##
   # TODO make this a loop

   def active_controller
     if @delegate.nil? then
       return self
     else
       return @delegate.active_controller
     end
   end

   ##
   # Return control to caller
   #
   # Called when a controller has completed, and needs to return a 
value.

   def answer(val = self)
     return val if @continuation.nil?

     @continuation.call(val)
   end

   def self.application_with_path(path, klass = nil)
     app = Borges::Application.new(path)
     app.session_class = klass unless klass.nil?
     app.preferences[:entry_point] = self

     return app
   end

   ##
   # Pass control
   #
   # Called when a controller desires to pass control to another
   # controller.
   #
   # If no controller is specified, then self is being called.  If
   # self is not going to answer, then don't save a continuation.
   #
   # Otherwise, delegate to the controller passed in, then call it.

   def call(controller = nil)
     if controller.nil? then
       unless will_answer? then
         raise Borges::RenderNotification.new

       else
         return callcc do |cc|
           @continuation = cc
           raise Borges::RenderNotification.new
         end

       end

     else
       return delegate_to(controller) do controller.call end

     end
   end

   def clear_delegate
     @delegate = nil
   end

   def confirm(str)
     return call(Borges::Dialog.confirmation(str))
   end

   def self.default_session_class
     return Borges::ControllerSession
   end

   def delegate_to(controller, &block)
     @delegate = controller
     value = block.call
     @delegate = nil
     return value
   end

   def inform(str)
     call(Borges::Dialog.message(str))
   end

   def initialize_controller
     @delegate = nil
     @continuation = nil
   end

   def on_answer(&block)
     @continuation = block
   end

   def self.register_application(app_name, session_class = 
default_session_class)
     app = application_with_path(app_name, session_class)
     Borges::Dispatcher.instance.register(app, app_name)
     return app
   end

   def self.register_authenticated_application(app_name, user, 
password)
     app = register_application(app_name, 
Borges::AuthenticatedSession)

     app.preferences[:username] = Borges::Preference.new(user)
     app.preferences[:password] = Borges::Preference.new(password)

     return app
   end

   def render_active_controller_with(context)
     del = @delegate

     if del.nil? then
       render_with(context)
     else
       del.render_active_controller_with(context)
     end
   end

   ##
   # for compatibility

   def render_on(r)
     render_active_controller_with(r.context)
   end

   def render_with(context)
   end

   ##
   # XXX Fix InputDialog

   def request(request, label = nil, initial = '')
     input_dialog = Borges::InputDialog.new
     input_dialog.message = request
     input_dialog.label = label
     input_dialog.default = initial

     call(input_dialog)
   end

   def session
     return Borges::Session.current_session
   end

   ##
   # Will this component ever call #answer?  Used to optimize calling 
of
   # Controllers.
   #
   # Redefine to return false if this Controller will not call 
#answer.

   def will_answer?
     return true
   end

   ##
   # Will this component ever call #call?  Used to optimize calling of
   # Controllers.
   #
   # Redefine to return false if this Controller will not call #call.

   def will_call?
     return true
   end

end



Vladimir Slepnev


More information about the Borges-users mailing list