checkability 0.4.1 → 0.7.0

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
- SHA1:
3
- metadata.gz: ae846f196e0b6d2648429f824e02205b9a3fe04d
4
- data.tar.gz: 10156c70279d72817146d19fceaef9cbba3f116d
2
+ SHA256:
3
+ metadata.gz: d691bd54ab262dd07d0bdf1120d632a71003cfdc730002275d10333e21045526
4
+ data.tar.gz: 104e1558d7867413f25e838d3db9aaf54d2a7f96b412dd1121149e9528c9f95d
5
5
  SHA512:
6
- metadata.gz: 990b1575b7ebfb0e667aa1ab2e6a0601e3388ea1b2ecd7f4808d843d1341085f454477804fa8f0edeb743fd2508fdb16d2b7a9eb2d8451a20a212791f67f411d
7
- data.tar.gz: 445c267c33c75d63188d6ec04767409afed7734292a369e880d8e1d1cc03b5b8a9af80339b076968d60816ec9834901ab9ed6a7299606b9d3fe496276e869af3
6
+ metadata.gz: 42816cf5985cfcc1d0f680496f0fdde3fd3263f87a4b12010f9d3f33694481703c8ed3785531914cfd5143982001c6fbe2977a52de789d7c559720048d3657ec
7
+ data.tar.gz: 00e84b4caa4c5fae3eea6ae4e7e1fb0c3550e29948c81df7a85aaf4ea8ae98bf1083e3559b1583d28243faecdd477ebdbb8b7eab33318cd6571f15b5a08b52a0
data/Rakefile CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'bundler/setup'
2
4
 
3
5
  require 'bundler/gem_tasks'
data/bin/checkability CHANGED
@@ -1,4 +1,5 @@
1
1
  #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
2
3
 
3
4
  require_relative '../lib/checkability'
4
5
 
data/lib/checkability.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'active_record'
2
4
  require 'active_support'
3
5
  require_relative 'checkability/version'
@@ -7,5 +9,7 @@ require_relative 'checkability/external_api_checker'
7
9
  require_relative 'checkability/external_api_connector'
8
10
  require_relative 'checkability/validator'
9
11
  require_relative 'checkability/acts_as_checkable'
12
+ require_relative 'checkability/checker'
13
+ require_relative 'checkability/abstract_checker'
10
14
 
11
15
  ActiveRecord::Base.include Checkability::ActsAsCheckable
@@ -0,0 +1,66 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'checker'
4
+
5
+ module Checkability
6
+ # @abstract
7
+ class AbstractChecker < Checker
8
+ # @return [Handler]
9
+ attr_reader :stop_process_on_failure, :stop_process_on_success
10
+ attr_accessor :success_message, :failure_message, :handler
11
+
12
+ def initialize(opts = {})
13
+ @stop_process_on_failure = opts[:stop_process_on_failure] || false
14
+ @stop_process_on_success = opts[:stop_process_on_success] || false
15
+ @success_message = opts[:success_message] || 'Success.'
16
+ @failure_message = opts[:failure_message] || 'Failed.'
17
+
18
+ @next_handler = nil
19
+ post_initialize(opts) # implemented in subclass
20
+ end
21
+
22
+ # @param [Handler] handler
23
+ #
24
+ # @return [Handler]
25
+ def next_handler(handler)
26
+ @handler = handler if handler
27
+
28
+ handler
29
+ end
30
+
31
+ # @abstract
32
+ #
33
+ # @param [String] request
34
+ #
35
+ # @return [Boolean, nil]
36
+ def handle(request)
37
+ check = check_value(request) # imlemented in subclass
38
+
39
+ return true if check && stop_process_on_success
40
+
41
+ return false if !check && stop_process_on_failure
42
+
43
+ handler&.handle(request)
44
+ end
45
+
46
+ def check_value(checkable)
47
+ result, message = result_and_message(checkable)
48
+ checkable.messages << message
49
+ result
50
+ end
51
+
52
+ def result_and_message(checkable)
53
+ result = _result(checkable)
54
+ str = result ? success_message : failure_message
55
+ [result, message(str, result)]
56
+ rescue StandardError => e
57
+ [false, message(e, false)]
58
+ end
59
+
60
+ def _result; end
61
+
62
+ def message(str, res)
63
+ "#{res}::#{str}"
64
+ end
65
+ end
66
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Checkability
2
4
  # Adding class and instance methods
3
5
  #
@@ -11,7 +13,8 @@ module Checkability
11
13
  class_methods do
12
14
  def acts_as_checkable(options = {})
13
15
  if !options.is_a?(Hash) && !options.empty?
14
- raise ArgumentError, "Hash expected, got #{options.class.name}"
16
+ raise ArgumentError,
17
+ "Hash expected, got #{options.class.name}"
15
18
  end
16
19
 
17
20
  class_attribute :checkable_conf
@@ -23,24 +26,26 @@ module Checkability
23
26
  attr_accessor :allowed, :messages
24
27
 
25
28
  def perform_check
26
- _setup
27
- self.allowed = _check
28
- messages << "'#{value}' is #{_allowness}. "
29
+ self.allowed = nil
30
+ self.messages = []
31
+ self.allowed = Checkability::Checkable.new(self).check(checkable_conf)
32
+ messages << "#{allowed}::'#{_value}' is #{_allowness}. "
29
33
  end
30
34
 
31
35
  private
32
36
 
33
- def _setup
34
- self.allowed = nil
35
- self.messages = []
37
+ def _value
38
+ send(_attr_name)
36
39
  end
37
40
 
38
- def _allowness
39
- allowed ? 'ALLOWED' : 'NOT allowed'
41
+ def _attr_name
42
+ checkable_conf[:attr_name] || :value
40
43
  end
41
44
 
42
- def _check
43
- Checkability::Checkable.new(self).check(checkable_conf)
45
+ def _setup; end
46
+
47
+ def _allowness
48
+ allowed ? 'ALLOWED' : 'NOT allowed'
44
49
  end
45
50
  end
46
51
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Checkability
2
4
  # Implements check method to Iterate on chechers
3
5
  # Possible to implemet as Iterator in future
@@ -7,32 +9,47 @@ module Checkability
7
9
 
8
10
  def initialize(checkable)
9
11
  @checkable = checkable
12
+ @checkable.messages = []
10
13
  end
11
14
 
12
- # sentence is a proc
13
- # like { |a,b,c| a && ( b || c ) }
14
- # where a,b,c are checkers
15
- # and each should return true|false
16
- # checkers is an array of checker objects
17
- # e.g. [storage_checker, external_api_checker]
18
- def check(opts = {})
19
- results = []
20
- opts[:checker_confs].each do |checker_conf|
21
- results << (res = _checker_to_check_value(checker_conf))
22
- break if res && checker_conf[:stop_process_if_success]
23
- break if res == false && checker_conf[:stop_process_if_failure]
24
- end
25
- opts[:strategy].call(results)
15
+ # As in result handlers should behave like this:
16
+ # validator .set_next(storage)
17
+ # storage .set_next(api_validator)
18
+ # api_validator.set_next(api_finder)
19
+ # api_validator.set_next(nil)
20
+ #
21
+ # validator.handle(request)
22
+ #
23
+ def check(opts)
24
+ handler_confs = opts[:handler_confs]
25
+ first_handler_name = opts[:first_handler]
26
+ first_handler = _handlers(handler_confs)[first_handler_name]
27
+
28
+ first_handler.handle(checkable)
29
+ # rescue StandardError => e
30
+ # checkable.messages << "false::#{e}: #{opts}."
31
+ # false
26
32
  end
27
33
 
28
34
  private
29
35
 
30
- def _checker_to_check_value(checker_conf)
31
- k = "Checkability::#{checker_conf[:name].to_s.camelize}".constantize
32
- k.new(checker_conf).check_value(checkable)
33
- rescue NameError => e
34
- checkable.messages << "#{e}: #{checker_conf[:name]}."
35
- false
36
+ def _handlers(handler_confs)
37
+ handlers = _make_handlers(handler_confs)
38
+ handlers.each do |handler_name, handler|
39
+ next_handler_name = handler_confs[handler_name][:next_handler]
40
+ handler.next_handler(handlers[next_handler_name]) if handlers[next_handler_name]
41
+ end
42
+ end
43
+
44
+ def _make_handlers(handler_confs)
45
+ handler_confs.transform_values do |handler_conf|
46
+ _make_handler(handler_conf)
47
+ end
48
+ end
49
+
50
+ def _make_handler(conf)
51
+ k = Checkability.const_get conf[:name].to_s.camelize
52
+ k.new(conf)
36
53
  end
37
54
  end
38
55
  end
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Checkability
4
+ # @abstract
5
+ class Checker
6
+ # @abstract
7
+ #
8
+ # @param [Handler] handler
9
+ def next_handler=(_handler)
10
+ raise NotImplementedError, "#{self.class} has not implemented method '#{__method__}'"
11
+ end
12
+
13
+ # @abstract
14
+ #
15
+ # @param [String] request
16
+ #
17
+ # @return [String, nil]
18
+ def handle(_handler)
19
+ raise NotImplementedError, "#{self.class} has not implemented method '#{__method__}'"
20
+ end
21
+
22
+ # @abstract
23
+ #
24
+ # @param [String] request
25
+ #
26
+ # @return [Boolean, true|false]
27
+ def check_value(_request)
28
+ raise NotImplementedError, "#{self.class} has not implemented method '#{__method__}'"
29
+ end
30
+
31
+ # @abstract
32
+ #
33
+ # @param [String] request
34
+ #
35
+ # @return [Boolean, true|false]
36
+ def result_and_message(_object)
37
+ raise NotImplementedError, "#{self.class} has not implemented method '#{__method__}'"
38
+ end
39
+ end
40
+ end
@@ -1,52 +1,45 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'faraday'
2
4
  require 'net/http'
3
5
  require 'net/https'
4
6
  require 'json'
5
7
 
8
+ # frozen_string_literal: true
9
+
6
10
  module Checkability
7
11
  # Checks if postcode exists in external API
8
12
  #
9
- class ExternalApiChecker
13
+ class ExternalApiChecker < AbstractChecker
10
14
  attr_reader :path, :path_suffix, :check_method, :connection, :http_verb,
11
15
  :failure_message, :success_message
12
16
 
13
- def initialize(conf = {})
17
+ def post_initialize(conf = {})
14
18
  @path = conf[:path]
15
19
  @http_verb = conf[:http_verb] || :get
16
20
  @path_suffix = conf[:path_suffix] || ''
17
21
  @check_method = conf[:check_method]
18
- @failure_message = conf[:failure_message] || 'Failed.'
19
- @success_message = conf[:success_message] || 'Success.'
20
22
  @connection = Checkability::ExternalApiConnector.new(conf)
21
23
  end
22
24
 
23
- def check_value(checkable)
24
- @resp = connection.connect.send(http_verb,
25
- checkable.value.delete(' ') + path_suffix)
26
- result, message = _result_and_message
27
- checkable.messages << message
28
- result
29
- end
30
-
31
25
  private
32
26
 
33
- def _message(str)
34
- "#{path}: #{str}"
35
- end
27
+ def _result(checkable)
28
+ resp = connection
29
+ .connect
30
+ .send(http_verb, "#{checkable.value.delete(' ')}#{path_suffix}")
31
+ return false unless resp.status == 200
36
32
 
37
- def _parsed(resp)
38
- JSON.parse(resp.body)
33
+ check_method.call(_parsed(resp))
39
34
  end
40
35
 
41
- def _result_and_message
42
- return [false, _message(@resp.status)] unless @resp.status == 200
43
-
44
- return [true, _message(success_message)] if check_method
45
- .call(_parsed(@resp))
36
+ def message(str, res)
37
+ str = "#{path}: #{str}"
38
+ super(str, res)
39
+ end
46
40
 
47
- [false, _message(failure_message)]
48
- rescue StandardError => e
49
- [false, _message(e)]
41
+ def _parsed(resp)
42
+ JSON.parse(resp.body)
50
43
  end
51
44
  end
52
45
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Checkability
2
4
  # Create connection
3
5
  #
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Checkability
2
4
  class Railtie < ::Rails::Railtie
3
5
  end
@@ -1,29 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'abstract_checker'
1
4
  module Checkability
2
5
  # Checks if postcode exists in Storage
3
6
  #
4
- class StorageChecker
5
- attr_reader :storage_class
7
+ class StorageChecker < AbstractChecker
8
+ attr_reader :storage_class, :attr_name
6
9
 
7
- def initialize(conf = {})
10
+ def post_initialize(conf = {})
8
11
  @storage_class = conf[:storage_class]
12
+ @attr_name = conf[:attr_name] || :value
9
13
  end
10
14
 
11
- def check_value(checkable)
12
- value = checkable.value.upcase
13
- result = _present_in_storage(value)
14
- checkable.messages << (result ? _message('Found') : _message('Not found'))
15
- result
15
+ private
16
+
17
+ def _result(checkable)
18
+ value = _normalize_value(checkable.send(attr_name))
19
+ storage_class.where(attr_name => value).present?
16
20
  end
17
21
 
18
- def _present_in_storage(value)
19
- storage_class.where(value: value)
20
- .or(storage_class.where(value: value.strip))
21
- .or(storage_class.where(value: value.delete(' ')))
22
- .present?
22
+ def message(str, res)
23
+ str = "Allowed #{storage_class}s list: #{str}"
24
+ super(str, res)
23
25
  end
24
26
 
25
- def _message(str)
26
- "Allowed #{storage_class}s list: #{str}."
27
+ def _normalize_value(value)
28
+ value.delete(' ').upcase
27
29
  end
28
30
  end
29
31
  end
@@ -1,27 +1,19 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Checkability
2
4
  # Checks if postcode comply with regex
3
5
  #
4
- class Validator
6
+ class Validator < AbstractChecker
5
7
  attr_reader :format
6
8
 
7
- def initialize(conf = {})
9
+ def post_initialize(conf = {})
8
10
  @format = conf[:format]
9
11
  end
10
12
 
11
- def check_value(checkable)
12
- result, message = _result_and_message(checkable)
13
- checkable.messages << message
14
- result
15
- end
16
-
17
13
  private
18
14
 
19
- def _result_and_message(checkable)
20
- if (checkable.value.delete(' ') =~ format[:regex]).nil?
21
- [false, "Value is NOT COMPLY with format of #{format[:name]}."]
22
- else
23
- [true, "Value is COMPLY with format of #{format[:name]}."]
24
- end
15
+ def _result(checkable)
16
+ !(checkable.value.delete(' ') =~ format[:regex]).nil?
25
17
  end
26
18
  end
27
19
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Checkability
2
- VERSION = '0.4.1'.freeze
4
+ VERSION = '0.7.0'
3
5
  end
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  # desc "Explaining what the task does"
2
3
  # task :checkability do
3
4
  # # Task goes here
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: checkability
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.1
4
+ version: 0.7.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andrey Eremeev
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-04-01 00:00:00.000000000 Z
11
+ date: 2021-04-03 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: Provide Checkers functionality.
14
14
  email:
@@ -23,8 +23,10 @@ files:
23
23
  - Rakefile
24
24
  - bin/checkability
25
25
  - lib/checkability.rb
26
+ - lib/checkability/abstract_checker.rb
26
27
  - lib/checkability/acts_as_checkable.rb
27
28
  - lib/checkability/checkable.rb
29
+ - lib/checkability/checker.rb
28
30
  - lib/checkability/external_api_checker.rb
29
31
  - lib/checkability/external_api_connector.rb
30
32
  - lib/checkability/railtie.rb
@@ -40,7 +42,7 @@ metadata:
40
42
  homepage_uri: https://github.com/azazelo/checkability
41
43
  source_code_uri: https://rubygems.org
42
44
  changelog_uri: https://rubygems.org
43
- post_install_message:
45
+ post_install_message:
44
46
  rdoc_options: []
45
47
  require_paths:
46
48
  - lib
@@ -48,16 +50,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
48
50
  requirements:
49
51
  - - ">="
50
52
  - !ruby/object:Gem::Version
51
- version: '0'
53
+ version: 2.6.2
52
54
  required_rubygems_version: !ruby/object:Gem::Requirement
53
55
  requirements:
54
56
  - - ">="
55
57
  - !ruby/object:Gem::Version
56
58
  version: '0'
57
59
  requirements: []
58
- rubyforge_project:
59
- rubygems_version: 2.4.6
60
- signing_key:
60
+ rubygems_version: 3.0.3
61
+ signing_key:
61
62
  specification_version: 4
62
63
  summary: Provide Checkers functionality.
63
64
  test_files: []