plezi 0.12.22 → 0.14.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.
Files changed (108) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +18 -0
  3. data/LICENSE.txt +17 -18
  4. data/README.md +54 -698
  5. data/Rakefile +7 -4
  6. data/bin/config.ru +22 -0
  7. data/{test → bin}/console +4 -6
  8. data/bin/hello_world +52 -0
  9. data/bin/setup +8 -0
  10. data/exe/plezi +145 -0
  11. data/lib/plezi.rb +24 -137
  12. data/lib/plezi/activation.rb +28 -0
  13. data/lib/plezi/api.rb +62 -0
  14. data/lib/plezi/controller/controller.rb +259 -0
  15. data/lib/plezi/controller/controller_class.rb +176 -0
  16. data/lib/plezi/controller/cookies.rb +40 -0
  17. data/lib/plezi/helpers.rb +60 -0
  18. data/lib/plezi/rake.rb +2 -24
  19. data/lib/plezi/render/erb.rb +34 -0
  20. data/lib/plezi/render/has_cache.rb +36 -0
  21. data/lib/plezi/render/markdown.rb +63 -0
  22. data/lib/plezi/render/render.rb +49 -0
  23. data/lib/plezi/render/sass.rb +55 -0
  24. data/lib/plezi/render/slim.rb +33 -0
  25. data/lib/plezi/router/adclient.rb +23 -0
  26. data/lib/plezi/router/assets.rb +67 -0
  27. data/lib/plezi/router/errors.rb +29 -0
  28. data/lib/plezi/router/route.rb +112 -0
  29. data/lib/plezi/router/router.rb +120 -0
  30. data/lib/plezi/version.rb +1 -1
  31. data/lib/plezi/websockets/message_dispatch.rb +91 -0
  32. data/lib/plezi/websockets/redis.rb +55 -0
  33. data/plezi.gemspec +25 -16
  34. data/resources/404.erb +5 -4
  35. data/resources/500.erb +5 -4
  36. data/resources/{500.html → 503.html} +8 -9
  37. data/resources/client.js +253 -0
  38. data/resources/config.ru +5 -36
  39. data/resources/ctrlr.rb +34 -0
  40. data/resources/gemfile +4 -0
  41. data/resources/mini_app.rb +28 -82
  42. data/resources/mini_exec +7 -0
  43. data/resources/mini_welcome_page.html +0 -0
  44. data/resources/procfile +3 -0
  45. data/resources/rakefile +4 -8
  46. data/resources/routes.rb +9 -26
  47. data/resources/{websockets.js → simple-client.js} +3 -3
  48. metadata +60 -85
  49. data/bin/plezi +0 -104
  50. data/docs/async_helpers.md +0 -245
  51. data/docs/controllers.md +0 -27
  52. data/docs/logging.md +0 -49
  53. data/docs/routes.md +0 -209
  54. data/docs/websockets.md +0 -213
  55. data/lib/plezi/builders/ac_model.rb +0 -59
  56. data/lib/plezi/builders/app_builder.rb +0 -137
  57. data/lib/plezi/builders/builder.rb +0 -43
  58. data/lib/plezi/builders/form_builder.rb +0 -27
  59. data/lib/plezi/common/api.rb +0 -92
  60. data/lib/plezi/common/cache.rb +0 -122
  61. data/lib/plezi/common/defer.rb +0 -21
  62. data/lib/plezi/common/dsl.rb +0 -94
  63. data/lib/plezi/common/redis.rb +0 -65
  64. data/lib/plezi/common/renderer.rb +0 -141
  65. data/lib/plezi/common/settings.rb +0 -52
  66. data/lib/plezi/handlers/controller_core.rb +0 -106
  67. data/lib/plezi/handlers/controller_magic.rb +0 -284
  68. data/lib/plezi/handlers/http_router.rb +0 -205
  69. data/lib/plezi/handlers/placebo.rb +0 -112
  70. data/lib/plezi/handlers/route.rb +0 -216
  71. data/lib/plezi/handlers/session.rb +0 -109
  72. data/lib/plezi/handlers/stubs.rb +0 -156
  73. data/lib/plezi/handlers/ws_identity.rb +0 -253
  74. data/lib/plezi/handlers/ws_object.rb +0 -308
  75. data/lib/plezi/helpers/http_sender.rb +0 -84
  76. data/lib/plezi/helpers/magic_helpers.rb +0 -104
  77. data/lib/plezi/helpers/mime_types.rb +0 -1995
  78. data/lib/plezi/oauth.rb +0 -5
  79. data/lib/plezi/oauth/auth_controller.rb +0 -229
  80. data/logo/dark.png +0 -0
  81. data/logo/light.png +0 -0
  82. data/logo/sign.png +0 -0
  83. data/resources/404.haml +0 -121
  84. data/resources/404.html +0 -124
  85. data/resources/404.slim +0 -120
  86. data/resources/500.haml +0 -120
  87. data/resources/500.slim +0 -120
  88. data/resources/Gemfile +0 -86
  89. data/resources/code.rb +0 -8
  90. data/resources/controller.rb +0 -142
  91. data/resources/database.yml +0 -33
  92. data/resources/db_ac_config.rb +0 -59
  93. data/resources/db_dm_config.rb +0 -51
  94. data/resources/db_sequel_config.rb +0 -33
  95. data/resources/en.yml +0 -204
  96. data/resources/haml_config.rb +0 -6
  97. data/resources/i18n_config.rb +0 -14
  98. data/resources/initialize.rb +0 -49
  99. data/resources/mini_exec.rb +0 -7
  100. data/resources/oauth_config.rb +0 -24
  101. data/resources/plezi_client.js +0 -198
  102. data/resources/plezi_websockets.html +0 -47
  103. data/resources/redis_config.rb +0 -42
  104. data/resources/slim_config.rb +0 -11
  105. data/resources/welcome_page.html +0 -272
  106. data/test/dispatch +0 -58
  107. data/test/hello_world +0 -13
  108. data/test/plezi_tests.rb +0 -581
@@ -1,112 +0,0 @@
1
- module Plezi
2
-
3
- # This API wil allows you to listen to Websocket Broadcasts sent to any object and to accept unicasts
4
- # even when NOT connected to a websocket.
5
- #
6
- # Simpley create a class to handle any events and call `Plezi::Placebo.new ClassName` or use the {Plezi.start_placebo} shortcut:
7
- #
8
- # # Important: set up a unique - but shared - main redis channel for BOTH Apps (The Plezi and the Placebo).
9
- # Plezi::Settings.redis_channel_name = 'unique_channel_name_for_app_b24270e2'
10
- # # Important: set Plezi's auo-Redis pub/sub server.
11
- # ENV['PL_REDIS_URL'] ||= "redis://redis:password@redis.server.com:9999"
12
- #
13
- # # create the Placebo bridge handler
14
- # class PleziBridge
15
- # def on_open
16
- # multicast :print, "Hello from Placebo!"
17
- # end
18
- # def print data
19
- # Iodine.info "Placebo message: #{data}"
20
- # puts "Placebo message: #{data}"
21
- # end
22
- # end
23
- #
24
- # # initiate Placebo mode using the bridge class. it's possible to create multiple
25
- # # it's possible to create multiple bridge classes this way.
26
- # Plezi.start_placebo(PleziBridge)
27
- #
28
- # A new instance will be created and that instance will answer any broadcasts, for ALL possible
29
- # Plezi controllers, as long as it had a method defined that is capable to handle the broadcast.
30
- #
31
- # The new instance will also accept unicasts sent to it's unique UUID.
32
- #
33
- # Returns an instance that is a member of the class passed, after that class was inherited by Plezi and
34
- # more methods were injected into it's subclass.
35
- module Placebo
36
-
37
- # the base module exposes some of the core functionality, but shouldn't be relied upon as far as it's API goes.
38
- module Base
39
- #the methods here will be injected to the Placebo controller.
40
- module Core
41
- def self.included base
42
- base.send :include, Plezi::Base::WSObject
43
- base.send :include, InstanceMethods
44
- base.extend ClassMethods
45
- base.superclass.instance_eval {extend SuperClassMethods}
46
- end
47
-
48
- #the methods here will be injected to the Placebo controller as Instance methods.
49
- module InstanceMethods
50
- public
51
- attr_accessor :io
52
- def initialize io_in, io_out, request
53
- @io_in = io_in
54
- @io_out = io_out
55
- @request = request
56
- super()
57
- end
58
- # Cleanup on disconnection
59
- def on_close
60
- @io_out.close unless @io_out.closed?
61
- return super() if defined? super
62
- Iodine.warn "Placebo #{self.class.superclass.name} disconnected. Ignore if this message appears during shutdown."
63
- end
64
- def placebo?
65
- true
66
- end
67
- end
68
- #the methods here will be injected to the Placebo controller as class methods.
69
- module ClassMethods
70
- end
71
- module SuperClassMethods
72
- def placebo?
73
- true
74
- end
75
- end
76
- end
77
- class PlaceboIO < ::Iodine::Http::Websockets
78
- # emulate Iodine::Protocol#timeout?
79
- def timeout? time
80
- false
81
- end
82
- # emulate Iodine::Protocol#call
83
- def call
84
- read
85
- Iodine.warn "Placebo IO recieved IO signal - this is unexpected..."
86
- end
87
- # override "go_away"
88
- def go_away
89
- close
90
- end
91
- end
92
- end
93
- module_function
94
- def new placebo_class, create = true
95
- new_class_name = "PlaceboPlezi__#{placebo_class.name.gsub( /[\:\-\#\<\>\{\}\(\)\s]/ , '_')}"
96
- new_class = nil
97
- new_class = Module.const_get new_class_name if Module.const_defined? new_class_name
98
- unless new_class
99
- new_class = Class.new(placebo_class) do
100
- include Placebo::Base::Core
101
- end
102
- Object.const_set(new_class_name, new_class)
103
- end
104
- return new_class unless create
105
- i, o = IO.pipe
106
- req = {}
107
- handler = new_class.new(i, o, req)
108
- Placebo::Base::PlaceboIO.new i, handler: handler, request: req
109
- handler
110
- end
111
- end
112
- end
@@ -1,216 +0,0 @@
1
- module Plezi
2
- module Base
3
- class Route
4
- # the Regexp that will be used to match the request.
5
- attr_reader :path
6
- # the controller that answers the request on this path (if exists).
7
- attr_reader :controller
8
- # the proc that answers the request on this path (if exists).
9
- attr_reader :proc
10
- # the parameters for the router and service that were used to create the service, router and host.
11
- attr_reader :params
12
- # an array containing the parts of the original url, if any. `false` for Regexp or non relevant routes.
13
- attr_reader :url_array
14
-
15
- # lets the route answer the request. returns false if no response has been sent.
16
- def on_request request, response
17
- fill_parameters = match request.path
18
- return false unless fill_parameters
19
- old_params = request.params.dup
20
- fill_parameters.each {|k,v| Plezi::Base::Helpers.add_param_to_hash k, ::Plezi::Base::Helpers.form_decode(v), request.params }
21
- ret = false
22
- if controller
23
- ret = controller.new(request, response)._route_path_to_methods_and_set_the_response_
24
- elsif proc
25
- # proc.init(request, response)
26
- # ret = proc.instance_exec(request, response, &proc)
27
- ret = proc.call(request, response)
28
- elsif controller == false
29
- request.path = path.match(request.path).to_a.last.to_s
30
- return false
31
- end
32
- unless ret
33
- request.params.replace old_params unless fill_parameters.empty?
34
- return false
35
- end
36
- return ret
37
- end
38
-
39
- # the initialize method accepts a Regexp or a String and creates the path object.
40
- #
41
- # Regexp paths will be left unchanged
42
- #
43
- # a string can be either a simple string `"/users"` or a string with parameters:
44
- # `"/static/:required/(:optional)/(:optional_with_format){[\d]*}/:optional_2"`
45
- def initialize path, controller, params={}, &block
46
- @original_path, @url_array, @params = path, false, params
47
- initialize_path( (controller == false) ? "#{path.chomp('/')}/*" : path )
48
- initialize_controller controller, block
49
- end
50
-
51
- # initializes the controller,
52
- # by inheriting the class into an Plezi controller subclass (with the Plezi::ControllerMagic injected).
53
- #
54
- # Proc objects are currently passed through without any change - as Proc routes are assumed to handle themselves correctly.
55
- def initialize_controller controller, block
56
- @controller, @proc = controller, block
57
- if controller.is_a?(Class)
58
- # add controller magic
59
- @controller = self.class.make_controller_magic controller, self
60
- end
61
- if @proc.is_a?(Proc)
62
- # # proc's methods aren't executed since it's binding isn't `self`
63
- # @proc.instance_exec do
64
- # extend ::Plezi::ControllerMagic::InstanceMethods
65
- # undef :url_for
66
- # undef :full_url_for
67
- # undef :requested_method
68
- # def run request, response
69
- # @request = request
70
- # @params = request.params
71
- # @flash = response.flash
72
- # @host_params = request[:host_settings]
73
- # @response = response
74
- # @cookies = request.cookies
75
- # end
76
- # end
77
- end
78
- end
79
-
80
- # Used to check for routes formatted: /:paramater - required parameters
81
- REGEXP_REQUIRED_PARAMS = /^\:([^\(\)\{\}\:]*)$/
82
- # Used to check for routes formatted: /(:paramater) - optional parameters
83
- REGEXP_OPTIONAL_PARAMS = /^\(\:([^\(\)\{\}\:]*)\)$/
84
- # Used to check for routes formatted: /(:paramater){regexp} - optional formatted parameters
85
- REGEXP_FORMATTED_OPTIONAL_PARAMS = /^\(\:([^\(\)\{\}\:]*)\)\{(.*)\}$/
86
- # Used to check for routes formatted: /:paramater{regexp} - required parameters
87
- REGEXP_FORMATTED_REQUIRED_PARAMS = /^\:([^\(\)\{\}\:\/]*)\{(.*)\}$/
88
- # Used to check for routes formatted: /{regexp} - required path
89
- REGEXP_FORMATTED_PATH = /^\{(.*)\}$/
90
-
91
- # initializes the path by converting the string into a Regexp
92
- # and noting any parameters that might need to be extracted for RESTful routes.
93
- def initialize_path path
94
- @fill_parameters = {}
95
- if path.is_a? Regexp
96
- @path = path
97
- elsif path.is_a? String
98
- # prep used prameters
99
- param_num = 0
100
-
101
- section_search = "([\\/][^\\/]*)"
102
- optional_section_search = "([\\/][^\\/]*)?"
103
-
104
- @path = '^'
105
- @url_array = []
106
-
107
- # prep path string and split it where the '/' charected is unescaped.
108
- @url_array = path.gsub(/(^\/)|(\/$)/, ''.freeze).gsub(/([^\\])\//, '\1 - /').split ' - /'
109
- @url_array.each.with_index do |section, section_index|
110
- if section == '*'.freeze
111
- # create catch all
112
- section_index == 0 ? (@path << "(.*)") : (@path << "(\\/.*)?")
113
- # finish
114
- @path = /#{@path}$/
115
- return
116
-
117
- # check for routes formatted: /:paramater - required parameters
118
- elsif section.match REGEXP_REQUIRED_PARAMS
119
- #create a simple section catcher
120
- @path << section_search
121
- # add paramater recognition value
122
- @fill_parameters[param_num += 1] = section.match(REGEXP_REQUIRED_PARAMS)[1]
123
-
124
- # check for routes formatted: /(:paramater) - optional parameters
125
- elsif section.match REGEXP_OPTIONAL_PARAMS
126
- #create a optional section catcher
127
- @path << optional_section_search
128
- # add paramater recognition value
129
- @fill_parameters[param_num += 1] = section.match(REGEXP_OPTIONAL_PARAMS)[1]
130
-
131
- # check for routes formatted: /(:paramater){regexp} - optional parameters
132
- elsif section.match REGEXP_FORMATTED_OPTIONAL_PARAMS
133
- #create a optional section catcher
134
- @path << ( "(\/(" + section.match(REGEXP_FORMATTED_OPTIONAL_PARAMS)[2] + "))?" )
135
- # add paramater recognition value
136
- @fill_parameters[param_num += 1] = section.match(REGEXP_FORMATTED_OPTIONAL_PARAMS)[1]
137
- param_num += 1 # we are using two spaces - param_num += should look for () in regex ? /[^\\](/
138
-
139
- # check for routes formatted: /:paramater{regexp} - required parameters
140
- elsif section.match REGEXP_FORMATTED_REQUIRED_PARAMS
141
- #create a simple section catcher
142
- @path << ( "(\/(" + section.match(REGEXP_FORMATTED_REQUIRED_PARAMS)[2] + "))" )
143
- # add paramater recognition value
144
- @fill_parameters[param_num += 1] = section.match(REGEXP_FORMATTED_REQUIRED_PARAMS)[1]
145
- param_num += 1 # we are using two spaces - param_num += should look for () in regex ? /[^\\](/
146
-
147
- # check for routes formatted: /{regexp} - formated path
148
- elsif section.match REGEXP_FORMATTED_PATH
149
- #create a simple section catcher
150
- @path << ( "\/(" + section.match(REGEXP_FORMATTED_PATH)[1] + ")" )
151
- # add paramater recognition value
152
- param_num += 1 # we are using one space - param_num += should look for () in regex ? /[^\\](/
153
- else
154
- @path << "\/"
155
- @path << section
156
- end
157
- end
158
- unless @fill_parameters.values.include?("id")
159
- @path << optional_section_search
160
- @fill_parameters[param_num += 1] = "id"
161
- @url_array << '(:id)'
162
- end
163
- # set the Regexp and return the final result.
164
- @path = /#{@path}$/
165
- else
166
- raise "Path cannot be initialized - path must be either a string or a regular experssion."
167
- end
168
- return
169
- end
170
-
171
- # this performs the match and assigns the parameters, if required.
172
- def match path
173
- hash = {}
174
- # m = nil
175
- # unless @fill_parameters.values.include?("format")
176
- # if (m = path.match /([^\.]*)\.([^\.\/]+)$/)
177
- # Plezi::Base::Helpers.add_param_to_hash 'format', m[2], hash
178
- # path = m[1]
179
- # end
180
- # end
181
- m = @path.match path
182
- return false unless m
183
- @fill_parameters.each { |k, v| hash[v] = m[k][1..-1] if m[k] && m[k] != '/'.freeze }
184
- hash
185
- end
186
-
187
- ###########
188
- ## class magic methods
189
-
190
- protected
191
-
192
- # injects some magic to the controller
193
- #
194
- # adds the `redirect_to` and `send_data` methods to the controller class, as well as the properties:
195
- # env:: the env recieved by the Rack server.
196
- # params:: the request's parameters.
197
- # cookies:: the request's cookies.
198
- # flash:: an amazing Hash object that sets temporary cookies for one request only - greate for saving data between redirect calls.
199
- #
200
- def self.make_controller_magic(controller, container)
201
- new_class_name = "Plezi__#{controller.name.gsub(/[\:\-\#\<\>\{\}\(\)\s]/ , '_'.freeze)}"
202
- return Module.const_get new_class_name if Module.const_defined? new_class_name
203
- # controller.include Plezi::ControllerMagic
204
- controller.instance_exec(container) {|r| include Plezi::ControllerMagic; }
205
- ret = Class.new(controller) do
206
- include Plezi::Base::ControllerCore
207
- end
208
- Object.const_set(new_class_name, ret)
209
- Module.const_get(new_class_name).reset_routing_cache
210
- ret
211
- end
212
-
213
- end
214
- end
215
-
216
- end
@@ -1,109 +0,0 @@
1
- module Plezi
2
- module Base
3
- module SessionStorage
4
- module_function
5
- # returns a session object
6
- def fetch id
7
- return Plezi::Session.new(id) if Plezi.redis # avoid a local cache if Redis is used.
8
- Iodine::Http::SessionManager::FileSessionStorage.fetch id # use the tmp-file-session logic if Redis isn't present
9
- end
10
- end
11
- end
12
- # A hash like interface for storing request session data.
13
- # The store must implement: store(key, value) (aliased as []=);
14
- # fetch(key, default = nil) (aliased as []);
15
- # delete(key); clear;
16
- class Session
17
-
18
- # The session's lifetime in seconds = 24 hours. This is only true when using the built in support for the Redis persistent storage.
19
- SESSION_LIFETIME = 60*60*24
20
- # called by the Plezi framework to initiate a session with the id requested
21
- def initialize id
22
- @id = id
23
- if id && Plezi.redis
24
- return self
25
- end
26
- failed
27
- end
28
- # returns the session id (the session cookie value).
29
- def id
30
- @id
31
- end
32
- # Get a key from the session data store. If a Redis server is supplied, it will be used to synchronize session data.
33
- #
34
- # Due to scaling considirations, all keys will be converted to strings, so that `"name" == :name` and `1234 == "1234"`.
35
- # If you store two keys that evaluate as the same string, they WILL override each other.
36
- def [] key
37
- key = key.to_s
38
- if conn=Plezi.redis
39
- conn.expire @id, SESSION_LIFETIME
40
- return conn.hget @id, key
41
- end
42
- failed
43
- end
44
- alias :fetch :[]
45
-
46
- # Stores a key in the session's data store. If a Redis server is supplied, it will be used to synchronize session data.
47
- #
48
- # Due to scaling considirations, all keys will be converted to strings, so that `"name" == :name` and `1234 == "1234"`.
49
- # If you store two keys that evaluate as the same string, they WILL override each other.
50
- def []= key, value
51
- return delete key if value.nil?
52
- key = key.to_s
53
- if (conn=Plezi.redis)
54
- conn.hset @id, key, value
55
- conn.expire @id, SESSION_LIFETIME
56
- return value
57
- end
58
- failed
59
- end
60
- alias :store :[]=
61
-
62
- # @return [Hash] returns a shallow copy of the current session data as a Hash.
63
- def to_h
64
- if (conn=Plezi.redis)
65
- conn.expire @id, SESSION_LIFETIME
66
- return conn.hgetall(@id)
67
- end
68
- failed
69
- end
70
- alias :refresh :to_h
71
-
72
- # @return [String] returns the Session data in YAML format.
73
- def to_s
74
- if (conn=Plezi.redis)
75
- conn.expire @id, SESSION_LIFETIME
76
- return conn.hgetall(@id).to_yaml
77
- end
78
- failed
79
- end
80
-
81
- # Removes a key from the session's data store.
82
- def delete key
83
- key = key.to_s
84
- if (conn=Plezi.redis)
85
- conn.expire @id, SESSION_LIFETIME
86
- ret = conn.hget @id, key
87
- conn.hdel @id, key
88
- return ret
89
- end
90
- failed
91
- end
92
-
93
- # Clears the session's data.
94
- def clear
95
- if (conn=Plezi.redis)
96
- return conn.del @id
97
- end
98
- failed
99
- end
100
-
101
- protected
102
-
103
- def failed
104
- raise 'Redis connection failed while using Redis Session Storage.'
105
-
106
- end
107
- end
108
- Iodine::Http::SessionManager.storage = Plezi::Base::SessionStorage
109
- end
@@ -1,156 +0,0 @@
1
- module Plezi
2
-
3
- ####
4
- # a skeleton for a RESTful controller class
5
- #
6
- # you dont have to inherit this or use this, this is stub code.
7
- #
8
- # it can also be used for non RESTful requests by utilizing only the
9
- # index method or adding public methods that aren't RESTful reserved (and don't start with '_').
10
- #
11
- # if a method returns false, a 404 error (not found) is assumed. and routes continue to search.
12
- #
13
- # otherwise, the method's return value is added to the response body. Normally, the method will return a String object.
14
- #
15
- # methods should return the response's body string as their last value, unless
16
- # they have correctly edited the response (in which case they should return `true`).
17
- #
18
- class StubRESTCtrl
19
-
20
- # every request that routes to this controller will create a new instance
21
- def initialize
22
- end
23
-
24
- # called when request is GET and params\[:id] isn't defined
25
- def index
26
- "Hello World!"
27
- end
28
-
29
- # called when request is GET and params\[:id] exists
30
- def show
31
- "nothing to show for id - #{params[:id]} - with parameters: #{params.to_s}"
32
- end
33
-
34
- # called when request is GET and params\[:id] == "new" (used for the "create new object" form).
35
- def new
36
- "Should we make something new?"
37
- end
38
-
39
- # called when request is POST or PUT and params\[:id] isn't defined or params\[:id] == "new"
40
- def save
41
- "save called - creating a new object."
42
- end
43
-
44
- # called when request is POST or PUT and params\[:id] exists and isn't "new"
45
- def update
46
- "update called - updating #{params[:id]}"
47
- end
48
-
49
- # called when request is DELETE (or params[:_method] == 'delete') and request.params\[:id] exists
50
- def delete
51
- "delete called - deleting object #{params[:id]}"
52
- end
53
-
54
- # called before request is called
55
- #
56
- # if method returns false (not nil), controller exists
57
- # and routes continue searching
58
- def before
59
- true
60
- end
61
- # called after request is completed
62
- #
63
- # if method returns false (not nil), the request body is cleared,
64
- # the controller exists and routes continue searching
65
- def after
66
- true
67
- end
68
- end
69
-
70
- ####
71
- # a skeleton for a WebSocket controller class which uses REST to emulate long XHR pulling
72
- #
73
- # you dont have to inherit this or use this, this is example/stub code.
74
- #
75
- # WebSockets Controllers and RESTful Controllers can be the same class
76
- # (the same route can handle both a regular request and a WebSocket request).
77
- #
78
- # if the pre_connect method returns false, the WebSockets connection will be refused and the remaining routes will be attempted.
79
- #
80
- class StubWSCtrl
81
-
82
- # every request that routes to this controller will create a new instance
83
- def initialize
84
- end
85
-
86
- # called before the protocol is swithed from HTTP to WebSockets.
87
- #
88
- # this allows setting headers, cookies and other data (such as authentication)
89
- # prior to opening a WebSocket.
90
- #
91
- # if the method returns false, the connection will be refused and the remaining routes will be attempted.
92
- def pre_connect
93
- true
94
- end
95
-
96
- # called immediately after a WebSocket connection has been established.
97
- # it blocks all the connection's actions until the `on_open` initialization is finished.
98
- def on_open
99
- true
100
- end
101
-
102
- # called when new data is recieved
103
- #
104
- # data is a string that contains binary or UTF8 (message dependent) data.
105
- def on_message data
106
- broadcast :_push, data
107
- _push "your message was sent: #{data.to_s}"
108
- end
109
-
110
- # called once, AFTER the connection was closed.
111
- def on_close
112
- end
113
-
114
- # called once, during **server shutdown**, BEFORE the connection is closed.
115
- # this will only be called for connections that are open while the server is shutting down.
116
- def on_shutdown
117
- end
118
-
119
- # a demo event method that recieves a broadcast from instance siblings.
120
- #
121
- # methods that are protected and methods that start with an underscore are hidden from the router
122
- # BUT, broadcasted methods must be public (or the broadcast will quietly fail)... so we have to use
123
- # the _underscore for this method.
124
- def _push data
125
- response << data.to_s
126
- end
127
-
128
- # a CLASS level callback that will be called when a unicast doesn't find it's target.
129
- #
130
- # the lack of this callback being called does NOT imply that the unicast was processed without errors,
131
- # it's only called if the target itself wasn't found.
132
- def self.failed_unicast target, method, arguments_array
133
- end
134
-
135
- #####
136
- ## It is possible to use RESTful methods to help emulate long XHR pulling.
137
- ## a RESTful controller can also be a WebSockets controller (these are not exclusive qualities).
138
-
139
- # called when request is GET and params\[:id] isn't defined
140
- def index
141
- "This stub controller is used to test websockets.\n\r\n\rVisit http://www.websocket.org/echo.html for WS testing.\n\r\n\rOr add a nickname to the route to view long-pulling stub. i.e.: #{request.base_url}/nickname"
142
- end
143
-
144
- # called when request is GET and params\[:id] exists (unless params\[:id] == "new").
145
- def show
146
- {message: 'read_chat', data: {id: params[:id], token: cookies['example_token'], example_data: 'we missed you.'}}.to_json
147
- end
148
- # called when request is POST / PUT and params\[:id] exists
149
- def update
150
- # assumes body is JSON - more handling could be done using the params (which hold parsed JSON data).
151
- broadcast :_push, request[:body]
152
- {message: 'write_chat', data: {id: params[:id], token: cookies['example_token'], example_data: 'message sent.'}}.to_json
153
- end
154
-
155
- end
156
- end