lib/plezi/controller/controller_class.rb in plezi-0.14.4 vs lib/plezi/controller/controller_class.rb in plezi-0.14.5

- old
+ new

@@ -1,176 +1,191 @@ -require 'json' module Plezi - module Controller - module ClassMethods - # A Ruby callback used to initialize class data for new Controllers. - def self.extended(base) - base._pl_init_class_data - end + module Controller + # this module extends the controller class with Plezi functions + module ClassMethods + # A Ruby callback used to initialize class data for new Controllers. + def self.extended(base) + base._pl_init_class_data + end - # Returns a relative URL for the controller, placing the requested parameters in the URL (inline, where possible and as query data when not possible). - def url_for(func, params = {}) - ::Plezi::Base::Router.url_for self, func, params - end + # Returns a relative URL for the controller, placing the requested parameters in the URL (inline, where possible and as query data when not possible). + def url_for(func, params = {}) + ::Plezi::Base::Router.url_for self, func, params + end - # Invokes a method on the `target` websocket connection. When using Iodine, the method is invoked asynchronously. - # - # self.unicast target, :my_method, "argument 1" - # - # Methods invoked using {unicast}, {broadcast} or {multicast} will quitely fail if the connection was lost, the requested method is undefined or the 'target' was invalid. - def unicast(target, event_method, *args) - ::Plezi::Base::MessageDispatch.unicast(self, target, event_method, args) - end + # Invokes a method on the `target` websocket connection. When using Iodine, the method is invoked asynchronously. + # + # self.unicast target, :my_method, "argument 1" + # + # Methods invoked using {unicast}, {broadcast} or {multicast} will quitely fail if the connection was lost, the requested method is undefined or the 'target' was invalid. + def unicast(target, event_method, *args) + ::Plezi::Base::MessageDispatch.unicast(self, target, event_method, args) + end - # Invokes a method on every websocket connection that belongs to this Controller / Type. When using Iodine, the method is invoked asynchronously. - # - # self.broadcast :my_method, "argument 1", "argument 2", 3 - # - # Methods invoked using {unicast}, {broadcast} or {multicast} will quitely fail if the connection was lost, the requested method is undefined or the 'target' was invalid. - def broadcast(event_method, *args) - ::Plezi::Base::MessageDispatch.broadcast(self, event_method, args) - end + # Invokes a method on every websocket connection that belongs to this Controller / Type. When using Iodine, the method is invoked asynchronously. + # + # self.broadcast :my_method, "argument 1", "argument 2", 3 + # + # Methods invoked using {unicast}, {broadcast} or {multicast} will quitely fail if the connection was lost, the requested method is undefined or the 'target' was invalid. + def broadcast(event_method, *args) + ::Plezi::Base::MessageDispatch.broadcast(self, event_method, args) + end - # Invokes a method on every websocket connection in the application. - # - # self.multicast :my_method, "argument 1", "argument 2", 3 - # - # Methods invoked using {unicast}, {broadcast} or {multicast} will quitely fail if the connection was lost, the requested method is undefined or the 'target' was invalid. - def multicast(event_method, *args) - ::Plezi::Base::MessageDispatch.multicast(self, event_method, args) - end + # Invokes a method on every websocket connection in the application. + # + # self.multicast :my_method, "argument 1", "argument 2", 3 + # + # Methods invoked using {unicast}, {broadcast} or {multicast} will quitely fail if the connection was lost, the requested method is undefined or the 'target' was invalid. + def multicast(event_method, *args) + ::Plezi::Base::MessageDispatch.multicast(self, event_method, args) + end + # Writes a message to every client websocket connection in all controllers(!). Accepts an optional filter method using a location reference for a *static* (Class/Module/global) method. The filter method will be passerd the websocket object and it should return `true` / `false`. + # + # self.write2everyone {event: "global", message: "This will be sent to everyone"}.to_json + # # or, we can define a filter method somewhere in our code + # module Filter + # def self.should_send? ws + # true + # end + # end + # # and we can use this filter method. + # data = {event: "global", message: "This will be sent to everyone"}.to_json + # self.write2everyone data, ::Filter, :should_send? + # + # It's important that the filter method is defined statically in our code and isn't dynamically allocated. Otherwise, scaling the application would be impossible. + def write2everyone(data, filter_owner = nil, filter_name = nil) + ::Plezi::Base::MessageDispatch.write2everyone(self, data, filter_owner, filter_name) + end - # @private - # This is used internally by Plezi, do not use. - RESERVED_METHODS = [:delete, :create, :update, :new, :show, :pre_connect, :on_open, :on_close, :on_shutdown, :on_message].freeze - # @private - # This function is used internally by Plezi, do not call. - def _pl_get_map - return @_pl_get_map if @_pl_get_map + # @private + # This is used internally by Plezi, do not use. + RESERVED_METHODS = [:delete, :create, :update, :new, :show, :pre_connect, :on_open, :on_close, :on_shutdown, :on_message].freeze + # @private + # This function is used internally by Plezi, do not call. + def _pl_get_map + return @_pl_get_map if @_pl_get_map - @_pl_get_map = {} - mths = public_instance_methods false - mths.delete_if { |m| m.to_s[0] == '_' || !(-1..0).cover?(instance_method(m).arity) } - @_pl_get_map[nil] = :index if mths.include?(:index) - RESERVED_METHODS.each { |m| mths.delete m } - mths.each { |m| @_pl_get_map[m.to_s.freeze] = m } + @_pl_get_map = {} + mths = public_instance_methods false + mths.delete_if { |mthd| mthd.to_s[0] == '_' || !(-1..0).cover?(instance_method(mthd).arity) } + @_pl_get_map[nil] = :index if mths.include?(:index) + RESERVED_METHODS.each { |mthd| mths.delete mthd } + mths.each { |mthd| @_pl_get_map[mthd.to_s.freeze] = mthd } - @_pl_get_map - end + @_pl_get_map + end - # @private - # This function is used internally by Plezi, do not call. - def _pl_has_delete - @_pl_has_delete - end + # @private + # This function is used internally by Plezi, do not call. + def _pl_has_delete + @_pl_has_delete + end - # @private - # This function is used internally by Plezi, do not call. - def _pl_has_update - @_pl_has_update - end + # @private + # This function is used internally by Plezi, do not call. + def _pl_has_update + @_pl_has_update + end - # @private - # This function is used internally by Plezi, do not call. - def _pl_has_create - @_pl_has_create - end + # @private + # This function is used internally by Plezi, do not call. + def _pl_has_create + @_pl_has_create + end - # @private - # This function is used internally by Plezi, do not call. - def _pl_has_new - @_pl_has_new - end + # @private + # This function is used internally by Plezi, do not call. + def _pl_has_new + @_pl_has_new + end - # @private - # This function is used internally by Plezi, do not call. - def _pl_has_show - @_pl_has_show - end + # @private + # This function is used internally by Plezi, do not call. + def _pl_has_show + @_pl_has_show + end - # @private - # This function is used internally by Plezi, do not call. - def _pl_is_websocket? - @_pl_is_websocket - end + # @private + # This function is used internally by Plezi, do not call. + def _pl_is_websocket? + @_pl_is_websocket + end - # @private - # This function is used internally by Plezi, do not call. - def _pl_is_ad? - @auto_dispatch - end + # @private + # This function is used internally by Plezi, do not call. + def _pl_is_ad? + @auto_dispatch + end - # @private - # This function is used internally by Plezi, do not call. - def _pl_ws_map - return @_pl_ws_map if @_pl_ws_map + # @private + # This function is used internally by Plezi, do not call. + def _pl_ws_map + return @_pl_ws_map if @_pl_ws_map - @_pl_ws_map = {} - mths = instance_methods false - mths.delete :index - RESERVED_METHODS.each { |m| mths.delete m } - mths.each { |m| @_pl_ws_map[m.to_s.freeze] = m; @_pl_ws_map[m] = m } + @_pl_ws_map = {} + mths = instance_methods false + mths.delete :index + RESERVED_METHODS.each { |mthd| mths.delete mthd } + mths.each { |mthd| @_pl_ws_map[mthd.to_s.freeze] = mthd; @_pl_ws_map[mthd] = mthd } - @_pl_ws_map - end + @_pl_ws_map + end - # @private - # This function is used internally by Plezi, do not call. - def _pl_ad_map - return @_pl_ad_map if @_pl_ad_map + # @private + # This function is used internally by Plezi, do not call. + def _pl_ad_map + return @_pl_ad_map if @_pl_ad_map - @_pl_ad_map = {} - mths = public_instance_methods false - mths.delete_if { |m| m.to_s[0] == '_' || ![-2, -1, 1].freeze.include?(instance_method(m).arity) } - mths.delete :index - RESERVED_METHODS.each { |m| mths.delete m } - mths.each { |m| @_pl_ad_map[m.to_s.freeze] = m; @_pl_ad_map[m] = m } + @_pl_ad_map = {} + mths = public_instance_methods false + mths.delete_if { |m| m.to_s[0] == '_' || ![-2, -1, 1].freeze.include?(instance_method(m).arity) } + mths.delete :index + RESERVED_METHODS.each { |m| mths.delete m } + mths.each { |m| @_pl_ad_map[m.to_s.freeze] = m; @_pl_ad_map[m] = m } - @_pl_ad_map - end + @_pl_ad_map + end - # @private - # This function is used internally by Plezi, do not call. - def _pl_params2method(params, env) - par_id = params['id'.freeze] - meth_id = _pl_get_map[par_id] - return meth_id if par_id && meth_id - # puts "matching against #{params}" - case params['_method'.freeze] - when :get # since this is common, it's pushed upwards. - if env['HTTP_UPGRADE'.freeze] && _pl_is_websocket? && env['HTTP_UPGRADE'.freeze].downcase.start_with?('websocket'.freeze) - @_pl_init_global_data ||= ::Plezi.plezi_initialize # wake up pub/sub drivers in case of `fork` - return :preform_upgrade - end - return :new if _pl_has_new && par_id == 'new'.freeze - return meth_id || (_pl_has_show && :show) || nil - when :put, :patch - return :create if _pl_has_create && (par_id.nil? || par_id == 'new'.freeze) - return :update if _pl_has_update - when :post - return :create if _pl_has_create - when :delete - return :delete if _pl_has_delete - end - meth_id || (_pl_has_show && :show) || nil - end + # @private + # This function is used internally by Plezi, do not call. + def _pl_params2method(params, env) + par_id = params['id'.freeze] + meth_id = _pl_get_map[par_id] + return meth_id if par_id && meth_id + # puts "matching against #{params}" + case params['_method'.freeze] + when :get # since this is common, it's pushed upwards. + if env['HTTP_UPGRADE'.freeze] && _pl_is_websocket? && env['HTTP_UPGRADE'.freeze].downcase.start_with?('websocket'.freeze) + @_pl_init_global_data ||= ::Plezi.plezi_initialize # wake up pub/sub drivers in case of `fork` + return :preform_upgrade + end + return :new if _pl_has_new && par_id == 'new'.freeze + return meth_id || (_pl_has_show && :show) || nil + when :put, :patch + return :create if _pl_has_create && (par_id.nil? || par_id == 'new'.freeze) + return :update if _pl_has_update + when :post + return :create if _pl_has_create + when :delete + return :delete if _pl_has_delete + end + meth_id || (_pl_has_show && :show) || nil + end - # @private - # This function is used internally by Plezi, do not call. - def _pl_init_class_data - @auto_dispatch ||= nil - @_pl_get_map = nil - @_pl_ad_map = nil - @_pl_ws_map = nil - @_pl_has_show = public_instance_methods(false).include?(:show) - @_pl_has_new = public_instance_methods(false).include?(:new) - @_pl_has_create = public_instance_methods(false).include?(:create) - @_pl_has_update = public_instance_methods(false).include?(:update) - @_pl_has_delete = public_instance_methods(false).include?(:delete) - @_pl_is_websocket = (instance_variable_defined?(:@auto_dispatch) && instance_variable_get(:@auto_dispatch)) || instance_methods(false).include?(:on_message) - _pl_get_map - _pl_ad_map - _pl_ws_map + # @private + # This function is used internally by Plezi, do not call. + def _pl_init_class_data + @auto_dispatch ||= nil + @_pl_get_map = @_pl_ad_map = @_pl_ws_map = nil + @_pl_has_show = public_instance_methods(false).include?(:show) + @_pl_has_new = public_instance_methods(false).include?(:new) + @_pl_has_create = public_instance_methods(false).include?(:create) + @_pl_has_update = public_instance_methods(false).include?(:update) + @_pl_has_delete = public_instance_methods(false).include?(:delete) + @_pl_is_websocket = (instance_variable_defined?(:@auto_dispatch) && instance_variable_get(:@auto_dispatch)) || instance_methods(false).include?(:on_message) + _pl_get_map + _pl_ad_map + _pl_ws_map + end end - end - end + end end