servactory 1.6.5 → 1.6.7

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: 7e0ef0253d0030321767ea6a532f52fada7923dcf9f0cc87e7651d7df5a1ec57
4
- data.tar.gz: 5e080cef06176ffdd734802503cf987fa6608f3acccf7d1497da6ad0968142c9
3
+ metadata.gz: 36958cd40c5a7f821265cbbaa4509262da61fb1dcb799d9ba57433012d2e35c1
4
+ data.tar.gz: 3a7a5736e738bc71be30ddef3bee4c536c108a29f24493da9359aa3cfd3eef3c
5
5
  SHA512:
6
- metadata.gz: 1195d6f2dcebe355307197eaf11cf0591ba5d9486020572afc8e4991741920664d0f8525052c1d1742e9af14eee627634e7be439529e9827ecfdaa437e87c8a0
7
- data.tar.gz: 48ed814dff14b30ac71d3484649ac7412e54ec8edcdc2bc8bcaa925d2babac1573efd473547717d83ea821064926ca8a9810c34fa91995d018d7b5e6c23bc221
6
+ metadata.gz: e9b3da95a52a025298169b2f6eea8e6b75bf538dc1ea98c4e903c3c43e50dccada335f37b6883f1cf7c1cb49ed4370a2b182ee2c05cb1c48e35b888575bdd26e
7
+ data.tar.gz: d52fe6ad625529e3f5efb114cbea5331505df217802f3acfc3a68acaa61e761de770c394210d28dd16be134c2eb1003e42d6ed1dc994e8ed8ec8ddad6538e1ad
data/README.md CHANGED
@@ -9,6 +9,53 @@ A set of tools for building reliable services of any complexity.
9
9
 
10
10
  See [servactory.com](https://servactory.com) for documentation.
11
11
 
12
+ ## Examples
13
+
14
+ ### Service
15
+
16
+ ```ruby
17
+ class UserService::Authenticate < ApplicationService::Base
18
+ input :email, type: String
19
+ input :password, type: String
20
+
21
+ output :user, type: User
22
+
23
+ private
24
+
25
+ def call
26
+ if (user = User.find_by(email: inputs.email)&.authenticate(inputs.password))
27
+ self.user = user
28
+ else
29
+ fail!(message: "Authentication failed")
30
+ end
31
+ end
32
+ end
33
+ ```
34
+
35
+ ### Using in controller
36
+
37
+ ```ruby
38
+ class SessionsController < ApplicationController
39
+ def create
40
+ service_result = UserService::Authenticate.call(**session_params)
41
+
42
+ if service_result.success?
43
+ session[:current_user_id] = service_result.user.id
44
+ redirect_to service_result.user
45
+ else
46
+ flash.now[:message] = service_result.errors.first.message
47
+ render :new
48
+ end
49
+ end
50
+
51
+ private
52
+
53
+ def session_params
54
+ params.require(:session).permit(:email, :password)
55
+ end
56
+ end
57
+ ```
58
+
12
59
  ## Contributing
13
60
 
14
61
  This project is intended to be a safe, welcoming space for collaboration. Contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct. We recommend reading the [contributing guide](./website/docs/CONTRIBUTING.md) as well.
@@ -6,6 +6,8 @@ module Servactory
6
6
  def call!(arguments = {}) # rubocop:disable Metrics/MethodLength, Metrics/AbcSize
7
7
  @context_store = Store.new(self)
8
8
 
9
+ context_store.context.send(:assign_service_strict_mode, true)
10
+
9
11
  assign_data_with(arguments)
10
12
 
11
13
  inputs_workbench.find_unnecessary!
@@ -31,6 +33,8 @@ module Servactory
31
33
  def call(arguments = {}) # rubocop:disable Metrics/MethodLength, Metrics/AbcSize
32
34
  @context_store = Store.new(self)
33
35
 
36
+ context_store.context.send(:assign_service_strict_mode, false)
37
+
34
38
  assign_data_with(arguments)
35
39
 
36
40
  inputs_workbench.find_unnecessary!
@@ -29,7 +29,17 @@ module Servactory
29
29
  end
30
30
 
31
31
  def fail!(message:, meta: nil)
32
- errors << Servactory.configuration.failure_class.new(message: message, meta: meta)
32
+ failure = Servactory.configuration.failure_class.new(message: message, meta: meta)
33
+
34
+ raise failure if @service_strict_mode
35
+
36
+ errors << failure
37
+ end
38
+
39
+ private
40
+
41
+ def assign_service_strict_mode(flag)
42
+ @service_strict_mode = flag
33
43
  end
34
44
  end
35
45
  end
@@ -16,9 +16,10 @@ module Servactory
16
16
 
17
17
  private
18
18
 
19
- def input(name, **options)
19
+ def input(name, *helpers, **options)
20
20
  collection_of_inputs << Input.new(
21
21
  name,
22
+ *helpers,
22
23
  **options
23
24
  )
24
25
  end
@@ -5,12 +5,21 @@ module Servactory
5
5
  class Input # rubocop:disable Metrics/ClassLength
6
6
  ARRAY_DEFAULT_VALUE = ->(is: false, message: nil) { { is: is, message: message } }
7
7
 
8
+ HELPER_LIBRARY = {
9
+ optional: { required: false },
10
+ internal: { internal: true },
11
+ as_array: { array: true }
12
+ }.freeze
13
+
14
+ private_constant :ARRAY_DEFAULT_VALUE, :HELPER_LIBRARY
15
+
8
16
  attr_reader :name,
9
17
  :internal_name
10
18
 
11
19
  # rubocop:disable Style/KeywordParametersOrder
12
20
  def initialize(
13
21
  name,
22
+ *helpers,
14
23
  as: nil,
15
24
  type:,
16
25
  **options
@@ -18,6 +27,8 @@ module Servactory
18
27
  @name = name
19
28
  @internal_name = as.present? ? as : name
20
29
 
30
+ options = apply_helpers_for_options(helpers: helpers, options: options) if helpers.present?
31
+
21
32
  add_basic_options_with(type: type, options: options)
22
33
 
23
34
  collection_of_options.each do |option|
@@ -28,6 +39,20 @@ module Servactory
28
39
  end
29
40
  # rubocop:enable Style/KeywordParametersOrder
30
41
 
42
+ def apply_helpers_for_options(helpers:, options:)
43
+ prepared_options = {}
44
+
45
+ helpers.each do |helper|
46
+ next unless HELPER_LIBRARY.key?(helper)
47
+
48
+ found_helper = HELPER_LIBRARY[helper]
49
+
50
+ prepared_options.merge!(found_helper)
51
+ end
52
+
53
+ options.merge(prepared_options)
54
+ end
55
+
31
56
  def add_basic_options_with(type:, options:)
32
57
  # Check Class: Servactory::Inputs::Validations::Required
33
58
  add_required_option_with(options)
@@ -63,7 +88,7 @@ module Servactory
63
88
  )
64
89
  ],
65
90
  define_input_conflicts: [
66
- DefineInputConflict.new(content: -> { return :required_vs_default if required? && default_value_present? })
91
+ DefineInputConflict.new(content: -> { :required_vs_default if required? && default_value_present? })
67
92
  ],
68
93
  need_for_checks: true,
69
94
  value_key: :is,
@@ -114,8 +139,8 @@ module Servactory
114
139
  )
115
140
  ],
116
141
  define_input_conflicts: [
117
- DefineInputConflict.new(content: -> { return :array_vs_array if array? && types.include?(Array) }),
118
- DefineInputConflict.new(content: -> { return :array_vs_inclusion if array? && inclusion_present? })
142
+ DefineInputConflict.new(content: -> { :array_vs_array if array? && types.include?(Array) }),
143
+ DefineInputConflict.new(content: -> { :array_vs_inclusion if array? && inclusion_present? })
119
144
  ],
120
145
  need_for_checks: false,
121
146
  value_key: :is,
@@ -94,7 +94,7 @@ module Servactory
94
94
  end
95
95
 
96
96
  def prepared_value
97
- @prepared_value ||= @input.optional? && !@input.default.nil? ? @input.default : @value
97
+ @prepared_value ||= @input.optional? && !@input.default.nil? && @value.blank? ? @input.default : @value
98
98
  end
99
99
  end
100
100
  end
@@ -31,6 +31,8 @@ module Servactory
31
31
  end
32
32
 
33
33
  def validate!
34
+ return unless should_be_checked?
35
+
34
36
  return if prepared_types.any? { |type| @value.is_a?(type) }
35
37
 
36
38
  raise_error_with(
@@ -44,6 +46,12 @@ module Servactory
44
46
 
45
47
  private
46
48
 
49
+ def should_be_checked?
50
+ @internal.required? || (
51
+ @internal.optional? && !@value.nil?
52
+ )
53
+ end
54
+
47
55
  def prepared_types
48
56
  @prepared_types ||=
49
57
  Array(@internal.types).map do |type|
@@ -31,6 +31,8 @@ module Servactory
31
31
  end
32
32
 
33
33
  def validate!
34
+ return unless should_be_checked?
35
+
34
36
  return if prepared_types.any? { |type| @value.is_a?(type) }
35
37
 
36
38
  raise_error_with(
@@ -44,6 +46,14 @@ module Servactory
44
46
 
45
47
  private
46
48
 
49
+ def should_be_checked?
50
+ @output.required? || (
51
+ @output.optional? && !@output.default.nil?
52
+ ) || (
53
+ @output.optional? && !@value.nil?
54
+ )
55
+ end
56
+
47
57
  def prepared_types
48
58
  @prepared_types ||=
49
59
  Array(@output.types).map do |type|
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Servactory
4
+ module Test
5
+ class FakeType; end
6
+ end
7
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Servactory
4
+ module Test
5
+ class Result
6
+ def initialize(**attributes)
7
+ attributes.each_pair do |method_name, method_return|
8
+ define_singleton_method(method_name) { method_return }
9
+ end
10
+ end
11
+ end
12
+ end
13
+ end
@@ -4,7 +4,7 @@ module Servactory
4
4
  module VERSION
5
5
  MAJOR = 1
6
6
  MINOR = 6
7
- PATCH = 5
7
+ PATCH = 7
8
8
 
9
9
  STRING = [MAJOR, MINOR, PATCH].join(".")
10
10
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: servactory
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.6.5
4
+ version: 1.6.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - Anton Sokolov
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-06-06 00:00:00.000000000 Z
11
+ date: 2023-06-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -247,6 +247,8 @@ files:
247
247
  - lib/servactory/outputs/validations/type.rb
248
248
  - lib/servactory/outputs/workbench.rb
249
249
  - lib/servactory/result.rb
250
+ - lib/servactory/test/fake_type.rb
251
+ - lib/servactory/test/result.rb
250
252
  - lib/servactory/utils.rb
251
253
  - lib/servactory/version.rb
252
254
  homepage: https://github.com/afuno/servactory