dandy 1.0.3 → 2.0.0.pre.alpha

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
  SHA256:
3
- metadata.gz: 10c1d06be946e67fdc9c9e2dd27e37015aa5c315006f153364f6a729eecadc8c
4
- data.tar.gz: eb3055e8a23b44e78661f7ae89896bb96748fb71bb2dbd9122f5f9f6a4271a94
3
+ metadata.gz: f0a2a55e97bb758be7b7fd22226adc5757a7ad94fc48596448d0b10447e85abe
4
+ data.tar.gz: 232468091c7e5dca9f15a28b54dedc298003f24a0acc116f85ea79f64f83db09
5
5
  SHA512:
6
- metadata.gz: 40389e9152244e5949e539d18caa4fd35604286721d327543bc2e20765d078e4888f2da0225bd052f54ec0e817e4cef7b50b5cf1092afdd09e5aed9364da66e3
7
- data.tar.gz: d6966b353e974d10a755677b84a1a5943a59cf2335eeec2a396203df118a03161fec03bd7f72b63a83467595d92ab019aac30c1d82412a9b5017e553bd8e43ae
6
+ metadata.gz: a090b89c227d4acd9b2d4fcd2527a649acd147d60b23aee1ebef93c3eec4659311a1204487e304e04a02a7c2abd489b5800c7c6a0522ba63cbd893ccdac24bdd
7
+ data.tar.gz: dca5768ae6c078c5f1cc5f529489ac43d856b169b49617dfacab1df649779a60a2f8a36d4eaeff20ff862443124e204d7d0d12e5fd49328a211d2c29140e93f1
data/lib/dandy.rb CHANGED
@@ -1,5 +1,6 @@
1
1
  require 'dandy/version'
2
2
  require 'dandy/app'
3
+ require 'dandy/consumer'
3
4
  require 'dandy/base/handle_errors'
4
5
 
5
6
  module Dandy
data/lib/dandy/app.rb CHANGED
@@ -11,7 +11,8 @@ require 'dandy/view_builder_registry'
11
11
  require 'dandy/view_factory'
12
12
  require 'dandy/view_builders/json'
13
13
  require 'dandy/routing/routing'
14
- require 'dandy/safe_executor'
14
+ require 'dandy/route_executor'
15
+ require 'dandy/handler_executor'
15
16
 
16
17
  module Dandy
17
18
  class App
@@ -22,12 +23,12 @@ module Dandy
22
23
 
23
24
  register_dependencies
24
25
  load_basic_dependencies
25
- parse_routes
26
+ parse_entrypoints
26
27
  add_view_builders
27
28
  end
28
29
 
29
30
  def call(env)
30
- request = Request.new(@route_matcher, @container, @safe_executor)
31
+ request = Request.new(@route_matcher, @container, @route_executor)
31
32
  request.handle(env)
32
33
  end
33
34
 
@@ -37,6 +38,10 @@ module Dandy
37
38
  @view_builder_registry.add(view_builder, format)
38
39
  end
39
40
 
41
+ def add_consumer(consumer)
42
+ consumer.connect(@message_handlers, @handler_executor)
43
+ end
44
+
40
45
  private
41
46
 
42
47
  def add_view_builders
@@ -65,9 +70,11 @@ module Dandy
65
70
  file_reader: Routing::FileReader,
66
71
  syntax_parser: SyntaxParser,
67
72
  syntax_error_interpreter: Routing::SyntaxErrorInterpreter,
68
- routes_builder: Routing::Builder,
69
- route_parser: Routing::Parser,
70
- safe_executor: SafeExecutor
73
+ routes_builder: Routing::RoutesBuilder,
74
+ handlers_builder: Routing::HandlersBuilder,
75
+ dandy_parser: Routing::Parser,
76
+ route_executor: RouteExecutor,
77
+ handler_executor: HandlerExecutor
71
78
  }
72
79
 
73
80
  singletons.keys.each do |name|
@@ -81,14 +88,17 @@ module Dandy
81
88
  @view_factory = @container.resolve(:view_factory)
82
89
  @dependency_loader = @container.resolve(:dependency_loader)
83
90
  @view_builder_registry = @container.resolve(:view_builder_registry)
84
- @route_parser = @container.resolve(:route_parser)
85
- @safe_executor = @container.resolve(:safe_executor)
91
+ @dandy_parser = @container.resolve(:dandy_parser)
92
+ @route_executor = @container.resolve(:route_executor)
93
+ @handler_executor = @container.resolve(:handler_executor)
86
94
 
87
95
  @dependency_loader.load_components
88
96
  end
89
97
 
90
- def parse_routes
91
- @routes = @route_parser.parse
98
+ def parse_entrypoints
99
+ entrypoints = @dandy_parser.parse
100
+ @routes = entrypoints[:routes]
101
+ @message_handlers = entrypoints[:message_handlers]
92
102
  @route_matcher = Routing::Matcher.new(@routes)
93
103
  end
94
104
  end
data/lib/dandy/chain.rb CHANGED
@@ -7,7 +7,7 @@ module Dandy
7
7
  @async_timeout = dandy_config[:action][:async_timeout]
8
8
  end
9
9
 
10
- def run_commands(commands, last_command)
10
+ def run_commands(commands, last_command, scope)
11
11
  threads = []
12
12
  Thread.abort_on_exception = true
13
13
 
@@ -19,17 +19,17 @@ module Dandy
19
19
  threads = []
20
20
 
21
21
  if last_command && (command.name == last_command.name)
22
- result = run_command(command)
22
+ result = run_command(command, scope)
23
23
  else
24
- run_command(command)
24
+ run_command(command, scope)
25
25
  end
26
26
  else
27
27
  thread = Thread.new {
28
28
  Timeout::timeout(@async_timeout) {
29
29
  if last_command && (command.name == last_command.name)
30
- result = run_command(command)
30
+ result = run_command(command, scope)
31
31
  else
32
- run_command(command)
32
+ run_command(command, scope)
33
33
  end
34
34
  }
35
35
  }
@@ -47,7 +47,7 @@ module Dandy
47
47
 
48
48
  private
49
49
 
50
- def run_command(command)
50
+ def run_command(command, scope)
51
51
  if command.entity?
52
52
  entity = @container.resolve(command.entity_name.to_sym)
53
53
  method_name = command.entity_method.to_sym
@@ -65,7 +65,7 @@ module Dandy
65
65
  @container
66
66
  .register_instance(result, command.result_name.to_sym)
67
67
  .using_lifetime(:scope)
68
- .bound_to(:dandy_request)
68
+ .bound_to(scope)
69
69
 
70
70
  result
71
71
  end
@@ -0,0 +1,32 @@
1
+ require 'dandy/message'
2
+
3
+ module Dandy
4
+ class Consumer
5
+ def initialize(container)
6
+ @container = container
7
+ end
8
+
9
+ def connect(message_handlers, handler_executor)
10
+ @message_handlers = {}
11
+ @handler_executor = handler_executor
12
+
13
+ message_handlers.each do |handler|
14
+ @message_handlers[handler.name] = handler
15
+ end
16
+
17
+ subscribe
18
+ end
19
+
20
+ def subscribe
21
+ raise DandyError, 'Method subscribe is not implemented in your consumer'
22
+ end
23
+
24
+ def handle(message_name, payload)
25
+ if @message_handlers.key? message_name
26
+ handler = @message_handlers[message_name]
27
+ message = Message.new(@container, handler, @handler_executor)
28
+ message.handle(payload)
29
+ end
30
+ end
31
+ end
32
+ end
@@ -2,7 +2,7 @@ path:
2
2
  dependencies:
3
3
  - app/actions
4
4
  views: app/views
5
- routes: app/app.routes
5
+ routes: app/app.dandy
6
6
  action:
7
7
  async_timeout: 10 # in seconds
8
8
  db:
@@ -0,0 +1,28 @@
1
+ module Dandy
2
+ class HandlerExecutor
3
+ def initialize(container, dandy_config)
4
+ @container = container
5
+ @dandy_config = dandy_config
6
+ end
7
+
8
+ def execute(message_handler)
9
+ chain = Chain.new(@container, @dandy_config)
10
+
11
+ begin
12
+ chain.run_commands(message_handler.commands, message_handler.last_command, :dandy_message)
13
+ rescue Exception => error
14
+ handle_error(message_handler, error)
15
+ end
16
+ end
17
+
18
+ def handle_error(message_handler, error)
19
+ @container
20
+ .register_instance(error, :dandy_error)
21
+ .using_lifetime(:scope)
22
+ .bound_to(:dandy_message)
23
+
24
+ command = @container.resolve(message_handler.catch.name.to_sym)
25
+ command.call
26
+ end
27
+ end
28
+ end
@@ -7,14 +7,16 @@ module Dandy
7
7
  @dandy_env = dandy_env
8
8
  end
9
9
 
10
- def load_components
10
+ def load_components(scope = :dandy_request)
11
11
  if @dandy_env == 'development'
12
12
  # every time reload types in development mode
13
13
  @types = @type_loader.load_types
14
14
  end
15
15
 
16
16
  @types.each do |type|
17
- @container.register(type[:class], type[:path].to_sym).using_lifetime(:scope).bound_to(:dandy_request)
17
+ @container.register(type[:class], type[:path].to_sym)
18
+ .using_lifetime(:scope)
19
+ .bound_to(scope)
18
20
  end
19
21
  end
20
22
  end
@@ -0,0 +1,50 @@
1
+ require 'json'
2
+ require 'awrence'
3
+ require 'plissken'
4
+ require 'rack/multipart'
5
+ require 'dandy/extensions/hash'
6
+ require 'dandy/view_factory'
7
+ require 'dandy/chain'
8
+
9
+ module Dandy
10
+ class Message
11
+ include Hypo::Scope
12
+
13
+ def initialize(container, handler, handler_executor)
14
+ @container = container
15
+ @handler = handler
16
+ @handler_executor = handler_executor
17
+ end
18
+
19
+ def handle(data)
20
+ create_scope
21
+ register_data(data)
22
+
23
+ begin
24
+ result = @handler_executor.execute(@handler)
25
+ release
26
+ rescue Exception => error
27
+ result = @handler_executor.handle_error(@handler, error)
28
+ end
29
+
30
+ result
31
+ end
32
+
33
+ private
34
+
35
+ def create_scope
36
+ @container
37
+ .register_instance(self, :dandy_message)
38
+ .using_lifetime(:scope)
39
+ .bound_to(self)
40
+ end
41
+
42
+ def register_data(data)
43
+ unless data.nil?
44
+ @container.register_instance(data, :dandy_data)
45
+ .using_lifetime(:scope)
46
+ .bound_to(:dandy_message)
47
+ end
48
+ end
49
+ end
50
+ end
data/lib/dandy/request.rb CHANGED
@@ -10,10 +10,10 @@ module Dandy
10
10
  class Request
11
11
  include Hypo::Scope
12
12
 
13
- def initialize(route_matcher, container, safe_executor)
13
+ def initialize(route_matcher, container, route_executor)
14
14
  @container = container
15
15
  @route_matcher = route_matcher
16
- @safe_executor = safe_executor
16
+ @route_executor = route_executor
17
17
  end
18
18
 
19
19
  def handle(rack_env)
@@ -49,12 +49,11 @@ module Dandy
49
49
  multipart = Rack::Multipart.parse_multipart(rack_env) || {}
50
50
  register_context(multipart.values, :dandy_files)
51
51
 
52
- body = @safe_executor.execute(match.route, headers)
53
-
54
52
  begin
53
+ body = @route_executor.execute(match.route, headers)
55
54
  release
56
55
  rescue Exception => error
57
- body = @safe_executor.handle_error(match.route, headers, error)
56
+ body = @route_executor.handle_error(match.route, headers, error)
58
57
  end
59
58
 
60
59
  status = @container.resolve(:dandy_status)
@@ -1,7 +1,7 @@
1
1
  require 'dandy/response'
2
2
 
3
3
  module Dandy
4
- class SafeExecutor
4
+ class RouteExecutor
5
5
  def initialize(container, dandy_config, view_factory)
6
6
  @container = container
7
7
  @dandy_config = dandy_config
@@ -12,7 +12,7 @@ module Dandy
12
12
  chain = Chain.new(@container, @dandy_config)
13
13
 
14
14
  begin
15
- result = chain.run_commands(route.commands, route.last_command)
15
+ result = chain.run_commands(route.commands, route.last_command, :dandy_request)
16
16
  if route.view
17
17
  result = @view_factory.create(route.view, headers['Accept'], {keys_format: headers['Keys-Format'] || 'snake'})
18
18
  end
@@ -0,0 +1,25 @@
1
+ require 'dandy/routing/message_handler'
2
+
3
+ module Dandy
4
+ module Routing
5
+ class HandlersBuilder
6
+ def initialize
7
+ @parsed_items = []
8
+ @route_params = []
9
+ @current_parent = nil
10
+ @prev_route = nil
11
+ end
12
+
13
+ def build(section)
14
+ section.messages.map do |message|
15
+ MessageHandler.new({
16
+ name: message.name,
17
+ catch: section.catch.command,
18
+ last_command: message.command_list.last,
19
+ commands: section.before_commands + message.command_list + section.after_commands
20
+ })
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,15 @@
1
+ module Dandy
2
+ module Routing
3
+ class MessageHandler
4
+ attr_reader :name, :params, :catch,
5
+ :commands, :last_command
6
+
7
+ def initialize(hash)
8
+ @name = hash[:name]
9
+ @commands = hash[:commands]
10
+ @last_command = hash[:last_command]
11
+ @catch = hash[:catch]
12
+ end
13
+ end
14
+ end
15
+ end
@@ -1,10 +1,11 @@
1
1
  module Dandy
2
2
  module Routing
3
3
  class Parser
4
- def initialize(file_reader, routes_builder,
4
+ def initialize(file_reader, routes_builder, handlers_builder,
5
5
  syntax_parser, syntax_error_interpreter)
6
6
  @file_reader = file_reader
7
7
  @routes_builder = routes_builder
8
+ @handlers_builder = handlers_builder
8
9
  @syntax_parser = syntax_parser
9
10
  @syntax_error_interpreter = syntax_error_interpreter
10
11
  end
@@ -18,7 +19,18 @@ module Dandy
18
19
  raise Dandy::SyntaxError, error_message
19
20
  end
20
21
 
21
- @routes_builder.build(tree.parse)
22
+ dandy = tree.parse
23
+
24
+ result = {}
25
+ if dandy.requests
26
+ result[:routes] = @routes_builder.build(dandy.requests)
27
+ end
28
+
29
+ if dandy.messages
30
+ result[:message_handlers] = @handlers_builder.build(dandy.messages)
31
+ end
32
+
33
+ result
22
34
  end
23
35
  end
24
36
  end
@@ -2,7 +2,7 @@
2
2
 
3
3
  module Dandy
4
4
  module Routing
5
- class Builder
5
+ class RoutesBuilder
6
6
  def initialize
7
7
  @parsed_items = []
8
8
  @route_params = []
@@ -10,10 +10,10 @@ module Dandy
10
10
  @prev_route = nil
11
11
  end
12
12
 
13
- def build(sections)
13
+ def build(requests)
14
14
  result = []
15
15
 
16
- node = sections.node
16
+ node = requests.node
17
17
  restore_hierarchy(node, nil, node.to_hash)
18
18
 
19
19
  @route_params.each do |route|
@@ -25,7 +25,7 @@ module Dandy
25
25
  http_verb: action[:http_verb],
26
26
  view: action[:view],
27
27
  http_status: action[:http_status],
28
- catch: sections.catch.command,
28
+ catch: requests.catch.command,
29
29
  last_command: action[:commands].last,
30
30
  commands: restore_callbacks(route, :before) + action[:commands] + restore_callbacks(route, :after)
31
31
  })
@@ -1,5 +1,6 @@
1
1
  require 'treetop'
2
- require 'dandy/routing/builder'
2
+ require 'dandy/routing/routes_builder'
3
+ require 'dandy/routing/handlers_builder'
3
4
  require 'dandy/routing/parser'
4
5
  require 'dandy/routing/matcher'
5
6
  require 'dandy/routing/file_reader'
@@ -20,11 +20,17 @@ require_relative 'syntax/route'
20
20
  require_relative 'syntax/respond'
21
21
 
22
22
 
23
- require_relative 'syntax/sections'
23
+ require_relative 'syntax/requests'
24
24
  require_relative 'syntax/before_section'
25
25
  require_relative 'syntax/tree_section'
26
26
  require_relative 'syntax/after_section'
27
27
  require_relative 'syntax/catch_section'
28
28
 
29
+ require_relative 'syntax/message_name'
30
+ require_relative 'syntax/message'
31
+ require_relative 'syntax/messages'
32
+
33
+ require_relative 'syntax/dandy'
34
+
29
35
  module Syntax
30
36
  end
@@ -0,0 +1,20 @@
1
+ module Syntax
2
+ class Dandy < Treetop::Runtime::SyntaxNode
3
+ attr_reader :requests, :messages
4
+
5
+ def parse
6
+ elements.each do |element|
7
+ element.elements.each do |nested|
8
+ if nested.is_a? Requests
9
+ @requests = nested.parse
10
+ end
11
+
12
+ if nested.is_a? Messages
13
+ @messages = nested.parse
14
+ end
15
+ end
16
+ end
17
+ self
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,19 @@
1
+ module Syntax
2
+ class Message < Treetop::Runtime::SyntaxNode
3
+ attr_accessor :name, :command_list
4
+
5
+ def parse
6
+ elements.each do |element|
7
+ if element.is_a? MessageName
8
+ @name = element.parse
9
+ end
10
+
11
+ if element.is_a? Commands
12
+ @command_list = element.parse
13
+ end
14
+ end
15
+
16
+ self
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,7 @@
1
+ module Syntax
2
+ class MessageName < Treetop::Runtime::SyntaxNode
3
+ def parse
4
+ text_value.gsub('"','')
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,35 @@
1
+ module Syntax
2
+ class Messages < Treetop::Runtime::SyntaxNode
3
+ attr_reader :messages, :catch, :before_commands, :after_commands
4
+
5
+ def parse
6
+ @messages ||= []
7
+ @before_commands = []
8
+ @after_commands = []
9
+
10
+ elements.each do |element|
11
+ if element.elements
12
+ element.elements.each do |nested|
13
+ if nested.is_a? Message
14
+ @messages << nested.parse
15
+ end
16
+ end
17
+ end
18
+
19
+ if element.is_a? BeforeSection
20
+ @before_commands = element.parse.commands
21
+ end
22
+
23
+ if element.is_a? AfterSection
24
+ @after_commands = element.parse.commands
25
+ end
26
+
27
+ if element.is_a? CatchSection
28
+ @catch = element.parse
29
+ end
30
+ end
31
+
32
+ self
33
+ end
34
+ end
35
+ end
@@ -1,5 +1,5 @@
1
1
  module Syntax
2
- class Sections < Treetop::Runtime::SyntaxNode
2
+ class Requests < Treetop::Runtime::SyntaxNode
3
3
  attr_reader :node, :catch
4
4
 
5
5
  def parse
@@ -1,6 +1,22 @@
1
1
  grammar Syntax
2
- rule sections
3
- ':receive' eol node catch <Sections>
2
+ rule dandy
3
+ (requests) 0..1 (messages) 0..1 <Dandy>
4
+ end
5
+
6
+ rule requests
7
+ ':request' eol node catch <Requests>
8
+ end
9
+
10
+ rule messages
11
+ ':message' eol before after message+ catch <Messages>
12
+ end
13
+
14
+ rule message
15
+ indent message_name commands eol <Message>
16
+ end
17
+
18
+ rule message_name
19
+ '"' [a-z0-9_\-.]+ '"' <MessageName>
4
20
  end
5
21
 
6
22
  rule before
data/lib/dandy/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Dandy
2
- VERSION = '1.0.3'
2
+ VERSION = '2.0.0-alpha'
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dandy
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.3
4
+ version: 2.0.0.pre.alpha
5
5
  platform: ruby
6
6
  authors:
7
7
  - Vladimir Kalinkin
8
- autorequire:
8
+ autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-09-07 00:00:00.000000000 Z
11
+ date: 2021-06-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: hypo
@@ -231,6 +231,7 @@ files:
231
231
  - lib/dandy/base/handle_errors.rb
232
232
  - lib/dandy/chain.rb
233
233
  - lib/dandy/config.rb
234
+ - lib/dandy/consumer.rb
234
235
  - lib/dandy/errors/dandy_error.rb
235
236
  - lib/dandy/errors/syntax_error.rb
236
237
  - lib/dandy/errors/view_engine_error.rb
@@ -252,17 +253,22 @@ files:
252
253
  - lib/dandy/generators/templates/dandy.yml
253
254
  - lib/dandy/generators/templates/db/mapping.rb
254
255
  - lib/dandy/generators/templates/views/show_welcome.json.jbuilder
256
+ - lib/dandy/handler_executor.rb
255
257
  - lib/dandy/loaders/dependency_loader.rb
256
258
  - lib/dandy/loaders/template_loader.rb
257
259
  - lib/dandy/loaders/type_loader.rb
260
+ - lib/dandy/message.rb
258
261
  - lib/dandy/request.rb
259
262
  - lib/dandy/response.rb
260
- - lib/dandy/routing/builder.rb
263
+ - lib/dandy/route_executor.rb
261
264
  - lib/dandy/routing/file_reader.rb
265
+ - lib/dandy/routing/handlers_builder.rb
262
266
  - lib/dandy/routing/match.rb
263
267
  - lib/dandy/routing/matcher.rb
268
+ - lib/dandy/routing/message_handler.rb
264
269
  - lib/dandy/routing/parser.rb
265
270
  - lib/dandy/routing/route.rb
271
+ - lib/dandy/routing/routes_builder.rb
266
272
  - lib/dandy/routing/routing.rb
267
273
  - lib/dandy/routing/syntax.rb
268
274
  - lib/dandy/routing/syntax/action.rb
@@ -272,6 +278,10 @@ files:
272
278
  - lib/dandy/routing/syntax/catch_section.rb
273
279
  - lib/dandy/routing/syntax/command.rb
274
280
  - lib/dandy/routing/syntax/commands.rb
281
+ - lib/dandy/routing/syntax/dandy.rb
282
+ - lib/dandy/routing/syntax/message.rb
283
+ - lib/dandy/routing/syntax/message_name.rb
284
+ - lib/dandy/routing/syntax/messages.rb
275
285
  - lib/dandy/routing/syntax/node.rb
276
286
  - lib/dandy/routing/syntax/nodes.rb
277
287
  - lib/dandy/routing/syntax/primitives/arrow.rb
@@ -284,14 +294,13 @@ files:
284
294
  - lib/dandy/routing/syntax/primitives/parameter.rb
285
295
  - lib/dandy/routing/syntax/primitives/path.rb
286
296
  - lib/dandy/routing/syntax/primitives/result_name.rb
297
+ - lib/dandy/routing/syntax/requests.rb
287
298
  - lib/dandy/routing/syntax/respond.rb
288
299
  - lib/dandy/routing/syntax/route.rb
289
- - lib/dandy/routing/syntax/sections.rb
290
300
  - lib/dandy/routing/syntax/tree_section.rb
291
301
  - lib/dandy/routing/syntax/view.rb
292
302
  - lib/dandy/routing/syntax_error_interpreter.rb
293
303
  - lib/dandy/routing/syntax_grammar.tt
294
- - lib/dandy/safe_executor.rb
295
304
  - lib/dandy/template_registry.rb
296
305
  - lib/dandy/version.rb
297
306
  - lib/dandy/view_builder.rb
@@ -303,7 +312,7 @@ licenses:
303
312
  - MIT
304
313
  metadata:
305
314
  allowed_push_host: https://rubygems.org
306
- post_install_message:
315
+ post_install_message:
307
316
  rdoc_options: []
308
317
  require_paths:
309
318
  - lib
@@ -314,12 +323,12 @@ required_ruby_version: !ruby/object:Gem::Requirement
314
323
  version: '0'
315
324
  required_rubygems_version: !ruby/object:Gem::Requirement
316
325
  requirements:
317
- - - ">="
326
+ - - ">"
318
327
  - !ruby/object:Gem::Version
319
- version: '0'
328
+ version: 1.3.1
320
329
  requirements: []
321
- rubygems_version: 3.1.2
322
- signing_key:
330
+ rubygems_version: 3.2.15
331
+ signing_key:
323
332
  specification_version: 4
324
333
  summary: Dandy is a minimalistic web API framework.
325
334
  test_files: []