plezi 0.14.4 → 0.14.5

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.
@@ -1,176 +1,191 @@
1
- require 'json'
2
1
  module Plezi
3
- module Controller
4
- module ClassMethods
5
- # A Ruby callback used to initialize class data for new Controllers.
6
- def self.extended(base)
7
- base._pl_init_class_data
8
- end
9
-
10
- # Returns a relative URL for the controller, placing the requested parameters in the URL (inline, where possible and as query data when not possible).
11
- def url_for(func, params = {})
12
- ::Plezi::Base::Router.url_for self, func, params
13
- end
14
-
15
- # Invokes a method on the `target` websocket connection. When using Iodine, the method is invoked asynchronously.
16
- #
17
- # self.unicast target, :my_method, "argument 1"
18
- #
19
- # 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.
20
- def unicast(target, event_method, *args)
21
- ::Plezi::Base::MessageDispatch.unicast(self, target, event_method, args)
22
- end
23
-
24
- # Invokes a method on every websocket connection that belongs to this Controller / Type. When using Iodine, the method is invoked asynchronously.
25
- #
26
- # self.broadcast :my_method, "argument 1", "argument 2", 3
27
- #
28
- # 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.
29
- def broadcast(event_method, *args)
30
- ::Plezi::Base::MessageDispatch.broadcast(self, event_method, args)
31
- end
32
-
33
- # Invokes a method on every websocket connection in the application.
34
- #
35
- # self.multicast :my_method, "argument 1", "argument 2", 3
36
- #
37
- # 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.
38
- def multicast(event_method, *args)
39
- ::Plezi::Base::MessageDispatch.multicast(self, event_method, args)
40
- end
41
-
42
- # @private
43
- # This is used internally by Plezi, do not use.
44
- RESERVED_METHODS = [:delete, :create, :update, :new, :show, :pre_connect, :on_open, :on_close, :on_shutdown, :on_message].freeze
45
- # @private
46
- # This function is used internally by Plezi, do not call.
47
- def _pl_get_map
48
- return @_pl_get_map if @_pl_get_map
49
-
50
- @_pl_get_map = {}
51
- mths = public_instance_methods false
52
- mths.delete_if { |m| m.to_s[0] == '_' || !(-1..0).cover?(instance_method(m).arity) }
53
- @_pl_get_map[nil] = :index if mths.include?(:index)
54
- RESERVED_METHODS.each { |m| mths.delete m }
55
- mths.each { |m| @_pl_get_map[m.to_s.freeze] = m }
56
-
57
- @_pl_get_map
58
- end
59
-
60
- # @private
61
- # This function is used internally by Plezi, do not call.
62
- def _pl_has_delete
63
- @_pl_has_delete
64
- end
65
-
66
- # @private
67
- # This function is used internally by Plezi, do not call.
68
- def _pl_has_update
69
- @_pl_has_update
70
- end
71
-
72
- # @private
73
- # This function is used internally by Plezi, do not call.
74
- def _pl_has_create
75
- @_pl_has_create
76
- end
77
-
78
- # @private
79
- # This function is used internally by Plezi, do not call.
80
- def _pl_has_new
81
- @_pl_has_new
82
- end
83
-
84
- # @private
85
- # This function is used internally by Plezi, do not call.
86
- def _pl_has_show
87
- @_pl_has_show
88
- end
89
-
90
- # @private
91
- # This function is used internally by Plezi, do not call.
92
- def _pl_is_websocket?
93
- @_pl_is_websocket
94
- end
95
-
96
- # @private
97
- # This function is used internally by Plezi, do not call.
98
- def _pl_is_ad?
99
- @auto_dispatch
100
- end
101
-
102
- # @private
103
- # This function is used internally by Plezi, do not call.
104
- def _pl_ws_map
105
- return @_pl_ws_map if @_pl_ws_map
106
-
107
- @_pl_ws_map = {}
108
- mths = instance_methods false
109
- mths.delete :index
110
- RESERVED_METHODS.each { |m| mths.delete m }
111
- mths.each { |m| @_pl_ws_map[m.to_s.freeze] = m; @_pl_ws_map[m] = m }
112
-
113
- @_pl_ws_map
114
- end
115
-
116
- # @private
117
- # This function is used internally by Plezi, do not call.
118
- def _pl_ad_map
119
- return @_pl_ad_map if @_pl_ad_map
120
-
121
- @_pl_ad_map = {}
122
- mths = public_instance_methods false
123
- mths.delete_if { |m| m.to_s[0] == '_' || ![-2, -1, 1].freeze.include?(instance_method(m).arity) }
124
- mths.delete :index
125
- RESERVED_METHODS.each { |m| mths.delete m }
126
- mths.each { |m| @_pl_ad_map[m.to_s.freeze] = m; @_pl_ad_map[m] = m }
127
-
128
- @_pl_ad_map
129
- end
130
-
131
- # @private
132
- # This function is used internally by Plezi, do not call.
133
- def _pl_params2method(params, env)
134
- par_id = params['id'.freeze]
135
- meth_id = _pl_get_map[par_id]
136
- return meth_id if par_id && meth_id
137
- # puts "matching against #{params}"
138
- case params['_method'.freeze]
139
- when :get # since this is common, it's pushed upwards.
140
- if env['HTTP_UPGRADE'.freeze] && _pl_is_websocket? && env['HTTP_UPGRADE'.freeze].downcase.start_with?('websocket'.freeze)
141
- @_pl_init_global_data ||= ::Plezi.plezi_initialize # wake up pub/sub drivers in case of `fork`
142
- return :preform_upgrade
143
- end
144
- return :new if _pl_has_new && par_id == 'new'.freeze
145
- return meth_id || (_pl_has_show && :show) || nil
146
- when :put, :patch
147
- return :create if _pl_has_create && (par_id.nil? || par_id == 'new'.freeze)
148
- return :update if _pl_has_update
149
- when :post
150
- return :create if _pl_has_create
151
- when :delete
152
- return :delete if _pl_has_delete
153
- end
154
- meth_id || (_pl_has_show && :show) || nil
155
- end
156
-
157
- # @private
158
- # This function is used internally by Plezi, do not call.
159
- def _pl_init_class_data
160
- @auto_dispatch ||= nil
161
- @_pl_get_map = nil
162
- @_pl_ad_map = nil
163
- @_pl_ws_map = nil
164
- @_pl_has_show = public_instance_methods(false).include?(:show)
165
- @_pl_has_new = public_instance_methods(false).include?(:new)
166
- @_pl_has_create = public_instance_methods(false).include?(:create)
167
- @_pl_has_update = public_instance_methods(false).include?(:update)
168
- @_pl_has_delete = public_instance_methods(false).include?(:delete)
169
- @_pl_is_websocket = (instance_variable_defined?(:@auto_dispatch) && instance_variable_get(:@auto_dispatch)) || instance_methods(false).include?(:on_message)
170
- _pl_get_map
171
- _pl_ad_map
172
- _pl_ws_map
173
- end
174
- end
175
- end
2
+ module Controller
3
+ # this module extends the controller class with Plezi functions
4
+ module ClassMethods
5
+ # A Ruby callback used to initialize class data for new Controllers.
6
+ def self.extended(base)
7
+ base._pl_init_class_data
8
+ end
9
+
10
+ # Returns a relative URL for the controller, placing the requested parameters in the URL (inline, where possible and as query data when not possible).
11
+ def url_for(func, params = {})
12
+ ::Plezi::Base::Router.url_for self, func, params
13
+ end
14
+
15
+ # Invokes a method on the `target` websocket connection. When using Iodine, the method is invoked asynchronously.
16
+ #
17
+ # self.unicast target, :my_method, "argument 1"
18
+ #
19
+ # 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.
20
+ def unicast(target, event_method, *args)
21
+ ::Plezi::Base::MessageDispatch.unicast(self, target, event_method, args)
22
+ end
23
+
24
+ # Invokes a method on every websocket connection that belongs to this Controller / Type. When using Iodine, the method is invoked asynchronously.
25
+ #
26
+ # self.broadcast :my_method, "argument 1", "argument 2", 3
27
+ #
28
+ # 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.
29
+ def broadcast(event_method, *args)
30
+ ::Plezi::Base::MessageDispatch.broadcast(self, event_method, args)
31
+ end
32
+
33
+ # Invokes a method on every websocket connection in the application.
34
+ #
35
+ # self.multicast :my_method, "argument 1", "argument 2", 3
36
+ #
37
+ # 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.
38
+ def multicast(event_method, *args)
39
+ ::Plezi::Base::MessageDispatch.multicast(self, event_method, args)
40
+ end
41
+ # 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`.
42
+ #
43
+ # self.write2everyone {event: "global", message: "This will be sent to everyone"}.to_json
44
+ # # or, we can define a filter method somewhere in our code
45
+ # module Filter
46
+ # def self.should_send? ws
47
+ # true
48
+ # end
49
+ # end
50
+ # # and we can use this filter method.
51
+ # data = {event: "global", message: "This will be sent to everyone"}.to_json
52
+ # self.write2everyone data, ::Filter, :should_send?
53
+ #
54
+ # 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.
55
+ def write2everyone(data, filter_owner = nil, filter_name = nil)
56
+ ::Plezi::Base::MessageDispatch.write2everyone(self, data, filter_owner, filter_name)
57
+ end
58
+
59
+ # @private
60
+ # This is used internally by Plezi, do not use.
61
+ RESERVED_METHODS = [:delete, :create, :update, :new, :show, :pre_connect, :on_open, :on_close, :on_shutdown, :on_message].freeze
62
+ # @private
63
+ # This function is used internally by Plezi, do not call.
64
+ def _pl_get_map
65
+ return @_pl_get_map if @_pl_get_map
66
+
67
+ @_pl_get_map = {}
68
+ mths = public_instance_methods false
69
+ mths.delete_if { |mthd| mthd.to_s[0] == '_' || !(-1..0).cover?(instance_method(mthd).arity) }
70
+ @_pl_get_map[nil] = :index if mths.include?(:index)
71
+ RESERVED_METHODS.each { |mthd| mths.delete mthd }
72
+ mths.each { |mthd| @_pl_get_map[mthd.to_s.freeze] = mthd }
73
+
74
+ @_pl_get_map
75
+ end
76
+
77
+ # @private
78
+ # This function is used internally by Plezi, do not call.
79
+ def _pl_has_delete
80
+ @_pl_has_delete
81
+ end
82
+
83
+ # @private
84
+ # This function is used internally by Plezi, do not call.
85
+ def _pl_has_update
86
+ @_pl_has_update
87
+ end
88
+
89
+ # @private
90
+ # This function is used internally by Plezi, do not call.
91
+ def _pl_has_create
92
+ @_pl_has_create
93
+ end
94
+
95
+ # @private
96
+ # This function is used internally by Plezi, do not call.
97
+ def _pl_has_new
98
+ @_pl_has_new
99
+ end
100
+
101
+ # @private
102
+ # This function is used internally by Plezi, do not call.
103
+ def _pl_has_show
104
+ @_pl_has_show
105
+ end
106
+
107
+ # @private
108
+ # This function is used internally by Plezi, do not call.
109
+ def _pl_is_websocket?
110
+ @_pl_is_websocket
111
+ end
112
+
113
+ # @private
114
+ # This function is used internally by Plezi, do not call.
115
+ def _pl_is_ad?
116
+ @auto_dispatch
117
+ end
118
+
119
+ # @private
120
+ # This function is used internally by Plezi, do not call.
121
+ def _pl_ws_map
122
+ return @_pl_ws_map if @_pl_ws_map
123
+
124
+ @_pl_ws_map = {}
125
+ mths = instance_methods false
126
+ mths.delete :index
127
+ RESERVED_METHODS.each { |mthd| mths.delete mthd }
128
+ mths.each { |mthd| @_pl_ws_map[mthd.to_s.freeze] = mthd; @_pl_ws_map[mthd] = mthd }
129
+
130
+ @_pl_ws_map
131
+ end
132
+
133
+ # @private
134
+ # This function is used internally by Plezi, do not call.
135
+ def _pl_ad_map
136
+ return @_pl_ad_map if @_pl_ad_map
137
+
138
+ @_pl_ad_map = {}
139
+ mths = public_instance_methods false
140
+ mths.delete_if { |m| m.to_s[0] == '_' || ![-2, -1, 1].freeze.include?(instance_method(m).arity) }
141
+ mths.delete :index
142
+ RESERVED_METHODS.each { |m| mths.delete m }
143
+ mths.each { |m| @_pl_ad_map[m.to_s.freeze] = m; @_pl_ad_map[m] = m }
144
+
145
+ @_pl_ad_map
146
+ end
147
+
148
+ # @private
149
+ # This function is used internally by Plezi, do not call.
150
+ def _pl_params2method(params, env)
151
+ par_id = params['id'.freeze]
152
+ meth_id = _pl_get_map[par_id]
153
+ return meth_id if par_id && meth_id
154
+ # puts "matching against #{params}"
155
+ case params['_method'.freeze]
156
+ when :get # since this is common, it's pushed upwards.
157
+ if env['HTTP_UPGRADE'.freeze] && _pl_is_websocket? && env['HTTP_UPGRADE'.freeze].downcase.start_with?('websocket'.freeze)
158
+ @_pl_init_global_data ||= ::Plezi.plezi_initialize # wake up pub/sub drivers in case of `fork`
159
+ return :preform_upgrade
160
+ end
161
+ return :new if _pl_has_new && par_id == 'new'.freeze
162
+ return meth_id || (_pl_has_show && :show) || nil
163
+ when :put, :patch
164
+ return :create if _pl_has_create && (par_id.nil? || par_id == 'new'.freeze)
165
+ return :update if _pl_has_update
166
+ when :post
167
+ return :create if _pl_has_create
168
+ when :delete
169
+ return :delete if _pl_has_delete
170
+ end
171
+ meth_id || (_pl_has_show && :show) || nil
172
+ end
173
+
174
+ # @private
175
+ # This function is used internally by Plezi, do not call.
176
+ def _pl_init_class_data
177
+ @auto_dispatch ||= nil
178
+ @_pl_get_map = @_pl_ad_map = @_pl_ws_map = nil
179
+ @_pl_has_show = public_instance_methods(false).include?(:show)
180
+ @_pl_has_new = public_instance_methods(false).include?(:new)
181
+ @_pl_has_create = public_instance_methods(false).include?(:create)
182
+ @_pl_has_update = public_instance_methods(false).include?(:update)
183
+ @_pl_has_delete = public_instance_methods(false).include?(:delete)
184
+ @_pl_is_websocket = (instance_variable_defined?(:@auto_dispatch) && instance_variable_get(:@auto_dispatch)) || instance_methods(false).include?(:on_message)
185
+ _pl_get_map
186
+ _pl_ad_map
187
+ _pl_ws_map
188
+ end
189
+ end
190
+ end
176
191
  end
@@ -1,54 +1,56 @@
1
1
  module Plezi
2
- module Controller
3
- # The cookie jar class. Controllers have an instance of this class named `cookies`.
4
- class Cookies < Hash
5
- attr_reader :request, :response
6
- def initialize(request, response)
7
- @request = request
8
- @response = response
2
+ module Controller
3
+ # The cookie jar class. Controllers have an instance of this class named `cookies`.
4
+ class Cookies < Hash
5
+ attr_reader :request, :response
6
+ def initialize(request, response)
7
+ @request = request
8
+ @response = response
9
+ end
10
+
11
+ # Reads a cookie from either the request cookie Hash or the new cookies Hash.
12
+ def[](key)
13
+ if key.is_a? Symbol
14
+ super(key) || super(key.to_s) || @request.cookies[key] || @request.cookies[key.to_s]
15
+ elsif key.is_a? String
16
+ super(key) || super(key.to_sym) || @request.cookies[key] || @request.cookies[key.to_sym]
17
+ else
18
+ super(key) || @request.cookies[key]
19
+ end
20
+ end
21
+
22
+ # Sets (or deletes) a cookie. New cookies are placed in the new cookie Hash and are accessible only to the controller that created them.
23
+ def[]=(key, value)
24
+ if value.nil?
25
+ @response.delete_cookie key
26
+ delete key
27
+ if key.is_a? Symbol
28
+ delete key.to_s
29
+ elsif key.is_a? String
30
+ delete key.to_sym
31
+ end
32
+ return nil
33
+ end
34
+ @response.set_cookie key, value
35
+ value = value[:value] if value.is_a? Hash
36
+ super
37
+ end
38
+ end
39
+ # Writes a line dlimited string of all the existing and the new cookies. i.e.:
40
+ # name1=value1
41
+ # name2=value2
42
+ def to_s
43
+ (@request ? (to_a + request.cookies.to_a) : to_a).map! { |pair| pair.join('=') } .join "\n"
9
44
  end
10
45
 
11
- # Reads a cookie from either the request cookie Hash or the new cookies Hash.
12
- def[](key)
13
- if key.is_a? Symbol
14
- super(key) || super(key.to_s) || @request.cookies[key] || @request.cookies[key.to_s]
15
- elsif key.is_a? String
16
- super(key) || super(key.to_sym) || @request.cookies[key] || @request.cookies[key.to_sym]
17
- else
18
- super(key) || @request.cookies[key]
19
- end
46
+ # Returns an array with all the keys of any available cookies (both existing and new cookies).
47
+ def keys
48
+ (@request ? (super + request.cookies.keys) : super)
20
49
  end
21
50
 
22
- # Sets (or deletes) a cookie. New cookies are placed in the new cookie Hash and are accessible only to the controller that created them.
23
- def[]=(key, value)
24
- if value.nil?
25
- @response.delete_cookie key
26
- delete key
27
- if key.is_a? Symbol
28
- delete key.to_s
29
- elsif key.is_a? String
30
- delete key.to_sym
31
- end
32
- return nil
33
- end
34
- @response.set_cookie key, value
35
- value = value[:value] if value.is_a? Hash
36
- super
51
+ # Returns an array with all the values of any available cookies (both existing and new cookies).
52
+ def values
53
+ (@request ? (super + request.cookies.values) : super)
37
54
  end
38
- end
39
- # Writes a line dlimited string of all the existing and the new cookies. i.e.:
40
- # name1=value1
41
- # name2=value2
42
- def to_s
43
- (@request ? (self.to_a + request.cookies.to_a) : self.to_a).map! {|pair| pair.join('=') } .join ("\n")
44
- end
45
- # Returns an array with all the keys of any available cookies (both existing and new cookies).
46
- def keys
47
- (@request ? (super + request.cookies.keys) : super)
48
- end
49
- # Returns an array with all the values of any available cookies (both existing and new cookies).
50
- def values
51
- (@request ? (super + request.cookies.values) : super)
52
- end
53
- end
55
+ end
54
56
  end