dandy 0.12.0 → 0.12.1

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: 47781859a32ae38be5a82a4548ee099ce2c745ea
4
- data.tar.gz: b8488633a66da4c980fb3532df442713ae35747c
3
+ metadata.gz: f5fd46a75db6411e264b87e934aff42dd34b2b7e
4
+ data.tar.gz: 681b74058c62074c072f59fab34c98ad21ac3e35
5
5
  SHA512:
6
- metadata.gz: b9ca968a3acd135a2656309c9ca2dd28d4c426b82a7d1b683c502201eeddd2f66772e74e75dfbbb8c1fdd03f50e81323842034e85b59d303da4441bc1a189eb5
7
- data.tar.gz: 7e802942e16d29e0de61a6c501bc62be98d5b1588028f2f1692894d2c633d6822de706d9a693c9d54dce750b317ca9b6aae5b5725f2161db87b8f26b00f0377f
6
+ metadata.gz: a9fc7ea134531646040be3368dcb0745e8bd8d19d4495bd38a0963728f8268c5d46f687f4bc7e0a76c0d55900f80d4ee07dbbbbb211cdce717a7aa809087fb85
7
+ data.tar.gz: 5a2b123dd6e34b828450a519ebb2cbe2bb98b52aa960bb1933956433fdc60d7db6b3166d2db9004ae60ccd4ddb604184e91f6581de7273c7c9ba7b8be0fdb730
@@ -9,9 +9,9 @@ require 'dandy/request'
9
9
  require 'dandy/template_registry'
10
10
  require 'dandy/view_builder_registry'
11
11
  require 'dandy/view_factory'
12
- require 'dandy/chain_factory'
13
12
  require 'dandy/view_builders/json'
14
13
  require 'dandy/routing/routing'
14
+ require 'dandy/safe_executor'
15
15
 
16
16
  module Dandy
17
17
  class App
@@ -27,7 +27,7 @@ module Dandy
27
27
  end
28
28
 
29
29
  def call(env)
30
- request = Request.new(@route_matcher, @container, @chain_factory, @view_factory)
30
+ request = Request.new(@route_matcher, @container, @safe_executor)
31
31
  request.handle(env)
32
32
  end
33
33
 
@@ -61,12 +61,12 @@ module Dandy
61
61
  template_registry: TemplateRegistry,
62
62
  view_builder_registry: ViewBuilderRegistry,
63
63
  view_factory: ViewFactory,
64
- chain_factory: ChainFactory,
65
64
  file_reader: Routing::FileReader,
66
65
  syntax_parser: SyntaxParser,
67
66
  syntax_error_interpreter: Routing::SyntaxErrorInterpreter,
68
67
  routes_builder: Routing::Builder,
69
- route_parser: Routing::Parser
68
+ route_parser: Routing::Parser,
69
+ safe_executor: SafeExecutor
70
70
  }
71
71
 
72
72
  singletons.keys.each do |name|
@@ -76,11 +76,12 @@ module Dandy
76
76
  end
77
77
 
78
78
  def load_basic_dependencies
79
- @chain_factory = @container.resolve(:chain_factory)
79
+ @dandy_config = @container.resolve(:dandy_config)
80
80
  @view_factory = @container.resolve(:view_factory)
81
81
  @dependency_loader = @container.resolve(:dependency_loader)
82
82
  @view_builder_registry = @container.resolve(:view_builder_registry)
83
83
  @route_parser = @container.resolve(:route_parser)
84
+ @safe_executor = @container.resolve(:safe_executor)
84
85
 
85
86
  @dependency_loader.load_components
86
87
  end
@@ -2,46 +2,23 @@ require 'timeout'
2
2
 
3
3
  module Dandy
4
4
  class Chain
5
- def initialize(container, dandy_config, commands, last_command, catch_command = nil)
6
- @commands = commands
7
- @last_command = last_command
5
+ def initialize(container, dandy_config)
8
6
  @container = container
9
- @catch_command = catch_command
10
7
  @async_timeout = dandy_config[:action][:async_timeout]
11
8
  end
12
9
 
13
- def execute
14
- if @catch_command.nil?
15
- run_commands
16
- else
17
- begin
18
- run_commands
19
- rescue Exception => error
20
- @container
21
- .register_instance(error, :dandy_error)
22
- .using_lifetime(:scope)
23
- .bound_to(:dandy_request)
24
-
25
- action = @container.resolve(@catch_command.name.to_sym)
26
- action.call
27
- end
28
- end
29
- end
30
-
31
- private
32
-
33
- def run_commands
10
+ def run_commands(commands, last_command)
34
11
  threads = []
35
12
  Thread.abort_on_exception = true
36
13
 
37
14
  result = nil
38
- @commands.each_with_index do |command, index|
15
+ commands.each_with_index do |command, index|
39
16
  if command.sequential?
40
17
  # all previous parallel commands should be done before the current sequential
41
18
  threads.each {|t| t.join}
42
19
  threads = []
43
20
 
44
- if @last_command && (command.name == @last_command.name)
21
+ if last_command && (command.name == last_command.name)
45
22
  result = run_command(command)
46
23
  else
47
24
  run_command(command)
@@ -49,7 +26,7 @@ module Dandy
49
26
  else
50
27
  thread = Thread.new {
51
28
  Timeout::timeout(@async_timeout) {
52
- if @last_command && (command.name == @last_command.name)
29
+ if last_command && (command.name == last_command.name)
53
30
  result = run_command(command)
54
31
  else
55
32
  run_command(command)
@@ -60,7 +37,7 @@ module Dandy
60
37
  end
61
38
 
62
39
  # if it's last item in chain then wait until parallel commands are done
63
- if index == @commands.length - 1
40
+ if index == commands.length - 1
64
41
  threads.each {|t| t.join}
65
42
  end
66
43
  end
@@ -68,6 +45,8 @@ module Dandy
68
45
  result
69
46
  end
70
47
 
48
+ private
49
+
71
50
  def run_command(command)
72
51
  if command.entity?
73
52
  entity = @container.resolve(command.entity_name.to_sym)
@@ -1,21 +1,19 @@
1
1
  require 'json'
2
+ require 'awrence'
3
+ require 'plissken'
2
4
  require 'rack/multipart'
3
5
  require 'dandy/extensions/hash'
4
- require 'dandy/chain_factory'
5
6
  require 'dandy/view_factory'
6
- require 'awrence'
7
- require 'plissken'
8
-
7
+ require 'dandy/chain'
9
8
 
10
9
  module Dandy
11
10
  class Request
12
11
  include Hypo::Scope
13
12
 
14
- def initialize(route_matcher, container, chain_factory, view_factory)
13
+ def initialize(route_matcher, container, safe_executor)
15
14
  @container = container
16
15
  @route_matcher = route_matcher
17
- @chain_factory = chain_factory
18
- @view_factory = view_factory
16
+ @safe_executor = safe_executor
19
17
  end
20
18
 
21
19
  def handle(rack_env)
@@ -31,36 +29,26 @@ module Dandy
31
29
  .collect {|k, v| [k.split('_').collect(&:capitalize).join('-'), v]}
32
30
  .flatten
33
31
  ]
34
- register_params(headers, :dandy_headers)
32
+
33
+ register_context(headers, :dandy_headers)
35
34
 
36
35
  if match.nil?
37
36
  result = [404, {'Content-Type' => headers['Accept']}, []]
38
37
  else
38
+ status = match.route.http_status || default_http_status(match.route.http_verb)
39
+ register_params(match.params)
40
+ register_status(status)
41
+
39
42
  query = Rack::Utils.parse_nested_query(rack_env['QUERY_STRING']).to_snake_keys.symbolize_keys
40
- register_params(query, :dandy_query)
43
+ register_context(query, :dandy_query)
41
44
 
42
45
  data = rack_env['rack.parser.result'] ? rack_env['rack.parser.result'].to_snake_keys.deep_symbolize_keys! : {}
43
- register_params(data, :dandy_data)
46
+ register_context(data, :dandy_data)
44
47
 
45
48
  multipart = Rack::Multipart.parse_multipart(rack_env) || {}
46
- register_params(multipart.values, :dandy_files)
47
-
48
- chain = @chain_factory.create(match)
49
- chain_result = chain.execute
49
+ register_context(multipart.values, :dandy_files)
50
50
 
51
- if match.route.view
52
- body = @view_factory.create(match.route.view, headers['Accept'], {keys_format: headers['Keys-Format'] || 'snake'})
53
- else
54
- if chain_result.is_a?(String)
55
- body = chain_result
56
- else # generate JSON when nothing other is requested
57
- if headers['Keys-Format'] == 'camel' && chain_result
58
- chain_result = chain_result.to_camelback_keys
59
- end
60
-
61
- body = JSON.generate(chain_result)
62
- end
63
- end
51
+ body = @safe_executor.execute(match.route, headers)
64
52
 
65
53
  status = @container.resolve(:dandy_status)
66
54
  result = [status, {'Content-Type' => headers['Accept']}, [body]]
@@ -80,12 +68,32 @@ module Dandy
80
68
  .bound_to(self)
81
69
  end
82
70
 
83
- def register_params(params, name)
71
+ def register_context(params, name)
84
72
  unless params.nil?
85
73
  @container.register_instance(params, name)
86
74
  .using_lifetime(:scope)
87
75
  .bound_to(:dandy_request)
88
76
  end
89
77
  end
78
+
79
+ def register_params(params)
80
+ params.keys.each do |key|
81
+ @container
82
+ .register_instance(params[key], key.to_sym)
83
+ .using_lifetime(:scope)
84
+ .bound_to(:dandy_request)
85
+ end
86
+ end
87
+
88
+ def register_status(status)
89
+ @container
90
+ .register_instance(status, :dandy_status)
91
+ .using_lifetime(:scope)
92
+ .bound_to(:dandy_request)
93
+ end
94
+
95
+ def default_http_status(http_verb)
96
+ http_verb == 'POST' ? 201 : 200
97
+ end
90
98
  end
91
99
  end
@@ -0,0 +1,41 @@
1
+ module Dandy
2
+ class SafeExecutor
3
+ def initialize(container, dandy_config, view_factory)
4
+ @container = container
5
+ @dandy_config = dandy_config
6
+ @view_factory = view_factory
7
+ end
8
+
9
+ def execute(route, headers)
10
+ chain = Chain.new(@container, @dandy_config)
11
+
12
+ begin
13
+ result = chain.run_commands(route.commands, route.last_command)
14
+ if route.view
15
+ result = @view_factory.create(route.view, headers['Accept'], {keys_format: headers['Keys-Format'] || 'snake'})
16
+ end
17
+
18
+ body = result.is_a?(String) ? result : format_response(result, headers)
19
+ rescue Exception => error
20
+ @container
21
+ .register_instance(error, :dandy_error)
22
+ .using_lifetime(:scope)
23
+ .bound_to(:dandy_request)
24
+
25
+ action = @container.resolve(route.catch.name.to_sym)
26
+ body = format_response(action.call, headers)
27
+ end
28
+
29
+ body
30
+ end
31
+
32
+ private
33
+ def format_response(result, headers)
34
+ if headers['Keys-Format'] == 'camel' && result
35
+ result = result.to_camelback_keys
36
+ end
37
+
38
+ JSON.generate(result)
39
+ end
40
+ end
41
+ end
@@ -1,3 +1,3 @@
1
1
  module Dandy
2
- VERSION = '0.12.0'.freeze
2
+ VERSION = '0.12.1'.freeze
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: 0.12.0
4
+ version: 0.12.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Vladimir Kalinkin
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2018-05-20 00:00:00.000000000 Z
11
+ date: 2018-05-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: hypo
@@ -230,7 +230,6 @@ files:
230
230
  - lib/dandy/app.rb
231
231
  - lib/dandy/base/handle_errors.rb
232
232
  - lib/dandy/chain.rb
233
- - lib/dandy/chain_factory.rb
234
233
  - lib/dandy/config.rb
235
234
  - lib/dandy/errors/dandy_error.rb
236
235
  - lib/dandy/errors/syntax_error.rb
@@ -288,6 +287,7 @@ files:
288
287
  - lib/dandy/routing/syntax/view.rb
289
288
  - lib/dandy/routing/syntax_error_interpreter.rb
290
289
  - lib/dandy/routing/syntax_grammar.tt
290
+ - lib/dandy/safe_executor.rb
291
291
  - lib/dandy/template_registry.rb
292
292
  - lib/dandy/version.rb
293
293
  - lib/dandy/view_builder.rb
@@ -1,39 +0,0 @@
1
- require 'dandy/chain'
2
-
3
- module Dandy
4
- class ChainFactory
5
- def initialize(container, dandy_config)
6
- @container = container
7
- @dandy_config = dandy_config
8
- end
9
-
10
- def create(match)
11
- status = match.route.http_status || default_http_status(match.route.http_verb)
12
- register_params(match.params)
13
- register_status(status)
14
- Chain.new(@container, @dandy_config, match.route.commands, match.route.last_command, match.route.catch)
15
- end
16
-
17
- private
18
-
19
- def register_params(params)
20
- params.keys.each do |key|
21
- @container
22
- .register_instance(params[key], key.to_sym)
23
- .using_lifetime(:scope)
24
- .bound_to(:dandy_request)
25
- end
26
- end
27
-
28
- def register_status(status)
29
- @container
30
- .register_instance(status, :dandy_status)
31
- .using_lifetime(:scope)
32
- .bound_to(:dandy_request)
33
- end
34
-
35
- def default_http_status(http_verb)
36
- http_verb == 'POST' ? 201 : 200
37
- end
38
- end
39
- end