em-midori 0.1.7.1 → 0.1.8

Sign up to get free protection for your applications and to get access to all the features.
Files changed (39) hide show
  1. checksums.yaml +4 -4
  2. data/lib/midori/api.rb +33 -60
  3. data/lib/midori/api_engine.rb +9 -36
  4. data/lib/midori/const.rb +30 -0
  5. data/lib/midori/core_ext/proc.rb +4 -4
  6. data/lib/midori/core_ext/promise.rb +10 -10
  7. data/lib/midori/core_ext/promise_exception.rb +3 -3
  8. data/lib/midori/core_ext/safe_require.rb +2 -2
  9. data/lib/midori/extension/file.rb +2 -2
  10. data/lib/midori/extension/ohm.rb +1 -1
  11. data/lib/midori/extension/postgres.rb +12 -12
  12. data/lib/midori/extension/redis.rb +4 -4
  13. data/lib/midori/extension/sequel.rb +3 -3
  14. data/lib/midori/middleware.rb +1 -1
  15. data/lib/midori/request.rb +2 -2
  16. data/lib/midori/runner.rb +4 -4
  17. data/lib/midori/sandbox.rb +8 -8
  18. data/lib/midori/server.rb +4 -4
  19. data/lib/midori/version.rb +1 -1
  20. data/lib/midori/websocket.rb +14 -14
  21. data/tutorial/README.md +11 -0
  22. data/tutorial/SUMMARY.md +28 -0
  23. data/tutorial/advanced/custom_extensions.md +0 -0
  24. data/tutorial/advanced/deploying_for_production.md +0 -0
  25. data/tutorial/advanced/error_handling.md +0 -0
  26. data/tutorial/advanced/rerl.md +0 -0
  27. data/tutorial/advanced/scaling_project.md +0 -0
  28. data/tutorial/advanced/unit_testing.md +0 -0
  29. data/tutorial/essentials/extensions.md +0 -0
  30. data/tutorial/essentials/getting_started.md +27 -0
  31. data/tutorial/essentials/installation.md +98 -0
  32. data/tutorial/essentials/middlewares.md +0 -0
  33. data/tutorial/essentials/request_handling.md +71 -0
  34. data/tutorial/essentials/routing.md +136 -0
  35. data/tutorial/essentials/runner.md +0 -0
  36. data/tutorial/meta/comparison_with_other_frameworks.md +0 -0
  37. data/tutorial/meta/join_the_midori_community.md +0 -0
  38. data/tutorial/meta/next_steps.md +0 -0
  39. metadata +29 -6
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: a1141fbd9e570a32ea33eb07ad6687a8b60bf36e
4
- data.tar.gz: a8c597845b57be046d0ec3e438e5d83694c5df84
3
+ metadata.gz: bded68c0e7831eb9e36ee2b49dec6c61c760a815
4
+ data.tar.gz: de5f760feffc996aa88443e3db67eab589d179d8
5
5
  SHA512:
6
- metadata.gz: 7dca5dee8b994779f9b684155bb20ac948d068e38b35e2f361a6ca01457b85ac5b1227c2e35ebf862b317343ced90cb567ec82d794e27f71a1c7bcf24c81162c
7
- data.tar.gz: 609351a34a8741f942afa9deda5ebf097b5cfdffd17fb153999073e43d9b6bd902ca601237032714ef6a4f4ade9fdd16a4befdebdb9615a34718131a0ec9b8e0
6
+ metadata.gz: 6ffe68ce957c773adf24da6a5e0c4c94deca32d0a617e29ee9ac10eacf4883e5e1d6cf0c94b0698fa30e9bde26599f4425bd081b38d945d0baa6b97a3d4a620e
7
+ data.tar.gz: 220b8c5f8ec1af61be67526d24975ccd1387384afd41c7014f7176a4bf2468c4fd061475eb147fd9bc8655e5f06b5b2677f382774bc3d8d1f954ff4b98a8b5b8
@@ -9,38 +9,11 @@ class Midori::API
9
9
  attr_accessor :routes, :scope_middlewares
10
10
 
11
11
  # Init private variables of class
12
- # @return [ nil ] nil
12
+ # @return [nil] nil
13
13
  def class_initialize
14
- @routes = {
15
- DELETE: [],
16
- GET: [],
17
- HEAD: [],
18
- POST: [],
19
- PUT: [],
20
- CONNECT: [],
21
- OPTIONS: [],
22
- TRACE: [],
23
- COPY: [],
24
- LOCK: [],
25
- MKCOL: [],
26
- MOVE: [],
27
- PROPFIND: [],
28
- PROPPATCH: [],
29
- UNLOCK: [],
30
- REPORT: [],
31
- MKACTIVITY: [],
32
- CHECKOUT: [],
33
- MERGE: [],
34
- :'M-SEARCH' => [],
35
- NOTIFY: [],
36
- SUBSCRIBE: [],
37
- UNSUBSCRIBE: [],
38
- PATCH: [],
39
- PURGE: [],
40
- WEBSOCKET: [],
41
- EVENTSOURCE: [],
42
- MOUNT: []
43
- }
14
+ @routes = {}
15
+ Midori::Const::ROUTE_METHODS.map {|method| @routes[method] = []}
16
+ @routes[:MOUNT] = []
44
17
  @scope_middlewares = []
45
18
  @temp_middlewares = []
46
19
  nil
@@ -57,9 +30,9 @@ class Midori::API
57
30
  def delete(path, &block) end
58
31
 
59
32
  # Add GET method as a DSL for route definition
60
- # @param [ String ] path Accepts as part of path in route definition
33
+ # @param [String] path Accepts as part of path in route definition
61
34
  # @yield what to run when route matched
62
- # @return [ nil ] nil
35
+ # @return [nil] nil
63
36
  # @example String as router
64
37
  # get '/' do
65
38
  # puts 'Hello World'
@@ -77,9 +50,9 @@ class Midori::API
77
50
  def head(path, &block) end
78
51
 
79
52
  # Add POST method as a DSL for route definition
80
- # @param [ String ] path Accepts as part of path in route definition
53
+ # @param [String] path Accepts as part of path in route definition
81
54
  # @yield what to run when route matched
82
- # @return [ nil ] nil
55
+ # @return [nil] nil
83
56
  # @example String as router
84
57
  # post '/' do
85
58
  # puts 'Hello World'
@@ -87,9 +60,9 @@ class Midori::API
87
60
  def post(path, &block) end
88
61
 
89
62
  # Add PUT method as a DSL for route definition
90
- # @param [ String ] path Accepts as part of path in route definition
63
+ # @param [String] path Accepts as part of path in route definition
91
64
  # @yield what to run when route matched
92
- # @return [ nil ] nil
65
+ # @return [nil] nil
93
66
  # @example String as router
94
67
  # put '/' do
95
68
  # puts 'Hello World'
@@ -97,9 +70,9 @@ class Midori::API
97
70
  def put(path, &block) end
98
71
 
99
72
  # Add CONNECT method as a DSL for route definition
100
- # @param [ String ] path Accepts as part of path in route definition
73
+ # @param [String] path Accepts as part of path in route definition
101
74
  # @yield what to run when route matched
102
- # @return [ nil ] nil
75
+ # @return [nil] nil
103
76
  # @example String as router
104
77
  # connect '/' do
105
78
  # puts 'Hello World'
@@ -107,8 +80,8 @@ class Midori::API
107
80
  def connect(path, &block) end
108
81
 
109
82
  # Add OPTIONS method as a DSL for route definition
110
- # @param [ String ] path Accepts as part of path in route definition
111
- # @return [ nil ] nil
83
+ # @param [String] path Accepts as part of path in route definition
84
+ # @return [nil] nil
112
85
  # @example String as router
113
86
  # options '/' do
114
87
  # puts 'Hello World'
@@ -174,7 +147,7 @@ class Midori::API
174
147
  # propfind '/' do
175
148
  # puts 'Hello World'
176
149
  # end
177
- def proppatch(path, &block) end
150
+ def propfind(path, &block) end
178
151
 
179
152
  # Add PROPPATCH method as a DSL for route definition
180
153
  # @param [ String ] path Accepts as part of path in route definition
@@ -266,7 +239,7 @@ class Midori::API
266
239
  # subscribe '/' do
267
240
  # puts 'Hello World'
268
241
  # end
269
- def merge(path, &block) end
242
+ def subscribe(path, &block) end
270
243
 
271
244
  # Add UNSUBSCRIBE method as a DSL for route definition
272
245
  # @param [ String ] path Accepts as part of path in route definition
@@ -299,9 +272,9 @@ class Midori::API
299
272
  def purge(path, &block) end
300
273
 
301
274
  # Add LINK method as a DSL for route definition
302
- # @param [ String ] path Accepts as part of path in route definition
275
+ # @param [String] path Accepts as part of path in route definition
303
276
  # @yield what to run when route matched
304
- # @return [ nil ] nil
277
+ # @return [nil] nil
305
278
  # @example String as router
306
279
  # link '/' do
307
280
  # puts 'Hello World'
@@ -309,9 +282,9 @@ class Midori::API
309
282
  def link(path, &block) end
310
283
 
311
284
  # Add UNLINK method as a DSL for route definition
312
- # @param [ String ] path Accepts as part of path in route definition
285
+ # @param [String] path Accepts as part of path in route definition
313
286
  # @yield what to run when route matched
314
- # @return [ nil ] nil
287
+ # @return [nil] nil
315
288
  # @example String as router
316
289
  # unlink '/' do
317
290
  # puts 'Hello World'
@@ -319,9 +292,9 @@ class Midori::API
319
292
  def unlink(path, &block) end
320
293
 
321
294
  # Add WEBSOCKET method as a DSL for route definition
322
- # @param [ String ] path Accepts as part of path in route definition
295
+ # @param [String] path Accepts as part of path in route definition
323
296
  # @yield what to run when route matched
324
- # @return [ nil ] nil
297
+ # @return [nil] nil
325
298
  # @example String as router
326
299
  # websocket '/' do
327
300
  # puts 'Hello World'
@@ -329,8 +302,8 @@ class Midori::API
329
302
  def websocket(path, &block) end
330
303
 
331
304
  # Add EVENTSOURCE method as a DSL for route definition
332
- # @param [ String ] path Accepts as part of path in route definition
333
- # @return [ nil ] nil
305
+ # @param [String] path Accepts as part of path in route definition
306
+ # @return [nil] nil
334
307
  # @example String as router
335
308
  # eventsource '/' do
336
309
  # puts 'Hello World'
@@ -338,9 +311,9 @@ class Midori::API
338
311
  def eventsource(path, &block) end
339
312
 
340
313
  # Mount a route prefix with another API defined
341
- # @param [ String ] prefix prefix of the route String
342
- # @param [ Class ] api inherited from Midori::API
343
- # @return [ nil ] nil
314
+ # @param [String] prefix prefix of the route String
315
+ # @param [Class] api inherited from Midori::API
316
+ # @return [nil] nil
344
317
  def mount(prefix, api)
345
318
  raise ArgumentError if prefix == '/' # Cannot mount route API
346
319
  @routes[:MOUNT] << [prefix, api]
@@ -348,9 +321,9 @@ class Midori::API
348
321
  end
349
322
 
350
323
  # Definitions for global error handler
351
- # @param [ Class ] error Error class, must be inherited form StandardError
324
+ # @param [Class] error Error class, must be inherited form StandardError
352
325
  # @yield what to do to deal with error
353
- # @yieldparam [ StandardError ] e the detailed error
326
+ # @yieldparam [StandardError] e the detailed error
354
327
  # @example Basic Usage
355
328
  # capture Midori::InternalError do |e|
356
329
  # Midori::Response(500, {}, e.backtrace)
@@ -361,10 +334,10 @@ class Midori::API
361
334
  end
362
335
 
363
336
  # Implementation of route DSL
364
- # @param [ String ] method HTTP method
365
- # @param [ String, Regexp ] path path definition
366
- # @param [ Proc ] block process to run when route matched
367
- # @return [ nil ] nil
337
+ # @param [String] method HTTP method
338
+ # @param [String, Regexp] path path definition
339
+ # @param [Proc] block process to run when route matched
340
+ # @return [nil] nil
368
341
  def add_route(method, path, block)
369
342
  # Argument check
370
343
  raise ArgumentError unless path.is_a?String
@@ -1,42 +1,15 @@
1
1
  ##
2
2
  # Merge and manage all APIs.
3
- # @attr [ Hash ] routes A hash of all routes merged
3
+ # @attr [Hash] routes A hash of all routes merged
4
4
  class Midori::APIEngine
5
5
  attr_accessor :routes
6
6
 
7
7
  # Init an API Engine
8
- # @param [ Class ] root_api API inherited from [ Midori::API ]
9
- # @param [ Symbol ] type type mustermann support
8
+ # @param [Class] root_api API inherited from [Midori::API]
9
+ # @param [Symbol] type type mustermann support
10
10
  def initialize(root_api, type = :sinatra)
11
- @routes = {
12
- DELETE: [],
13
- GET: [],
14
- HEAD: [],
15
- POST: [],
16
- PUT: [],
17
- CONNECT: [],
18
- OPTIONS: [],
19
- TRACE: [],
20
- COPY: [],
21
- LOCK: [],
22
- MKCOL: [],
23
- MOVE: [],
24
- PROPFIND: [],
25
- PROPPATCH: [],
26
- UNLOCK: [],
27
- REPORT: [],
28
- MKACTIVITY: [],
29
- CHECKOUT: [],
30
- MERGE: [],
31
- :'M-SEARCH' => [],
32
- NOTIFY: [],
33
- SUBSCRIBE: [],
34
- UNSUBSCRIBE: [],
35
- PATCH: [],
36
- PURGE: [],
37
- WEBSOCKET: [],
38
- EVENTSOURCE: []
39
- }
11
+ @routes = {}
12
+ Midori::Const::ROUTE_METHODS.map {|method| @routes[method] = []}
40
13
  @root_api = root_api
41
14
  @type = type
42
15
  @routes = merge('', root_api, [])
@@ -66,10 +39,10 @@ class Midori::APIEngine
66
39
  end
67
40
 
68
41
  # Process after receive data from client
69
- # @param request [ Midori::Request ] Http Raw Request
70
- # @param connection [ EM::Connection ] A connection created by EventMachine
71
- # @return [ Midori::Response ] Http Response
72
- # @raise [ Midori::Error::NotFound ] If no route matched
42
+ # @param request [Midori::Request] Http Raw Request
43
+ # @param connection [EM::Connection] A connection created by EventMachine
44
+ # @return [Midori::Response] Http Response
45
+ # @raise [Midori::Error::NotFound] If no route matched
73
46
  def receive(request, connection = nil)
74
47
  @routes[request.method].each do |route|
75
48
  params = route.path.params(request.path)
@@ -84,4 +84,34 @@ module Midori::Const
84
84
  'Upgrade' => 'websocket',
85
85
  'Connection' => 'Upgrade'
86
86
  }
87
+
88
+ ROUTE_METHODS = %i(
89
+ DELETE
90
+ GET
91
+ HEAD
92
+ POST
93
+ PUT
94
+ CONNECT
95
+ OPTIONS
96
+ TRACE
97
+ COPY
98
+ LOCK
99
+ MKCOL
100
+ MOVE
101
+ PROPFIND
102
+ PROPPATCH
103
+ UNLOCK
104
+ REPORT
105
+ MKACTIVITY
106
+ CHECKOUT
107
+ MERGE
108
+ M-SEARCH
109
+ NOTIFY
110
+ SUBSCRIBE
111
+ UNSUBSCRIBE
112
+ PATCH
113
+ PURGE
114
+ WEBSOCKET
115
+ EVENTSOURCE
116
+ )
87
117
  end
@@ -1,12 +1,12 @@
1
1
  ##
2
2
  # Meta-programming Proc for Syntactic Sugars
3
3
  class Proc
4
- # Convert [ Proc ] to [ Lambda ]
5
- # @param [ Object ] instance the context
6
- # @return [ Lambda ] Lambda converted
4
+ # Convert [Proc] to [Lambda]
5
+ # @param [Object] instance the context
6
+ # @return [Lambda] Lambda converted
7
7
  # @note Converting [Proc] to [Lambda] may have incorrect behaviours on corner cases.
8
8
  # @note See {Ruby Language Issues}[https://bugs.ruby-lang.org/issues/7314] for more details.
9
- def to_lambda (instance = Object.new)
9
+ def to_lambda(instance = Object.new)
10
10
  instance.define_singleton_method(:_, &self)
11
11
  instance.method(:_).to_proc
12
12
  end
@@ -3,15 +3,15 @@
3
3
  # Referenced from {Qiita}[http://qiita.com/south37/items/99a60345b22ef395d424]
4
4
  class Promise
5
5
  # Init a Promise
6
- # @param [ Proc ] callback an async method
6
+ # @param [Proc] callback an async method
7
7
  def initialize(callback)
8
8
  @callback = callback
9
9
  end
10
10
 
11
11
  # Define what to do after a method callbacks
12
- # @param [ Proc ] resolve what on callback
13
- # @param [ Proc ] reject what on callback failed
14
- # @return [ nil ] nil
12
+ # @param [Proc] resolve what on callback
13
+ # @param [Proc] reject what on callback failed
14
+ # @return [nil] nil
15
15
  def then(resolve = ->() {}, reject = ->() {})
16
16
  @callback.call(resolve, reject)
17
17
  end
@@ -20,7 +20,7 @@ end
20
20
  # A Syntactic Sugar for Promise
21
21
  class DeferPromise < Promise
22
22
  # A Syntactic Sugar for Promise
23
- # @param [ proc ] deffered To do what asynchronous
23
+ # @param [Proc] deffered To do what asynchronous
24
24
  def initialize(deffered)
25
25
  super(->(resolve, _reject){
26
26
  EventMachine.defer(proc {
@@ -36,7 +36,7 @@ end
36
36
 
37
37
  module Kernel
38
38
  # Logic dealing of async method
39
- # @param [ Fiber ] fiber a fiber to call
39
+ # @param [Fiber] fiber a fiber to call
40
40
  def async_internal(fiber)
41
41
  chain = lambda do |result|
42
42
  return unless result.is_a?Promise
@@ -48,7 +48,7 @@ module Kernel
48
48
  end
49
49
 
50
50
  # Define an async method
51
- # @param [ Symbol ] method_name method name
51
+ # @param [Symbol] method_name method name
52
52
  # @yield async method
53
53
  # @example
54
54
  # async :hello do
@@ -60,15 +60,15 @@ module Kernel
60
60
  }
61
61
  end
62
62
 
63
- # Shortcut to init [ DeferPromise ]
63
+ # Shortcut to init [DeferPromise]
64
64
  # @yield To do what asynchronous
65
- # @return [ DerferPromise ] instance
65
+ # @return [DerferPromise] instance
66
66
  def defer(&block)
67
67
  DeferPromise.new(block)
68
68
  end
69
69
 
70
70
  # Block the I/O to wait for async method response
71
- # @param [ Promise ] promise promise method
71
+ # @param [Promise] promise promise method
72
72
  # @example
73
73
  # result = await SQL.query('SELECT * FROM hello')
74
74
  def await(promise)
@@ -1,11 +1,11 @@
1
1
  ##
2
- # A special error as containers of errors inside [ Promise ]
3
- # @attr [ StandardError ] raw_exception raw execption raised
2
+ # A special error as containers of errors inside [Promise]
3
+ # @attr [StandardError] raw_exception raw execption raised
4
4
  class PromiseException < StandardError
5
5
  attr_reader :raw_exception
6
6
 
7
7
  # Init PromiseException
8
- # @param [ StandardError ] raw_exception raw execption raised
8
+ # @param [StandardError] raw_exception raw execption raised
9
9
  def initialize(raw_exception)
10
10
  super(nil)
11
11
  @raw_exception = raw_exception
@@ -1,7 +1,7 @@
1
1
  module Kernel
2
2
  # Raise error if Load Failed
3
- # @param [ String ] file file to Load
4
- # @param [ String ] prompt To prompt what when load error
3
+ # @param [String] file file to Load
4
+ # @param [String] prompt To prompt what when load error
5
5
  def safe_require(file, prompt)
6
6
  begin
7
7
  require file
@@ -3,13 +3,13 @@
3
3
  class Midori::File
4
4
  class << self
5
5
  # Same APIs as File.read
6
- # @param [ Array ] args args of File.read
6
+ # @param [Array] args args of File.read
7
7
  def read(*args)
8
8
  await(defer{File.read(*args)})
9
9
  end
10
10
 
11
11
  # Same APIs as File.write
12
- # @param [ Array ] args args of File.write
12
+ # @param [Array] args args of File.write
13
13
  def write(*args)
14
14
  await(defer{File.write(*args)})
15
15
  end
@@ -4,7 +4,7 @@ safe_require 'ohm', 'gem install ohm'
4
4
  # Midori Extension of ohm through meta programming Redic
5
5
  class Redic
6
6
  # Call a redis request asynchronously
7
- # @param [ Array ] args args of Redic.call
7
+ # @param [Array] args args of Redic.call
8
8
  def call(*args)
9
9
  await(defer{
10
10
  @client.connect do
@@ -2,22 +2,22 @@ safe_require 'postgres-pr/message', 'gem install postgres-pr'
2
2
 
3
3
  ##
4
4
  # Midori Extension for Postgres Driver
5
- # @attr [ Integer ] connected Connection Status
5
+ # @attr [Integer] connected Connection Status
6
6
  class Midori::Postgres
7
7
  attr_reader :connected
8
8
 
9
9
  # Init a Postgres Connection
10
- # @param [ Array ] args args of EM.connect
10
+ # @param [Array] args args of EM.connect
11
11
  def initialize(*args)
12
12
  @connected = false
13
13
  @db = EM.connect(*args, EM::P::Postgres3)
14
14
  end
15
15
 
16
16
  # Connect the Postgres server
17
- # @param [ String ] db_name database name
18
- # @param [ String ] username username
19
- # @param [ password ] password password
20
- # @return [ nil ] nil
17
+ # @param [String] db_name database name
18
+ # @param [String] username username
19
+ # @param [password] password password
20
+ # @return [nil] nil
21
21
  def connect(db_name, username, password)
22
22
  await(Promise.new(->(resolve, _reject) {
23
23
  @db.connect(db_name, username, password).callback do |status|
@@ -28,8 +28,8 @@ class Midori::Postgres
28
28
  end
29
29
 
30
30
  # Make SQL query
31
- # @param [ String ] sql sql query
32
- # @return [ Midori::Postgres::Result ] query result
31
+ # @param [String] sql sql query
32
+ # @return [Midori::Postgres::Result] query result
33
33
  def query(sql)
34
34
  await(Promise.new(->(resolve, _reject) {
35
35
  begin
@@ -44,14 +44,14 @@ end
44
44
 
45
45
  ##
46
46
  # Postgres Result for Midori Postgres Driver Extension
47
- # @attr [ Array ] result result if success
48
- # @attr [ Array ] errors exceptions met
47
+ # @attr [Array] result result if success
48
+ # @attr [Array] errors exceptions met
49
49
  class Midori::Postgres::Result
50
50
  attr_reader :result, :errors
51
51
 
52
52
  # Init a Postgres Result
53
- # @param [ Array ] result result if success
54
- # @param [ Array ] errors exceptions met
53
+ # @param [Array] result result if success
54
+ # @param [Array] errors exceptions met
55
55
  def initialize(result, errors)
56
56
  @result = result
57
57
  @errors = errors
@@ -5,15 +5,15 @@ safe_require 'em-hiredis', 'gem install em-hiredis'
5
5
  class Midori::Redis
6
6
 
7
7
  # Init a Redis Connection
8
- # @param [ Array ] args args EM::Hiredis.connect
8
+ # @param [Array] args args EM::Hiredis.connect
9
9
  def initialize(*args)
10
10
  @connection = EM::Hiredis.connect(*args)
11
11
  @connection
12
12
  end
13
13
 
14
14
  # Call a redis request asynchronously
15
- # @param [ String ] sys method name
16
- # @param [ Array ] args args of the method calling
15
+ # @param [String] sys method name
16
+ # @param [Array] args args of the method calling
17
17
  def method_missing(sys, *args)
18
18
  await(Promise.new(->(resolve, _reject) {
19
19
  @connection.send(sys, *args).callback do |*ret_args|
@@ -23,7 +23,7 @@ class Midori::Redis
23
23
  end
24
24
 
25
25
  # Return raw pubsub mode
26
- # @return [ EM::Hiredis::Pubsub ] raw pubsub
26
+ # @return [EM::Hiredis::Pubsub] raw pubsub
27
27
  def pubsub
28
28
  @connection.pubsub
29
29
  end
@@ -5,9 +5,9 @@ require 'sequel/adapters/postgres'
5
5
  # Midori Extension of sequel postgres through meta programming
6
6
  class Sequel::Postgres::Adapter
7
7
  # Call a sql request asynchronously
8
- # @param [ String ] sql sql request
9
- # @param [ Array ] args args to send
10
- # @return [ Array ] sql query result
8
+ # @param [String] sql sql request
9
+ # @param [Array] args args to send
10
+ # @return [Array] sql query result
11
11
  def execute_query(sql, args)
12
12
  @db.log_connection_yield(sql, self, args) do
13
13
  args ? await(defer{async_exec(sql, args)}) : await(defer{async_exec(sql)})
@@ -21,7 +21,7 @@ class Midori::Middleware
21
21
  end
22
22
 
23
23
  # Dynamically generate a method to use inside router
24
- # @param [ Symbol ] name name of the method
24
+ # @param [Symbol] name name of the method
25
25
  # @yield the block to run
26
26
  def self.helper(name, &block)
27
27
  Midori::CleanRoom.class_exec do
@@ -32,8 +32,8 @@ class Midori::Request
32
32
  end
33
33
 
34
34
  # Init an request with String data
35
- # @param [ String ] data
36
- # @return [ nil ] nil
35
+ # @param [String] data
36
+ # @return [nil] nil
37
37
  def parse(data)
38
38
  offset = @parser << data
39
39
  @body = data[offset..-1]
@@ -1,13 +1,13 @@
1
1
  ##
2
2
  # Abstract runner class to control instance of Midori Server
3
- # @attr [ String ] bind the address to bind
4
- # @attr [ Integer ] port the port to bind
3
+ # @attr [String] bind the address to bind
4
+ # @attr [Integer] port the port to bind
5
5
  class Midori::Runner
6
6
  attr_reader :bind, :port
7
7
 
8
8
  # Define status of a runner
9
- # @param [ Class ] api inherited from [ Midori::API ]
10
- # @param [ Class ] configure inherited from [ Midori::Configure ]
9
+ # @param [Class] api inherited from [Midori::API]
10
+ # @param [Class] configure inherited from [Midori::Configure]
11
11
  def initialize(api, configure = Midori::Configure)
12
12
  @logger = configure.logger
13
13
  @bind = configure.bind
@@ -9,17 +9,17 @@ class Midori::Sandbox
9
9
  end
10
10
 
11
11
  # Add a rule to Sandbox
12
- # @param [ Class ] class_name the class to capture
13
- # @param [ Proc ] block what to do when captured
14
- # @return [ nil ] nil
12
+ # @param [Class] class_name the class to capture
13
+ # @param [Proc] block what to do when captured
14
+ # @return [nil] nil
15
15
  def add_rule(class_name, block)
16
16
  @handlers[class_name] = block
17
17
  nil
18
18
  end
19
19
 
20
20
  # Detect what to run with given error
21
- # @param [ StandardError ] error the error captured
22
- # @return [ nil ] nil
21
+ # @param [StandardError] error the error captured
22
+ # @return [nil] nil
23
23
  def capture(error)
24
24
  if @handlers[error.class].nil?
25
25
  @handlers[Midori::Exception::InternalError].call(error)
@@ -29,9 +29,9 @@ class Midori::Sandbox
29
29
  end
30
30
 
31
31
  # Run sandbox inside given clean room
32
- # @param [ Midori::CleanRoom ] clean_room Clean room to run
33
- # @param [ Proc ] function the block to run
34
- # @return [ nil ] nil
32
+ # @param [Midori::CleanRoom] clean_room Clean room to run
33
+ # @param [Proc] function the block to run
34
+ # @return [nil] nil
35
35
  def run(clean_room, function, *args)
36
36
  begin
37
37
  function.to_lambda(clean_room).call(*args)
@@ -2,13 +2,13 @@
2
2
  # Logic to EventMachine TCP Server, running inside +EM::Connection+
3
3
  module Midori::Server
4
4
  # @!attribute request
5
- # @return [ Midori::Request ] raw request
5
+ # @return [Midori::Request] raw request
6
6
  # @!attribute api
7
- # @return [ Class ] inherited from Midori::API
7
+ # @return [Class] inherited from Midori::API
8
8
  # @!attribute websocket
9
- # @return [ Midori::WebSocket ] defined websocket instance
9
+ # @return [Midori::WebSocket] defined websocket instance
10
10
  # @!attribute eventsource
11
- # @return [ Midori::EventSource] defined eventsource instance
11
+ # @return [Midori::EventSource] defined eventsource instance
12
12
  attr_accessor :request, :api, :websocket, :eventsource
13
13
 
14
14
  # Define server behaviour
@@ -1,5 +1,5 @@
1
1
  # Midori Module
2
2
  module Midori
3
3
  # Current Version Code
4
- VERSION = '0.1.7.1'.freeze
4
+ VERSION = '0.1.8'.freeze
5
5
  end
@@ -1,22 +1,22 @@
1
1
  ##
2
2
  # This class provides methods for WebSocket connection instance.
3
- # @attr [ Array<Integer>, String ] msg message send from client
4
- # @attr [ Integer ] opcode operation code of WebSocket
5
- # @attr [ Hash ] events response for different event
6
- # @attr [ EM::Connection ] connection raw EventMachine connection
7
- # @attr [ Midori::Request ] request raw request
3
+ # @attr [Array<Integer>, String] msg message send from client
4
+ # @attr [Integer] opcode operation code of WebSocket
5
+ # @attr [Hash] events response for different event
6
+ # @attr [EM::Connection] connection raw EventMachine connection
7
+ # @attr [Midori::Request] request raw request
8
8
  class Midori::WebSocket
9
9
  attr_accessor :msg, :opcode, :events, :connection, :request
10
10
 
11
11
  # Init a WebSocket instance with a connection
12
- # @param [ EM::Connection ] connection raw EventMachine connection
12
+ # @param [EM::Connection] connection raw EventMachine connection
13
13
  def initialize(connection)
14
14
  @events = {}
15
15
  @connection = connection
16
16
  end
17
17
 
18
18
  # Decode raw data send from client
19
- # @param [ StringIO ] data raw data
19
+ # @param [StringIO] data raw data
20
20
  def decode(data)
21
21
  # Fin and Opcode
22
22
  byte_tmp = data.getbyte
@@ -31,7 +31,7 @@ class Midori::WebSocket
31
31
  end
32
32
 
33
33
  # Decode masked message send from client
34
- # @param [ StringIO ] data raw data
34
+ # @param [StringIO] data raw data
35
35
  def decode_mask(data)
36
36
  # Mask
37
37
  byte_tmp = data.getbyte
@@ -50,7 +50,7 @@ class Midori::WebSocket
50
50
  end
51
51
 
52
52
  # API definition for events
53
- # @param [ Symbol ] event event name(open, message, close, ping, pong)
53
+ # @param [Symbol] event event name(open, message, close, ping, pong)
54
54
  # @yield what to do after event matched
55
55
  # @example
56
56
  # websocket '/websocket' do |ws|
@@ -63,7 +63,7 @@ class Midori::WebSocket
63
63
  end
64
64
 
65
65
  # Send data
66
- # @param [ Array<Integer>, String ] msg data to send
66
+ # @param [Array<Integer>, String] msg data to send
67
67
  def send(msg)
68
68
  output = []
69
69
  if msg.is_a?String
@@ -79,20 +79,20 @@ class Midori::WebSocket
79
79
  end
80
80
 
81
81
  # Send a Ping request
82
- # @param [ String ] str string to send
82
+ # @param [String] str string to send
83
83
  def ping(str)
84
84
  heartbeat(0b10001001, str)
85
85
  end
86
86
 
87
87
  # Send a Pong request
88
- # @param [ String ] str string to send
88
+ # @param [String] str string to send
89
89
  def pong(str)
90
90
  heartbeat(0b10001010, str)
91
91
  end
92
92
 
93
93
  # Ancestor of ping pong
94
- # @param [ Integer ] method opcode
95
- # @param [ String ] str string to send
94
+ # @param [Integer] method opcode
95
+ # @param [String] str string to send
96
96
  def heartbeat(method, str)
97
97
  raise Midori::Exception::PingPongSizeTooLarge if str.size > 125
98
98
  @connection.send_data [method, str.size, str].pack("CCA#{str.size}")
@@ -0,0 +1,11 @@
1
+ # Introduction
2
+
3
+ ## What is midori?
4
+
5
+ Midori (pronounced /miːdɒliː/) is a **Ruby web framework** for building APIs, web pages and realtime web services. Midori is designed to provide **non-blocking** I/O operations without **callback hells** on web development. The core library is focused on network I/Os, and gives a very easy DSL to pick up and converting existed projects on. On the other hand, midori also officially provides extension libraries that could deal with file, database, cache, network requests and other I/O operations without blocking.
6
+
7
+ If you want to know how midori compares to other libraries/frameworks, checkout out the [Compatison with Other Frameworks](meta/comparison_with_other_frameworks.md)
8
+
9
+ ## Note
10
+
11
+ The official guide assumes intermediate level knowledge of Ruby and backend development. If you are totally new , it might not be the best idea to jump right into a framework as your first step - grasp the basics then come back! Prior experience with other frameworks like Rails helps, but is not required.
@@ -0,0 +1,28 @@
1
+ # Summary
2
+
3
+ ## Essentials
4
+
5
+ * [Introduction](README.md)
6
+ * [Installation](essentials/installation.md)
7
+ * [Getting Started](essentials/getting_started.md)
8
+ * [Routing](essentials/routing.md)
9
+ * [Request Handling](essentials/request_handling.md)
10
+ * [Runner](essentials/runner.md)
11
+ * [Middlewares](essentials/middlewares.md)
12
+ * [Extensions](essentials/extensions.md)
13
+
14
+
15
+ ## Advanced
16
+
17
+ - [Error Handling](advanced/error_handling.md)
18
+ - [Request-Eval-Response Loop](advanced/rerl.md)
19
+ - [Custom Extensions](advanced/custom_extensions.md)
20
+ - [Scaling Project](advanced/scaling_project.md)
21
+ - [Unit Testing](advanced/unit_testing.md)
22
+ - [Deploying for Production](advanced/deploying_for_production.md)
23
+
24
+ ## Meta
25
+
26
+ - [Comparison with Other Frameworks](meta/comparison_with_other_frameworks.md)
27
+ - [Next Steps](meta/next_steps.md)
28
+ - [Join the Midori Community](meta/join_the_midori_community.md)
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
@@ -0,0 +1,27 @@
1
+ # Getting Started
2
+
3
+ ## Hello Midori
4
+
5
+ midori is a [DSL](https://en.wikipedia.org/wiki/Domain-specific_language) for web and API development in Ruby with minimal effort:
6
+
7
+ ```ruby
8
+ # hello_midori.rb
9
+ require 'midori'
10
+
11
+ class HelloWorldAPI < Midori::API
12
+ get '/' do
13
+ 'Ohayou Midori'
14
+ end
15
+ end
16
+
17
+ Midori::Runner.new(HelloWorldAPI).start
18
+ ```
19
+
20
+ Run with
21
+
22
+ ```
23
+ $ ruby hello_midori.rb
24
+ ```
25
+
26
+ View at: http://127.0.0.1:8080 with your browser, if you see a page showing: **Ohayou Midori**. You've made your first application with midori.
27
+
@@ -0,0 +1,98 @@
1
+ # Installation
2
+
3
+ ## Requirements
4
+
5
+ Open up a command line prompt. Any commands prefaced with a dollar sign `$` should be run in the command line. Verify that you have a current version of Ruby installed:
6
+
7
+ ```
8
+ $ ruby -v
9
+ ruby 2.4.0p0
10
+ ```
11
+
12
+ Generally, midori supports the following ruby interpreters:
13
+
14
+ - Ruby (MRI) **>= 2.1.0**
15
+ - JRuby >= **9.0.4.0**
16
+
17
+ For every version released, it would be tested and **officially ensured** in the following environments:
18
+
19
+ - Ruby
20
+ - 2.1.0
21
+ - 2.2.6
22
+ - 2.3.3
23
+ - 2.4.0
24
+ - JRuby
25
+ - 9.0.4.0, OpenJDK 7
26
+ - 9.0.4.0, OracleJDK 7
27
+ - 9.0.4.0, OracleJDK 8
28
+
29
+ **Note: **
30
+
31
+ - **For JRuby users, you may meet performance problem due to the issues of [Fiber implementation](https://github.com/jruby/jruby/wiki/DifferencesBetweenMriAndJruby#continuations-and-fibers) with JVM, which may [possibly improved](https://github.com/jruby/jruby/wiki/PerformanceTuning#enable-coroutine-based-fibers) in the future JRuby versions with JDK 9.**
32
+ - **For macOS users, you may meet performance problem due to the issues of [EventMachine](https://github.com/heckpsi-lab/em-midori/issues/15). Very few people would use macOS in production, so this issue may not affect much, but we are still working hard on fixing it.**
33
+
34
+ It's hard to say that if it is possible for running on other ruby implementations like Rubinius, if you're in favor of supporting more ruby implementations, you could open a ticket [here](https://github.com/heckpsi-lab/em-midori/issues), and we are glad to discuss it.
35
+
36
+ ## Install with RubyGems
37
+
38
+ ```
39
+ $ gem install em-midori
40
+ Successfully installed em-midori-0.1.7
41
+ 1 gem installed
42
+ ```
43
+
44
+ To test whether it has installed properly, run:
45
+
46
+ ```
47
+ $ ruby -r "midori" -e "class A < Midori::API;end;Midori::Runner.new(A).start"
48
+ ```
49
+
50
+ If you see the following message, then everything now works fine.
51
+
52
+ ```
53
+ Midori 0.1.7 is now running on 127.0.0.1:8080
54
+ ```
55
+
56
+ ## Use Bundler
57
+
58
+ Example `Gemfile` of basic usage as following:
59
+
60
+ ```ruby
61
+ source 'https://rubygems.org'
62
+ gem 'bundler', '~> 1.0'
63
+ gem 'em-midori', '~> 0.1', require: 'midori'
64
+ ```
65
+
66
+ and then running:
67
+
68
+ ```
69
+ $ bundle install
70
+ ```
71
+
72
+ You could use
73
+
74
+ ```ruby
75
+ require 'bundler'
76
+ Bundler.require
77
+ ```
78
+
79
+ in your entrance ruby file.
80
+
81
+ To include built-in extensions of midori you could make your `Gemfile` like:
82
+
83
+ ```ruby
84
+ source 'https://rubygems.org'
85
+ gem 'bundler', '~> 1.0'
86
+ gem 'em-midori', '~> 0.1', require: %w'midori midori/extension/sequel'
87
+ ```
88
+
89
+ Using bunlder could make dependency management much easier, which helps a lot in scaling project. To learn more about bundler, you could see docs [here](http://bundler.io/docs.html).
90
+
91
+ ## For Developers in China
92
+
93
+ You may probably meet problems with rubygems due to unstable overseas internet connection issues in China. The most popular way to solve it is to use mirror provided by [RubyChina](https://gems.ruby-china.org/) or [TUNA](https://mirror.tuna.tsinghua.edu.cn/help/rubygems/) as your gem source. This may have some side effects in development, because there's a few minutes' delay in receiving gem updates.
94
+
95
+ Alternatively, you could use proxy to connect the main repository directly to avoid the delay problem. But using proxy is a little too complex in production environment.
96
+
97
+ Choose the solution better fits your requirements. Mixing the solutions like using proxy in development and using mirror in production is also a good choice.
98
+
File without changes
@@ -0,0 +1,71 @@
1
+ # Request Handling
2
+
3
+ ## Accessing the request object
4
+
5
+ The incoming request object can be accessed from request level (filter, routes, error handlers) through the `request` method:
6
+
7
+ ```ruby
8
+ class ExampleAPI < Midori::API
9
+ get '/' do
10
+ request.ip # '127.0.0.1' client ip address
11
+ request.port # '8080' client port
12
+ request.method # 'GET'
13
+ request.path # '/'
14
+ request.query_string # ''
15
+ request.header # {} request header
16
+ request.body # request body sent by the client
17
+ request.params # {} params matched in router
18
+ end
19
+ end
20
+ ```
21
+
22
+ **Note (for sinatra users): **The `request.body` in modori is a `String` object but not a `StringIO` object.
23
+
24
+ ## Construct the response object
25
+
26
+ Midori accepts the return value of the block as the response body by default.
27
+
28
+ You could edit variable `status` and `header` to construct things other than body.
29
+
30
+ You could also return a `Midori::Response` object as your response, which could override everything.
31
+
32
+ ```ruby
33
+ class ExampleAPI < Midori::API
34
+ get '/case_0' do
35
+ 'Hello'
36
+ # HTTP/1.1 200 OK
37
+ # Server: Midori/1.0
38
+ #
39
+ # Hello
40
+ end
41
+
42
+ get '/case_1' do
43
+ status = 418
44
+ "I\'m a teapot"
45
+ # HTTP/1.1 418 I'm a teapot
46
+ # Server: Midori/1.0
47
+ #
48
+ # I'm a teapot
49
+ end
50
+
51
+ get '/case_2' do
52
+ header['Example-Header'] = 'Example-Value'
53
+ 'Hello'
54
+ end
55
+ # HTTP/1.1 200 OK
56
+ # Server: Midori/1.0
57
+ # Example-Header: Example-Value
58
+ #
59
+ # Hello
60
+
61
+ get '/case_3' do
62
+ status = 202
63
+ header['Example-Header'] = 'Example-Value'
64
+ Midori::Response.new(200, {}, 'Hello')
65
+ end
66
+ # HTTP/1.1 200 OK
67
+ #
68
+ # Hello
69
+ end
70
+ ```
71
+
@@ -0,0 +1,136 @@
1
+ # Routing
2
+
3
+ ## Basic Usage
4
+
5
+ Routes should be defined inside a class inherited from `Midori::API`. Midori doesn't support defining routes globally like sinatra to avoid scope pollution, which affects a lot in scaling project.
6
+
7
+ In midori, a route is an HTTP method with a URL-matching pattern. Each route is associated with a block:
8
+
9
+ ```ruby
10
+ class ExampleAPI < Midori::API
11
+ get '/' do
12
+ #.. show something ..
13
+ end
14
+
15
+ post '/' do
16
+ #.. create something ..
17
+ end
18
+
19
+ put '/' do
20
+ #.. replace something ..
21
+ end
22
+
23
+ delete '/' do
24
+ #.. annihilate something ..
25
+ end
26
+
27
+ options '/' do
28
+ #.. appease something ..
29
+ end
30
+
31
+ link '/' do
32
+ #.. affiliate something ..
33
+ end
34
+
35
+ unlink '/' do
36
+ #.. separate something ..
37
+ end
38
+ end
39
+ ```
40
+
41
+ Routes are matched in the order they are defined. The first route that matches the request is invoked.
42
+
43
+ Midori not only supports the methods above, it supports almostly every method provided in RFC standards. You could look it up in [API doc](http://www.rubydoc.info/gems/em-midori/Midori/API) for more details.
44
+
45
+ ## Params
46
+
47
+ Routes patterns may include named parameters, accessible via the `request.params` hash:
48
+
49
+ ```ruby
50
+ class ExampleAPI < Midori::API
51
+ get '/hello/:name' do
52
+ "Ohayou #{request.params['name']}"
53
+ end
54
+ end
55
+ ```
56
+
57
+ Route patterns may also include splat (or wildcard) parameters, accessible via the `request.params['splat']` array:
58
+
59
+ ```ruby
60
+ class ExampleAPI < Midori::API
61
+ get '/say/*/to/*' do
62
+ # matches /say/hello/to/world
63
+ request.params['splat'] # => ["hello", "world"]
64
+ end
65
+
66
+ get '/download/*.*' do
67
+ # matches /download/path/to/file.xml
68
+ request.params['splat'] # => ["path/to/file", "xml"]
69
+ end
70
+ end
71
+ ```
72
+
73
+ Routes may also utilize query string:
74
+
75
+ ```ruby
76
+ class ExampleAPI < Midori::API
77
+ get '/posts' do
78
+ # matches "GET /posts?title=foo&author=bar"
79
+ request.query_string # => title=foo&author=bar
80
+ end
81
+ end
82
+ ```
83
+
84
+ ## WebSocket & EventSource
85
+
86
+ `WebSocket` connection uses `GET` method in HTTP protocol, but indeed, it behaves totally different from `GET` requests. You don't need to care about the protocol details. In midori, you could easily manage websocket connections easily.
87
+
88
+ Here's a chatroom example using websocket in midori:
89
+
90
+ ```ruby
91
+ CONNECTION_POOL = []
92
+
93
+ class ExampleAPI < Midori::API
94
+ websocket '/' do |ws|
95
+ ws.on :open do
96
+ ws.send 'Ohayo Midori'
97
+ CONNECTION_POOL << ws
98
+ end
99
+
100
+ ws.on :message do |msg|
101
+ CONNECTION_POOL.map do |client|
102
+ client.send msg
103
+ end
104
+ end
105
+
106
+ ws.on :close do
107
+ CONNECTION_POOL.delete(ws)
108
+ puts 'Oyasumi midori'
109
+ end
110
+ end
111
+ end
112
+ ```
113
+
114
+ midori also supports `EventSource ` connection as part of your route.
115
+
116
+ Here's a chatroom example using eventsource in midori:
117
+
118
+ ```ruby
119
+ CONNECTION_POOL = []
120
+
121
+ class ExampleAPI < Midori::API
122
+ post '/pub' do
123
+ clients = CONNECTION_POOL.clone
124
+ CONNECTION_POOL.clear
125
+ # EventSource connection disconnects every time message sent, DO NOT reuse connection pool
126
+ clients.map do |client|
127
+ client.send request.body
128
+ end
129
+ end
130
+
131
+ eventsource '/sub' do |es|
132
+ CONNECTION_POOL << es
133
+ end
134
+ end
135
+ ```
136
+
File without changes
File without changes
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: em-midori
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.7.1
4
+ version: 0.1.8
5
5
  platform: ruby
6
6
  authors:
7
7
  - HeckPsi Lab
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-01-10 00:00:00.000000000 Z
11
+ date: 2017-01-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: eventmachine
@@ -52,8 +52,8 @@ dependencies:
52
52
  - - "~>"
53
53
  - !ruby/object:Gem::Version
54
54
  version: 0.6.1
55
- description: EM Midori is an EventMachine-based Web Framework written in pure Ruby,
56
- providing high performance and proper abstraction.
55
+ description: Midori is a Ruby Web Framework, providing high performance and proper
56
+ abstraction.
57
57
  email: business@heckpsi.com
58
58
  executables: []
59
59
  extensions: []
@@ -91,12 +91,35 @@ files:
91
91
  - lib/midori/server.rb
92
92
  - lib/midori/version.rb
93
93
  - lib/midori/websocket.rb
94
+ - tutorial/README.md
95
+ - tutorial/SUMMARY.md
96
+ - tutorial/advanced/custom_extensions.md
97
+ - tutorial/advanced/deploying_for_production.md
98
+ - tutorial/advanced/error_handling.md
99
+ - tutorial/advanced/rerl.md
100
+ - tutorial/advanced/scaling_project.md
101
+ - tutorial/advanced/unit_testing.md
102
+ - tutorial/essentials/extensions.md
103
+ - tutorial/essentials/getting_started.md
104
+ - tutorial/essentials/installation.md
105
+ - tutorial/essentials/middlewares.md
106
+ - tutorial/essentials/request_handling.md
107
+ - tutorial/essentials/routing.md
108
+ - tutorial/essentials/runner.md
109
+ - tutorial/meta/comparison_with_other_frameworks.md
110
+ - tutorial/meta/join_the_midori_community.md
111
+ - tutorial/meta/next_steps.md
94
112
  homepage: https://github.com/heckpsi-lab/em-midori
95
113
  licenses:
96
114
  - MIT
97
115
  metadata:
98
116
  issue_tracker: https://github.com/heckpsi-lab/em-midori/issues
99
- post_install_message:
117
+ post_install_message: "\n _____ _ \n| _ | | \n|
118
+ | | | |__ __ _ _ _ ___ \n| | | | '_ \\ / _` | | | |/ _ \\ \n\\ \\_/ / | |
119
+ | (_| | |_| | (_) |\n \\___/|_| |_|\\__,_|\\__, |\\___/ \n __/
120
+ | \n |___/ \n _ _ _ \n (_)
121
+ \ | | (_)\n _ __ ___ _ __| | ___ _ __ _ \n| '_ ` _ \\| |/ _` |/ _ \\|
122
+ '__| |\n| | | | | | | (_| | (_) | | | |\n|_| |_| |_|_|\\__,_|\\___/|_| |_|\n\n"
100
123
  rdoc_options: []
101
124
  require_paths:
102
125
  - lib
@@ -115,5 +138,5 @@ rubyforge_project:
115
138
  rubygems_version: 2.6.8
116
139
  signing_key:
117
140
  specification_version: 4
118
- summary: An EventMachine Based Web Framework on Ruby
141
+ summary: High performance ruby web framework
119
142
  test_files: []