light-services 2.0.0.rc1 → 2.0.0.rc6

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
  SHA256:
3
- metadata.gz: 3274d2f86c3525ce73f2bcdc5e90f3da5e09979ee4f5f6425a5a41ef482489a2
4
- data.tar.gz: 2b4a0f8657f730b184b22c5eccd3273e7bdfc8abcfe7c9ec61852b38260eee48
3
+ metadata.gz: 06c568f730742de7555fcdccd76689a7ae983dbc97880935b2587439f1707d29
4
+ data.tar.gz: 48ad82deadfae1e28300aea79fdb6b220f3c2a29e4e082419cb43743aebfda15
5
5
  SHA512:
6
- metadata.gz: 1420e6b25d7b48cc2924a02fde1fc0f9aa9701a9c2d0faf0643ebc508e6d2eca3be6e650b42ecdd3947683899acb9ca47388bf392d0372157b73208b17f8b294
7
- data.tar.gz: 44e1641a0ce332a8f4904ee278f3d116452335cb5186025536242a7b9714aedea55c0a3e629159b6d46feb82f4b979d1fab41baef0e4fa5fb35aa47151c778fe
6
+ metadata.gz: e55a6a1b112d794368d08c4c487734613e24d8fbf1ec5d9b097f0cba22148f37325053db5568a9715ab0d1c8ba3abb22b5762657e5b838048fe6e4c11a6cb6ec
7
+ data.tar.gz: 84ffbca0ddfade25831c0b2c7597455200a98149e6a2e102923ec9298faa4d0486a97c5b06d2d2e0a974cb47a43feb84bc4748ee3bda3aec5731b5ff132bd089
data/.gitignore CHANGED
@@ -15,3 +15,6 @@
15
15
  # Ignore IDE files
16
16
  /.idea
17
17
  *.iml
18
+
19
+ # Ignore gem files
20
+ *.gem
data/Gemfile.lock CHANGED
@@ -1,85 +1,86 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- light-services (2.0.0.beta1)
4
+ light-services (2.0.0.rc5)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
8
8
  specs:
9
- activemodel (6.0.3.2)
10
- activesupport (= 6.0.3.2)
11
- activerecord (6.0.3.2)
12
- activemodel (= 6.0.3.2)
13
- activesupport (= 6.0.3.2)
14
- activesupport (6.0.3.2)
9
+ activemodel (6.1.4)
10
+ activesupport (= 6.1.4)
11
+ activerecord (6.1.4)
12
+ activemodel (= 6.1.4)
13
+ activesupport (= 6.1.4)
14
+ activesupport (6.1.4)
15
15
  concurrent-ruby (~> 1.0, >= 1.0.2)
16
- i18n (>= 0.7, < 2)
17
- minitest (~> 5.1)
18
- tzinfo (~> 1.1)
19
- zeitwerk (~> 2.2, >= 2.2.2)
20
- ast (2.4.1)
21
- codecov (0.1.17)
16
+ i18n (>= 1.6, < 2)
17
+ minitest (>= 5.1)
18
+ tzinfo (~> 2.0)
19
+ zeitwerk (~> 2.3)
20
+ ast (2.4.2)
21
+ codecov (0.1.21)
22
22
  json
23
23
  simplecov
24
- url
25
- concurrent-ruby (1.1.6)
26
- database_cleaner (1.8.5)
27
- database_cleaner-active_record (1.8.0)
24
+ concurrent-ruby (1.1.9)
25
+ database_cleaner (1.99.0)
26
+ database_cleaner-active_record (1.99.0)
28
27
  activerecord
29
- database_cleaner (~> 1.8.0)
30
- diff-lcs (1.4.2)
31
- docile (1.3.2)
32
- i18n (1.8.3)
28
+ database_cleaner (~> 1.99.0)
29
+ diff-lcs (1.4.4)
30
+ docile (1.4.0)
31
+ i18n (1.8.10)
33
32
  concurrent-ruby (~> 1.0)
34
- json (2.3.0)
35
- minitest (5.14.1)
36
- parallel (1.19.2)
37
- parser (2.7.1.4)
33
+ json (2.5.1)
34
+ minitest (5.14.4)
35
+ parallel (1.20.1)
36
+ parser (3.0.2.0)
38
37
  ast (~> 2.4.1)
39
38
  rainbow (3.0.0)
40
- rake (13.0.1)
41
- regexp_parser (1.7.1)
42
- rexml (3.2.4)
43
- rspec (3.9.0)
44
- rspec-core (~> 3.9.0)
45
- rspec-expectations (~> 3.9.0)
46
- rspec-mocks (~> 3.9.0)
47
- rspec-core (3.9.2)
48
- rspec-support (~> 3.9.3)
49
- rspec-expectations (3.9.2)
39
+ rake (13.0.6)
40
+ regexp_parser (2.1.1)
41
+ rexml (3.2.5)
42
+ rspec (3.10.0)
43
+ rspec-core (~> 3.10.0)
44
+ rspec-expectations (~> 3.10.0)
45
+ rspec-mocks (~> 3.10.0)
46
+ rspec-core (3.10.1)
47
+ rspec-support (~> 3.10.0)
48
+ rspec-expectations (3.10.1)
50
49
  diff-lcs (>= 1.2.0, < 2.0)
51
- rspec-support (~> 3.9.0)
52
- rspec-mocks (3.9.1)
50
+ rspec-support (~> 3.10.0)
51
+ rspec-mocks (3.10.2)
53
52
  diff-lcs (>= 1.2.0, < 2.0)
54
- rspec-support (~> 3.9.0)
55
- rspec-support (3.9.3)
56
- rubocop (0.86.0)
53
+ rspec-support (~> 3.10.0)
54
+ rspec-support (3.10.2)
55
+ rubocop (0.93.1)
57
56
  parallel (~> 1.10)
58
- parser (>= 2.7.0.1)
57
+ parser (>= 2.7.1.5)
59
58
  rainbow (>= 2.2.2, < 4.0)
60
- regexp_parser (>= 1.7)
59
+ regexp_parser (>= 1.8)
61
60
  rexml
62
- rubocop-ast (>= 0.0.3, < 1.0)
61
+ rubocop-ast (>= 0.6.0)
63
62
  ruby-progressbar (~> 1.7)
64
63
  unicode-display_width (>= 1.4.0, < 2.0)
65
- rubocop-ast (0.0.3)
66
- parser (>= 2.7.0.1)
67
- rubocop-performance (1.6.1)
68
- rubocop (>= 0.71.0)
69
- rubocop-rspec (1.40.0)
70
- rubocop (>= 0.68.1)
71
- ruby-progressbar (1.10.1)
72
- simplecov (0.18.5)
64
+ rubocop-ast (1.8.0)
65
+ parser (>= 3.0.1.1)
66
+ rubocop-performance (1.10.2)
67
+ rubocop (>= 0.90.0, < 2.0)
68
+ rubocop-ast (>= 0.4.0)
69
+ rubocop-rspec (1.44.1)
70
+ rubocop (~> 0.87)
71
+ rubocop-ast (>= 0.7.1)
72
+ ruby-progressbar (1.11.0)
73
+ simplecov (0.21.2)
73
74
  docile (~> 1.1)
74
75
  simplecov-html (~> 0.11)
75
- simplecov-html (0.12.2)
76
+ simplecov_json_formatter (~> 0.1)
77
+ simplecov-html (0.12.3)
78
+ simplecov_json_formatter (0.1.3)
76
79
  sqlite3 (1.4.2)
77
- thread_safe (0.3.6)
78
- tzinfo (1.2.7)
79
- thread_safe (~> 0.1)
80
+ tzinfo (2.0.4)
81
+ concurrent-ruby (~> 1.0)
80
82
  unicode-display_width (1.7.0)
81
- url (0.3.2)
82
- zeitwerk (2.3.1)
83
+ zeitwerk (2.4.2)
83
84
 
84
85
  PLATFORMS
85
86
  ruby
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "light/services/message"
3
4
  require "light/services/messages"
4
5
  require "light/services/base_with_context"
5
6
 
@@ -45,6 +46,7 @@ module Light
45
46
  @outputs = Collection::Outputs.new(self)
46
47
  @arguments = Collection::Arguments.new(self, args)
47
48
 
49
+ @done = false
48
50
  @launched_steps = []
49
51
 
50
52
  initialize_errors
@@ -67,6 +69,14 @@ module Light
67
69
  @warnings.any?
68
70
  end
69
71
 
72
+ def done!
73
+ @done = true
74
+ end
75
+
76
+ def done?
77
+ @done
78
+ end
79
+
70
80
  def call
71
81
  time = Benchmark.ms do
72
82
  run_steps
@@ -83,9 +93,12 @@ module Light
83
93
  end
84
94
 
85
95
  class << self
86
- # TODO: Create `run!`
87
- def run(args = {})
88
- new(args).tap(&:call)
96
+ def run(args = {}, config = {})
97
+ new(args, config).tap(&:call)
98
+ end
99
+
100
+ def run!(args = {})
101
+ run(args, raise_on_error: true)
89
102
  end
90
103
 
91
104
  def with(service_or_config = {}, config = {})
@@ -14,11 +14,15 @@ module Light
14
14
  raise Light::Services::ArgTypeError, "#{parent_service.class} - must be a subclass of Light::Services::Base"
15
15
  end
16
16
 
17
- # TODO: Create `run!`
18
17
  def run(args = {})
19
18
  @service_class.new(extend_arguments(args), @config, @parent_service).tap(&:call)
20
19
  end
21
20
 
21
+ def run!(args = {})
22
+ @config[:raise_on_error] = true
23
+ run(args)
24
+ end
25
+
22
26
  private
23
27
 
24
28
  def extend_arguments(args)
@@ -63,14 +63,12 @@ module Light
63
63
 
64
64
  def validate_name!(klass, name)
65
65
  if !@allow_redefine && all(klass).key?(name)
66
- # TODO: Update error class
67
66
  raise Light::Services::Error, "#{@item_class} with name `#{name}` already exists in service #{klass}"
68
67
  end
69
68
  end
70
69
 
71
70
  def validate_opts!(klass, name, opts)
72
71
  if opts[:before] && opts[:after]
73
- # TODO: Update error class
74
72
  raise Light::Services::Error, "You cannot specify `before` and `after` " \
75
73
  "for #{@item_class} `#{name}` in service #{klass} at the same time"
76
74
  end
@@ -28,6 +28,14 @@ module Light
28
28
  @storage[key]
29
29
  end
30
30
 
31
+ def [](key)
32
+ get(key)
33
+ end
34
+
35
+ def []=(key, value)
36
+ set(key, value)
37
+ end
38
+
31
39
  def load_defaults
32
40
  settings_collection.each do |name, settings|
33
41
  next if !settings.default_exists || key?(name)
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ # This class stores errors and warnings
4
+ module Light
5
+ module Services
6
+ class Message
7
+ # Getters
8
+ attr_reader :key, :text
9
+
10
+ def initialize(key, text, opts = {})
11
+ @key = key
12
+ @text = text
13
+ @opts = opts
14
+ end
15
+
16
+ def break?
17
+ @opts[:break]
18
+ end
19
+
20
+ def rollback?
21
+ @opts[:rollback]
22
+ end
23
+
24
+ def to_s
25
+ text
26
+ end
27
+ end
28
+ end
29
+ end
@@ -10,18 +10,21 @@ module Light
10
10
  @messages = {}
11
11
  end
12
12
 
13
- def add(key, message, opts = {})
14
- @messages[key] ||= []
13
+ def add(key, text, opts = {})
14
+ raise Light::Services::Error, "Error text can't be blank" if !text || text.blank?
15
15
 
16
- if message.is_a?(Array)
17
- @messages[key] += message
18
- else
16
+ message = nil
17
+
18
+ [*text].each do |text|
19
+ message = text.is_a?(Message) ? text : Message.new(key, text, opts)
20
+
21
+ @messages[key] ||= []
19
22
  @messages[key] << message
20
23
  end
21
24
 
22
- raise!(key, message)
23
- break!(opts[:break])
24
- rollback!(opts[:rollback])
25
+ raise!(message)
26
+ break!(opts.key?(:break) ? opts[:break] : message.break?)
27
+ rollback!(opts.key?(:rollback) ? opts[:rollback] : message.rollback?) if !opts.key?(:last) || opts[:last]
25
28
  end
26
29
 
27
30
  def break?
@@ -31,45 +34,40 @@ module Light
31
34
  def copy_from(entity, opts = {})
32
35
  if defined?(ActiveRecord::Base) && entity.is_a?(ActiveRecord::Base)
33
36
  copy_from(entity.errors.messages, opts)
37
+ elsif entity.is_a?(Light::Services::Base)
38
+ copy_from(entity.errors, opts)
34
39
  elsif entity.respond_to?(:each)
35
- entity.each do |key, message|
36
- add(key, message, opts)
40
+ last_index = entity.size - 1
41
+
42
+ entity.each_with_index do |(key, message), index|
43
+ add(key, message, opts.merge(last: index == last_index))
37
44
  end
38
45
  else
39
- # TODO: Update error
40
- raise Light::Services::Error
46
+ raise Light::Services::Error, "Don't know how to import errors from #{entity}"
41
47
  end
42
48
  end
43
49
 
44
50
  def copy_to(entity)
45
- if defined?(ActiveRecord::Base) && entity.is_a?(ActiveRecord::Base)
46
- each do |key, message|
47
- entity.errors.add(key, message)
51
+ if defined?(ActiveRecord::Base) && entity.is_a?(ActiveRecord::Base) || entity.is_a?(Light::Services::Base)
52
+ each do |key, messages|
53
+ messages.each do |message|
54
+ entity.errors.add(key, message.to_s)
55
+ end
48
56
  end
49
57
  elsif entity.is_a?(Hash)
50
- each do |key, message|
58
+ each do |key, messages|
51
59
  entity[key] ||= []
52
- entity[key] << message
60
+ entity[key] += messages.map(&:to_s)
53
61
  end
54
62
  else
55
- # TODO: Update error
56
- raise Light::Services::Error
63
+ raise Light::Services::Error, "Don't know how to export errors to #{entity}"
57
64
  end
58
65
 
59
66
  entity
60
67
  end
61
68
 
62
- def errors_to_record(record)
63
- if !defined?(ActiveRecord::Base) || !record.is_a?(ActiveRecord::Base)
64
- # TODO: Update error
65
- raise Light::Services::Error
66
- end
67
-
68
- errors.each do |key, message|
69
- record.errors.add(key, message)
70
- end
71
-
72
- record
69
+ def to_h
70
+ @messages.to_h.map { |key, value| [key, value.map(&:to_s)] }.to_h
73
71
  end
74
72
 
75
73
  def method_missing(method, *args, &block)
@@ -92,10 +90,10 @@ module Light
92
90
  @break = true
93
91
  end
94
92
 
95
- def raise!(key, message)
93
+ def raise!(message)
96
94
  return unless @config[:raise_on_add]
97
95
 
98
- raise Light::Services::Error, "#{key.to_s.capitalize} #{message}"
96
+ raise Light::Services::Error, "#{message.key.to_s.capitalize} #{message}"
99
97
  end
100
98
 
101
99
  def rollback!(rollback)
@@ -6,7 +6,7 @@ module Light
6
6
  module Settings
7
7
  class Argument
8
8
  # Getters
9
- attr_reader :name, :default_exists, :default, :context, :optional
9
+ attr_reader :name, :default_exists, :default, :context, :optional, :arg_types_cache
10
10
 
11
11
  def initialize(name, service_class, opts = {})
12
12
  @name = name
@@ -18,6 +18,8 @@ module Light
18
18
  @default = opts.delete(:default)
19
19
  @optional = opts.delete(:optional)
20
20
 
21
+ @arg_types_cache = {}
22
+
21
23
  define_methods
22
24
  end
23
25
 
@@ -25,6 +27,8 @@ module Light
25
27
  return if !@type || [*@type].any? do |type|
26
28
  if type == :boolean
27
29
  value.is_a?(TrueClass) || value.is_a?(FalseClass)
30
+ elsif type.is_a?(Symbol)
31
+ arg_type(value) == type
28
32
  else
29
33
  value.is_a?(type)
30
34
  end
@@ -36,6 +40,19 @@ module Light
36
40
 
37
41
  private
38
42
 
43
+ def arg_type(value)
44
+ klass = value.class
45
+
46
+ @arg_types_cache[klass] ||= klass
47
+ .name
48
+ .gsub(/::/, '/')
49
+ .gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2')
50
+ .gsub(/([a-z\d])([A-Z])/,'\1_\2')
51
+ .tr("-", "_")
52
+ .downcase
53
+ .to_sym
54
+ end
55
+
39
56
  def define_methods
40
57
  name = @name
41
58
 
@@ -45,6 +45,8 @@ module Light
45
45
  private
46
46
 
47
47
  def run?(instance)
48
+ return false if instance.done?
49
+
48
50
  if @if
49
51
  check_condition(@if, instance)
50
52
  elsif @unless
@@ -59,7 +61,7 @@ module Light
59
61
  when Symbol
60
62
  instance.send(condition)
61
63
  when Proc
62
- condition.call
64
+ instance.instance_exec(&condition)
63
65
  else
64
66
  raise Light::Services::Error, "#{@service_class} condition should be a Symbol or Proc " \
65
67
  "for the step `#{@name}` (currently: #{condition.class})"
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Light
4
4
  module Services
5
- VERSION = "2.0.0.rc1"
5
+ VERSION = "2.0.0.rc6"
6
6
  end
7
7
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: light-services
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.0.rc1
4
+ version: 2.0.0.rc6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andrew Emelianenko
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2021-06-10 00:00:00.000000000 Z
11
+ date: 2021-12-20 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: Powerful implementation of Service Object pattern for Ruby and Rails
14
14
  email:
@@ -41,6 +41,7 @@ files:
41
41
  - lib/light/services/collection/outputs.rb
42
42
  - lib/light/services/config.rb
43
43
  - lib/light/services/exceptions.rb
44
+ - lib/light/services/message.rb
44
45
  - lib/light/services/messages.rb
45
46
  - lib/light/services/settings/argument.rb
46
47
  - lib/light/services/settings/output.rb