easy_monad 0.0.9 → 0.0.10

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: 78550feeca682ba33f20b7050071d3842eeccd847b3b319c90a86ec4bd429ebb
4
- data.tar.gz: dae5536d6035f67546136f12ffe1fc52d602bdffc8dd5eeba120fec2313c4cd7
3
+ metadata.gz: 6f1c4f41cf83d60e4fc8ce5cfb32fe96045049f1a30a93bdcc977c1dcfd2323b
4
+ data.tar.gz: faec7d0b656d2d0d4c82a2156788c791ca3432a1cd4c0b8b3639f237c2b58abc
5
5
  SHA512:
6
- metadata.gz: 4df38565173d60444699897fd5326c30464fd9bfa23de7c9025cce0ece5a8a9416ce68674a57dd534f3484dd7c1b2195285c8a6802660267f2cb97cec20294b1
7
- data.tar.gz: 8cf8d948c812075b068479e25737a0d43999831f2dea87a018d6d62fe8c1049d96bb27076f88173ed91d4bd4ae1939669d768402ee9e8ce8e5c215c14014d909
6
+ metadata.gz: 63f5ff5e17720c96320463956fd12f4b92d5017d8034280303537958db0ea05583320d5f5a89ea859fbc762d38e261fb741a2d494ddd57d3d7a3137bbe904815
7
+ data.tar.gz: 4f4b2e8e3ac21a33a092ddd949a0358b26a585f903f6a39383843658cc3c0974fc8db516907f993513c9ac9d381d8f7186421d28eaf1a3961c2799dfd2663a7c
@@ -0,0 +1,30 @@
1
+ module EasyMonad
2
+ class Configuration
3
+ class << self
4
+ attr_accessor :logger,
5
+ :using_modules,
6
+ :filter_parameters,
7
+ :rails_environment,
8
+ :configured
9
+
10
+ def set_defaults
11
+ require 'logger'
12
+
13
+ @logger = ::Logger.new(STDOUT)
14
+ @using_modules = [:params_sanitizer, :logging, :i18n]
15
+ @filter_parameters = %w[
16
+ password
17
+ password_confirmation
18
+ secret
19
+ password_salt
20
+ ]
21
+ end
22
+
23
+ def configure
24
+ yield self
25
+
26
+ @configured = true
27
+ end
28
+ end
29
+ end
30
+ end
data/lib/easy_monad.rb ADDED
@@ -0,0 +1,23 @@
1
+ require_relative 'configuration'
2
+
3
+ require_relative 'modules/params_sanitizer'
4
+ require_relative 'modules/i18n'
5
+ require_relative 'modules/logging'
6
+
7
+ require_relative 'operation'
8
+ require_relative 'errors'
9
+
10
+ module EasyMonad
11
+ def self.str_to_const(str)
12
+ eval(str.split('_').map(&:capitalize).unshift('Modules::').join)
13
+ end
14
+
15
+ Configuration.rails_environment = !!defined?(Rails)
16
+ Configuration.set_defaults unless Configuration.configured
17
+
18
+ Configuration.using_modules.each do |mod|
19
+ raise ArgumentError, 'Included Module must be a Symbol!' unless mod.is_a?(Symbol)
20
+
21
+ Operation.include str_to_const(mod.to_s)
22
+ end
23
+ end
data/lib/errors.rb ADDED
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ module EasyMonad
4
+ class Errors < Hash
5
+ def add(key, value)
6
+ self[key] ||= value
7
+ end
8
+
9
+ def to_a
10
+ map { |key, val| "#{key}: #{val}" }
11
+ end
12
+
13
+ def to_s
14
+ to_a.join(', ')
15
+ end
16
+
17
+ def only_messages
18
+ values.flatten.map { _1.delete(':') }
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ module EasyMonad
4
+ module Modules
5
+ module I18n
6
+ def desc(error)
7
+ ::I18n.t("operations.#{self.class.name.underscore.gsub('/', '.')}.#{error}")
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,62 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'params_sanitizer'
4
+
5
+ module EasyMonad
6
+ module Modules
7
+ module Logging
8
+ def self.included(base)
9
+ base.singleton_class.prepend(ClassMethods)
10
+ end
11
+
12
+ module ClassMethods
13
+ def call(*, **)
14
+ operation = new(*, **)
15
+
16
+ operation.within_early_exit_block do
17
+ operation.memoize_start_time
18
+ operation.log_start(operation)
19
+ operation.call
20
+ operation.log_end(operation)
21
+
22
+ operation
23
+ end
24
+ end
25
+ end
26
+
27
+ def log_start(operation)
28
+ logger.info "Operation #{operation.class.name} starts params: #{operation.params_for_logging(operation.params)}"
29
+ end
30
+
31
+ def log_end(operation)
32
+ logger.info "Operation #{operation.class.name} ends. Took: #{duration_from_start_in_secs} sec, params: #{operation.params_for_logging(operation.params)}"
33
+ end
34
+
35
+ def log_critical_error(operation)
36
+ logger.error "Operation #{operation.class.name} ends with error. Took: #{duration_from_start_in_secs} sec, params: #{operation.params_for_logging(operation.params)}, errors: #{operation.errors.to_a}"
37
+ end
38
+
39
+ def log_error(operation)
40
+ logger.error "Operation #{operation.class.name} has errors: #{operation.errors.to_a} params: #{operation.params_for_logging(operation.params)}"
41
+ end
42
+
43
+ def memoize_start_time
44
+ @start_time = cpu_clock_now
45
+ end
46
+
47
+ private
48
+
49
+ def duration_from_start_in_secs
50
+ (cpu_clock_now - @start_time).floor(2)
51
+ end
52
+
53
+ def logger
54
+ @logger ||= Configuration.logger
55
+ end
56
+
57
+ def cpu_clock_now
58
+ Process.clock_gettime(Process::CLOCK_MONOTONIC)
59
+ end
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ module EasyMonad
4
+ module Modules
5
+ module ParamsSanitizer
6
+ def params_for_logging(params)
7
+ regex = /(#{filter_parameters.join('|')})":"([^"]*)"/
8
+ hashed_params(params).inspect.gsub(regex, '\1":"[FILTERED]"')
9
+ end
10
+
11
+ private
12
+
13
+ def hashed_params(params)
14
+ if Configuration.rails_environment
15
+ params.is_a?(ActionController::Parameters) ? params.to_unsafe_h : params.to_h
16
+ else
17
+ params.to_h
18
+ end
19
+ end
20
+
21
+ def filter_parameters
22
+ if Configuration.rails_environment
23
+ Rails.configuration.filter_parameters += Configuration.filter_parameters
24
+ else
25
+ Configuration.filter_parameters
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
data/lib/operation.rb ADDED
@@ -0,0 +1,95 @@
1
+ # frozen_string_literal: true
2
+
3
+ module EasyMonad
4
+ class Operation
5
+ attr_reader :params
6
+ attr_accessor :result, :errors
7
+
8
+ def initialize(params, errors = Errors.new)
9
+ @params = params
10
+ @errors = errors
11
+ end
12
+
13
+ class << self
14
+ def call(*, **)
15
+ operation = new(*, **)
16
+
17
+ operation.within_early_exit_block do
18
+ operation.call
19
+
20
+ operation
21
+ end
22
+ end
23
+
24
+ alias [] call
25
+ end
26
+
27
+ def result!
28
+ return result if success?
29
+
30
+ raise ProcessError, self
31
+ end
32
+
33
+ def failure?
34
+ errors.any?
35
+ end
36
+
37
+ def success?
38
+ errors.empty?
39
+ end
40
+
41
+ def within_early_exit_block(&)
42
+ catch(:critical, &)
43
+ end
44
+
45
+ def call
46
+ raise NotImplementedError, "You must implement #call by yourself!"
47
+ end
48
+
49
+ protected
50
+
51
+ def join(other)
52
+ other.errors.each do |error, description|
53
+ error(error, description)
54
+ end
55
+
56
+ other
57
+ end
58
+
59
+ def strict_join!(other)
60
+ other.errors.each do |error, description|
61
+ critical_error!(error, description)
62
+ end
63
+
64
+ other
65
+ end
66
+
67
+ # stubs for Logging and ParamsSanitizer mudules
68
+ def log_error(_) = nil
69
+ def log_critical_error(_) = nil
70
+ def params_for_logging(params) = params
71
+
72
+ private
73
+
74
+ def error(error, description = nil)
75
+ errors.add(error, description || 'Something went wrong')
76
+ log_error(self)
77
+ end
78
+
79
+ def critical_error!(error, description = nil)
80
+ errors.add(error, description || 'Something went wrong')
81
+ log_critical_error(self)
82
+ throw(:critical, self)
83
+ end
84
+ end
85
+
86
+ class ProcessError < StandardError
87
+ attr_reader :operation, :message
88
+
89
+ def initialize(operation)
90
+ super
91
+ @operation = operation
92
+ @message = "#{operation.class} Process Error"
93
+ end
94
+ end
95
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: easy_monad
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.9
4
+ version: 0.0.10
5
5
  platform: ruby
6
6
  authors:
7
7
  - T.Zhuk
@@ -15,7 +15,14 @@ email:
15
15
  executables: []
16
16
  extensions: []
17
17
  extra_rdoc_files: []
18
- files: []
18
+ files:
19
+ - lib/configuration.rb
20
+ - lib/easy_monad.rb
21
+ - lib/errors.rb
22
+ - lib/modules/i18n.rb
23
+ - lib/modules/logging.rb
24
+ - lib/modules/params_sanitizer.rb
25
+ - lib/operation.rb
19
26
  licenses:
20
27
  - MIT
21
28
  metadata: