plezi 0.7.3 → 0.7.4

Sign up to get free protection for your applications and to get access to all the features.
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