plezi 0.7.3 → 0.7.4

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: d2c1ce05a4f21add0356e4feb915c3f559ac29b7
4
- data.tar.gz: 949097175113449016158060ae646d3b94124469
3
+ metadata.gz: e7b74f28a320e2558c0478929989d9904ed191aa
4
+ data.tar.gz: 3231b1fca07d1ac55bfd14f1eff40be0cb0a7154
5
5
  SHA512:
6
- metadata.gz: 60e319eb716785ff1363ded7fa6aa8a2d8e81da7239598c3ce17bab2bcb996ecda364b15ccac56b0bf1f66c260b1018a4cf04cd1249647220dd113b17868247d
7
- data.tar.gz: 694bc16bb7c79cc83a90e77a6ef0880769e1a22d70d48656367592731a6aaa0f0ad4a5d1048691fba23c5ed66283403c18ade96639bfe96ce9fe11d2651cace8
6
+ metadata.gz: bd7d3987c60cad451d7860296ece6fc2e19b24922c318a344fde248832d7bd7b91f956db0c6f600ccca185d7bb43401973036a79b4a8f8c405b08ce9a2a524f7
7
+ data.tar.gz: 5ca2c5850793f1c23ddec678499989e2166062c9b4c67ae1deb2232eaa9db0069235bfaaad7482aff4728dc2ffaba59012f4ab8e0c22d278f5d7bdb44e807c1a
@@ -2,11 +2,21 @@
2
2
 
3
3
  ***
4
4
 
5
+ Change log v.0.7.4
6
+
7
+ **change/fix**: it seems that behavior is more predictable when routes macgic parameters are non-persistent between routes. The old behavior (persistent parameters) is now limited to re-write routes.
8
+
9
+ **fix**: an error was introduced when using paramd\[:id] with a Fixnum. This was caused by the router attempting to search for a method by that name before using the parameter as an :id. This is now fixed by temporarily converting the Fixnum to a string before the required converstion to a symbol.
10
+
11
+ **experimental feature**: added the method `def_special_method`, which can be used in controller classes to create specially named paths, defying Ruby naming restrictions, such as: "play-now", "text.me" etc'. This is an EXPERIMENTAL feature which might be limited in future releases (specifically limited to names without dots '.', in case of future formatting support).
12
+
13
+ ***
14
+
5
15
  Change log v.0.7.3
6
16
 
7
17
  **major fix**: Fixed a conflict in the controller namespaces and caching system, which caused routing and Redis connection errors. The errors were resolved by moving the caching to the Framework's global caching system.
8
18
 
9
- **fix + feature**: It is now possible to dynamically add or remove routes from existing controllers. As you know, Plezi controllers behave like "smart folders" and their public methods are automatically published as routes. But - That routing tables is cached. Now the cache is automatically reset whenever a method is added or removed from the controller, or, you can reset the controller's routing cache by calling the controller class method #reset_routing_cache. This allows you to dynamically add or remove routes from existing controllers.
19
+ **fix + feature**: It is now possible to dynamically add or remove routes from existing controllers. As you know, Plezi controllers behave like "smart folders" and their public methods are automatically published as routes. But - That routing table is cached. Now the cache is automatically reset whenever a method is added or removed from the controller, or, you can reset the controller's routing cache by calling the controller class method #reset_routing_cache. This allows you to dynamically add or remove routes from existing controllers.
10
20
 
11
21
  **fix**: fixed as issue with utf-8 data in the cookie and flash data, where utf-8 data wasn't encoded properly as an ASCII string before being sent in the HTTP headers.
12
22
 
data/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # Plezi, The Rack Free Ruby HTTP & Websocket Framework
1
+ # Plezi, The Rack Free Ruby framework for realtime web-apps
2
2
  [![Gem Version](https://badge.fury.io/rb/plezi.svg)](http://badge.fury.io/rb/plezi)
3
3
  [![Inline docs](http://inch-ci.org/github/boazsegev/plezi.svg?branch=master)](http://inch-ci.org/github/boazsegev/plezi)
4
4
 
@@ -94,7 +94,7 @@ Remember to connect to the service from at least two browser windows - to truly
94
94
 
95
95
  # do you need automated redis support?
96
96
  # require 'redis'
97
- # ENV['PL_REDIS_URL'] = "http://user:password@localhost:6379"
97
+ # ENV['PL_REDIS_URL'] = "redis://user:password@localhost:6379"
98
98
 
99
99
  class BroadcastCtrl
100
100
  def index
@@ -109,7 +109,10 @@ Remember to connect to the service from at least two browser windows - to truly
109
109
  def _send_message data
110
110
  response << data
111
111
  end
112
- def people
112
+ def hello
113
+ 'Hello!'
114
+ end
115
+ def_special_method "humans.txt" do
113
116
  'I made this :)'
114
117
  end
115
118
  end
@@ -119,7 +122,7 @@ Remember to connect to the service from at least two browser windows - to truly
119
122
  route '/', BroadcastCtrl
120
123
  ```
121
124
 
122
- method names starting with an underscore ('_') will NOT be made public by the router: so while '/people' is public ( [try it](http://localhost:3000/people) ), '/_send_message' will return a 404 not found error ( [try it](http://localhost:3000/_send_message) ).
125
+ method names starting with an underscore ('_') will NOT be made public by the router: so while both '/hello' and '/humans.txt' are public ( [try it](http://localhost:3000/humans.txt) ), '/_send_message' will return a 404 not found error ( [try it](http://localhost:3000/_send_message) ).
123
126
 
124
127
  ## Native HTTP streaming with Asynchronous events
125
128
 
@@ -175,7 +178,7 @@ Plezi can be used to create virtual hosts for the same service:
175
178
  listen
176
179
  host 'localhost', alias: 'localhost2'
177
180
 
178
- shared_route '/people' do |req, res|
181
+ shared_route '/humans.txt' do |req, res|
179
182
  res << "we are people - shared by all routes."
180
183
  end
181
184
 
@@ -195,8 +198,8 @@ Now visit:
195
198
 
196
199
  * [http://127.0.0.1:3000/]( http://127.0.0.1:3000/ )
197
200
  * [http://localhost:3000/]( http://localhost:3000/ )
198
- * [http://127.0.0.1:3000/people]( http://127.0.0.1:3000/people )
199
- * [http://localhost:3000/people]( http://localhost:3000/people )
201
+ * [http://127.0.0.1:3000/humans.txt]( http://127.0.0.1:3000/humans.txt )
202
+ * [http://localhost:3000/humans.txt]( http://localhost:3000/humans.txt )
200
203
 
201
204
  ## Plezi Logging
202
205
 
@@ -242,32 +245,19 @@ Asynchronous callbacks (works only while services are active and running):
242
245
  # an asynchronous method call with an optional callback block
243
246
  PL.callback(Kernel, :puts, "Plezi will start eating our code once we exit terminal.") {puts 'first output finished'}
244
247
 
245
- ## Food for thought - advanced controller uses
248
+ ## Re-write Routes
246
249
 
247
- Here's some food for thought - code similar to something actually used at some point while developing the applicatio template used by `plezi new myapp`:
250
+ Plezi supports special routes used to re-write the request and extract parameters for all future routes.
248
251
 
249
- require 'plezi'
252
+ This allows you to create path prefixes which will be removed once their information is extracted.
250
253
 
251
- # this controller will re-write the request to extract data,
252
- # and then it will fail, so that routing continues.
253
- #
254
- # this is here just for the demo.
255
- #
256
- class ReWriteController
257
- # using the before filter and regular expressions to make some changes.
258
- def before
259
- # extract the fr and en locales.
260
- result = request.path.match /^\/(en|fr)($|\/.*)/
261
-
262
- if result
263
- params[:locale] = result[1]
264
- request.path = result[2]
265
- end
254
+ This is great for setting global information such as internationalization (I18n) locales.
266
255
 
267
- # let the routing continue.
268
- return false
269
- end
270
- end
256
+ By using a route with the a 'false' controller, the parameters extracted are automatically retained.
257
+
258
+ *(Older versions of Plezi allowed this behavior for all routes, but it was deprecated starting version 0.7.4).
259
+
260
+ require 'plezi'
271
261
 
272
262
  class Controller
273
263
  def index
@@ -286,31 +276,23 @@ Here's some food for thought - code similar to something actually used at some p
286
276
  end
287
277
  def delete
288
278
  return "Mon Dieu! Mon français est mauvais!" if params[:locale] == 'fr'
289
- "did you try /#{params["id"]}/?_method=delete or does your server support a native DELETE method?"
279
+ "did you try #{request.base_url + request.original_path}?_method=delete or does your server support a native DELETE method?"
290
280
  end
291
281
  end
292
282
 
293
283
  listen
294
284
 
295
- # we run the ReWriteController first, to rewrite the path for all the remaining routes.
296
- #
297
- # this is here just for the demo...
298
- #
299
- # ...in this specific case, it is possible to dispense with the ReWriteController class
300
- # and write:
301
- #
302
- # route '/(:locale){fr|en}/*', false
303
- #
304
- # the false controller acts as a simple path re-write that
305
- # deletes everything before the '*' sign (the catch-all).
306
- #
307
- route '*' , ReWriteController
285
+ # this is our re-write route.
286
+ # it will extract the locale and re-write the request.
287
+ route '/:locale{fr|en}/*', false
308
288
 
309
289
  # this route takes a regular expression that is a simple math calculation
310
290
  # (calculator)
291
+ #
292
+ # it is an example for a Proc controller, which can replace the Class controller.
311
293
  route /^\/[\d\+\-\*\/\(\)\.]+$/ do |request, response|
312
294
  message = (request.params[:locale] == 'fr') ? "La solution est" : "My Answer is"
313
- response << "#{message}: #{eval(request.path[1..-1])}"
295
+ response << "#{message}: #{eval( request.path[1..-1] )}"
314
296
  end
315
297
 
316
298
  route "/users" , Controller
@@ -322,10 +304,15 @@ try:
322
304
  * [http://localhost:3000/](http://localhost:3000/)
323
305
  * [http://localhost:3000/fr](http://localhost:3000/fr)
324
306
  * [http://localhost:3000/users/hello](http://localhost:3000/users/hello)
325
- * [http://localhost:3000/(5+5*20-15)/9](http://localhost:3000/(5+5*20-15)/9)
326
- * [http://localhost:3000/fr/(5+5*20-15)/9](http://localhost:3000/fr/(5+5*20-15)/9)
307
+ * [http://localhost:3000/users/(5+5*20-15)/9.0](http://localhost:3000/users/(5+5*20-15)/9.0)
308
+ * [http://localhost:3000/(5+5*20-15)/9.0](http://localhost:3000/(5+5*20-15)/9)
309
+ * [http://localhost:3000/fr/(5+5*20-15)/9.0](http://localhost:3000/fr/(5+5*20-15)/9)
327
310
  * [http://localhost:3000/users/hello?_method=delete](http://localhost:3000/users/hello?_method=delete)
328
311
 
312
+ As you can see in the example above, Plezi supports Proc routes as well as Class controller routes.
313
+
314
+ Please notice that there are some differences between the two. Proc routes less friedly, but plenty powerful and are great for custom 404 error handling.
315
+
329
316
  ## Plezi Settings
330
317
 
331
318
  Plezi is ment to be very flexible. please take a look at the Plezi Module for settings you might want to play with (max_threads, idle_sleep, create_logger) or any monkey patching you might enjoy.
@@ -120,6 +120,8 @@ end
120
120
  #
121
121
  # thanks to Russ Olsen for his ideas for a DSL and his blog post at:
122
122
  # http://www.jroller.com/rolsen/entry/building_a_dsl_in_ruby1
123
+ #
124
+ # ...he doesn't know it, but he inspired a revolution.
123
125
  ##############################################################################
124
126
  module Plezi
125
127
  end
@@ -66,6 +66,11 @@ module Plezi
66
66
  LOCK.synchronize { CACHE_STORE.delete filename } # if CACHE_STORE[filename]
67
67
  end
68
68
 
69
+ # clears all cached data.
70
+ def clear_cache! filename
71
+ LOCK.synchronize { CACHE_STORE.clear } # if CACHE_STORE[filename]
72
+ end
73
+
69
74
  # returns true if the filename is cached.
70
75
  def cached? filename
71
76
  !CACHE_STORE[filename].nil?
@@ -153,6 +153,19 @@ def shared_route(path, controller = nil, &block)
153
153
  Plezi::DSL.shared_route(path, controller, &block)
154
154
  end
155
155
 
156
+ # defines a method with a special name, such as "humens.txt".
157
+ #
158
+ # this could be used in controller classes, to define special routes which might defy
159
+ # normal Ruby naming conventions, such as "/welcome-home", "/play!", etc'
160
+ #
161
+ # could also be used to define methods with special formatting, such as "humans.txt",
162
+ # until a more refined way to deal with formatting will be implemented.
163
+ def def_special_method name, obj=self, &block
164
+ obj.instance_eval { define_method name.to_s.to_sym, &block }
165
+ end
166
+
167
+
168
+
156
169
  # finishes setup of the servers and starts them up. This will hange the proceess.
157
170
  #
158
171
  # this method is called automatically by the Plezi framework.
@@ -170,8 +183,17 @@ def start_services
170
183
  Plezi.start_services
171
184
  end
172
185
 
186
+ # restarts the Plezi app with the same arguments as when it was started.
187
+ #
188
+ # EXPERIMENTAL
189
+ def restart_plezi_app
190
+ exec "/usr/bin/env ruby #{$PL_SCRIPT} #{$PL_ARGV.join ' '}"
191
+ end
192
+
173
193
  # sets to start the services once dsl script is finished loading.
174
194
  at_exit { start_services } unless ( defined?(NO_PLEZI_AUTO_START) || defined?(BUILDING_PLEZI_TEMPLATE) || defined?(PLEZI_ON_RACK) )
175
195
 
176
196
  # sets a name for the process (on some systems).
197
+ $PL_SCRIPT = $0
198
+ $PL_ARGV = $*.dup
177
199
  $0="Plezi (Ruby)"
@@ -37,6 +37,7 @@ module Plezi
37
37
  run_every(5 , Plezi.method(:clear_connections)) #{info "Cleared inactive Connections"}
38
38
  run_every 3600 , GC.method(:start)
39
39
  # run_every( 1 , Proc.new() { Plezi.info "#{IO_CONNECTION_DIC.length} active connections ( #{ IO_CONNECTION_DIC.select{|k,v| v.protocol.is_a?(WSProtocol)} .length } websockets)." })
40
+ # run_every 10 , -> {Plezi.info "Cache report: #{CACHE_STORE.length} objects cached." }
40
41
  (max_threads).times { Thread.new { thread_cycle until exit_flag } }
41
42
 
42
43
  # Thread.new { check_connections until SERVICES.empty? }
@@ -131,11 +131,11 @@ module Plezi
131
131
  true
132
132
  end
133
133
 
134
- # renders a template file (.erb/.haml) or an html file (.html) to text
135
- # for example, to render the file `body.html.haml` with the layout `main_layout.html.haml`:
134
+ # renders a template file (.slim/.erb/.haml) or an html file (.html) to text
135
+ # for example, to render the file `body.html.slim` with the layout `main_layout.html.haml`:
136
136
  # render :body, layout: :main_layout
137
137
  #
138
- # or, for example, to render the file `json.js.haml`
138
+ # or, for example, to render the file `json.js.slim`
139
139
  # render :json, type: 'js'
140
140
  #
141
141
  # or, for example, to render the file `template.haml`
@@ -148,7 +148,7 @@ module Plezi
148
148
  # options aceept the following keys:
149
149
  # type:: the types for the `:layout' and 'template'. can be any extention, such as `"json"`. defaults to `"html"`.
150
150
  # layout:: a layout template that has at least one `yield` statement where the template will be rendered.
151
- # locale:: the I18n locale for the render. (defaults to params[:locale]) - only if the I18n gem namespace is defined (`require 'i18n'`).
151
+ # locale:: the I18n locale for the render. (defaults to params\[:locale]) - only if the I18n gem namespace is defined (`require 'i18n'`).
152
152
  #
153
153
  # if template is a string, it will assume the string is an
154
154
  # absolute path to a template file. it will NOT search for the template but might raise exceptions.
@@ -193,7 +193,7 @@ module Plezi
193
193
  # set DELETE method if simulated
194
194
  request.request_method = 'DELETE' if params[:_method].to_s.downcase == 'delete'
195
195
  # respond to special :id routing
196
- return params[:id].to_sym if params[:id] && self.class.available_public_methods.include?(params[:id].to_sym)
196
+ return params[:id].to_s.to_sym if params[:id] && self.class.available_public_methods.include?(params[:id].to_s.to_sym)
197
197
  #review general cases
198
198
  case request.request_method
199
199
  when 'GET', 'HEAD'
@@ -302,7 +302,11 @@ module Plezi
302
302
 
303
303
  # reviews the Redis connection, sets it up if it's missing and returns the Redis connection.
304
304
  #
305
- # todo: review thread status? (incase an exception killed it)
305
+ # a Redis connection will be automatically created if the `ENV['PL_REDIS_URL']` is set.
306
+ # for example:
307
+ # ENV['PL_REDIS_URL'] = ENV['REDISCLOUD_URL']`
308
+ # or
309
+ # ENV['PL_REDIS_URL'] = "redis://username:password@my.host:6379"
306
310
  def redis_connection
307
311
  # return false unless defined?(Redis) && ENV['PL_REDIS_URL']
308
312
  # return @@redis if defined?(@@redis_sub_thread) && @@redis
@@ -16,6 +16,7 @@ module Plezi
16
16
  def on_request request
17
17
  fill_parameters = match request.path
18
18
  return false unless fill_parameters
19
+ old_params = request.params.dup
19
20
  fill_parameters.each {|k,v| HTTP.add_param_to_hash k, v, request.params }
20
21
  ret = false
21
22
  response = HTTPResponse.new request
@@ -29,7 +30,7 @@ module Plezi
29
30
  return false
30
31
  end
31
32
  unless ret
32
- request.params.delete :id if fill_parameters['id']
33
+ request.params.replace old_params unless fill_parameters.empty?
33
34
  return false
34
35
  end
35
36
  response.try_finish
@@ -180,6 +180,12 @@ module Plezi
180
180
  @parser_data[:path] = @parser_data[:original_path].chomp('/')
181
181
  @parser_data[:original_path].freeze
182
182
 
183
+ # the following can be used to extract the request's 'format':
184
+ # /(^.*)(\.[^\.\/]*)$/.match @parser_data[:path]
185
+ # ...? should this be done? Could be limited to certain formats:
186
+ # /(^.*)(\.(txt|html|json|js|xml|xhtml|csv))$/.match @parser_data[:path]
187
+ # ... even worst?
188
+
183
189
  HTTP.make_utf8! @parser_data[:host_name] if @parser_data[:host_name]
184
190
  HTTP.make_utf8! @parser_data[:query]
185
191
 
@@ -1,3 +1,3 @@
1
1
  module Plezi
2
- VERSION = "0.7.3"
2
+ VERSION = "0.7.4"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: plezi
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.3
4
+ version: 0.7.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Boaz Segev
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-03-20 00:00:00.000000000 Z
11
+ date: 2015-03-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler