checkability 0.4.1 → 0.7.0

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
- 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: []