checkability 0.6.0 → 1.0.1

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: 0f584d475c0bf9395f3cbdb0d47a436b7f1a56ab93fb4d76095b58de9a0a4485
4
- data.tar.gz: d9ff4ef5b3a877fd0a8efe830958df8e14d3ae0e221903fbb436623457c14e74
3
+ metadata.gz: 49569c239e2acdb43486cf8269a923d3118424798700e49be0edfaf7f7551b25
4
+ data.tar.gz: 7a81f73bc65865564495bd5d8b9680d76249fa69b3d730543162ebd5b1f61048
5
5
  SHA512:
6
- metadata.gz: e7f9740350a632cea6131709f9e765f0c8e47981b564a8fb426103fe1c55688f7d27ce7190b11278e540807bd0e2dfeabe65d5d47d4e494b4865074db384447d
7
- data.tar.gz: 4baa39ca9c3aaec3845e2d84a72f38caf74f662bab1b3f6ff453439763393db4865c7a3912b8c09f606d37a2b15860f779750f9d8cc0e8b19f102362310355d5
6
+ metadata.gz: d28be27a0487566262cf3d284213b076f1c7dbc9bfc2f59844444fa16761842c9348dd9df609420488bc8d597a3b50741a7bb712de86ab2056afb565399dc07b
7
+ data.tar.gz: ad42af8d0f399d130c2282d4c2938230f87c9f01e70fd43df3f031303aeca8767335a5e0fabe281b58edb1d081c5500a10a83d94e7befda7f461f4770bbf9c0c
data/README.md CHANGED
@@ -12,12 +12,12 @@ How to use my plugin.
12
12
  inside of any rails model do
13
13
  ```ruby
14
14
  class SomeModel
15
- acts_as_checkable strategy: proc { |a, b, c| a && (b || c) },
16
- checkers: uk_postcode_checkers
15
+ extend UKPostcodeCheckersConf
16
+ acts_as_checkable uk_postcode_checkers_conf
17
17
  end
18
18
  ```
19
19
  where `uk_postcode_checkers` is method which returns hash with configurations
20
- https://github.com/azazelo/postcode_checker/blob/master/app/models/concerns/u_k_postcode_checkers.rb
20
+ https://github.com/azazelo/postcode_checker/blob/master/app/models/concerns/u_k_postcode_checkers_conf.rb
21
21
  then in your controller:
22
22
  ```ruby
23
23
  class ChecksController < ApplicationController
@@ -30,7 +30,7 @@ class ChecksController < ApplicationController
30
30
  message, alert_class =
31
31
  if @check.valid?
32
32
  @check.perform_check
33
- [@check.messages.join('<br/>'), _alert_class(@check.allowed)]
33
+ [@check.ch_messages.join('<br/>'), _alert_class(@check.ch_allowed)]
34
34
  else
35
35
  [@check.errors.full_messages.join('<br/>'), _alert_class(false)]
36
36
  end
data/lib/checkability.rb CHANGED
@@ -9,7 +9,6 @@ require_relative 'checkability/external_api_checker'
9
9
  require_relative 'checkability/external_api_connector'
10
10
  require_relative 'checkability/validator'
11
11
  require_relative 'checkability/acts_as_checkable'
12
- require_relative 'checkability/chain_of_resp/handler'
13
- require_relative 'checkability/chain_of_resp/abstract_handler'
12
+ require_relative 'checkability/base_checker'
14
13
 
15
14
  ActiveRecord::Base.include Checkability::ActsAsCheckable
@@ -12,20 +12,28 @@ module Checkability
12
12
 
13
13
  class_methods do
14
14
  def acts_as_checkable(options = {})
15
- raise ArgumentError, "Hash expected, got #{options.class.name}" if !options.is_a?(Hash) && !options.empty?
15
+ if !options.is_a?(Hash) && !options.empty?
16
+ raise ArgumentError,
17
+ "Hash expected, got #{options.class.name}"
18
+ end
16
19
 
17
- class_attribute :checkable_conf
20
+ class_attribute :ch_conf
18
21
 
19
- self.checkable_conf = options
22
+ self.ch_conf = options
20
23
  end
21
24
  end
22
25
 
23
- attr_accessor :allowed, :messages
26
+ attr_accessor :ch_allowed, :ch_messages
27
+
28
+ def initialize(params)
29
+ @ch_messages = []
30
+ @ch_allowed = nil
31
+ super(params)
32
+ end
24
33
 
25
34
  def perform_check
26
- _setup
27
- self.allowed = Checkability::Checkable.new(self).check(checkable_conf)
28
- messages << "#{allowed}::'#{_value}' is #{_allowness}. "
35
+ Checkability::Checkable.new(self).check(ch_conf)
36
+ ch_messages << "#{ch_allowed}::'#{_value}' is #{_allowness}. "
29
37
  end
30
38
 
31
39
  private
@@ -35,16 +43,11 @@ module Checkability
35
43
  end
36
44
 
37
45
  def _attr_name
38
- checkable_conf[:attr_name] || :value
39
- end
40
-
41
- def _setup
42
- self.allowed = nil
43
- self.messages = []
46
+ ch_conf[:attr_name] || :value
44
47
  end
45
48
 
46
49
  def _allowness
47
- allowed ? 'ALLOWED' : 'NOT allowed'
50
+ ch_allowed ? 'ALLOWED' : 'NOT allowed'
48
51
  end
49
52
  end
50
53
  end
@@ -0,0 +1,76 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'checker'
4
+
5
+ module Checkability
6
+ # @abstract
7
+ class BaseChecker < Checker
8
+ # @return [Handler]
9
+ attr_reader :stop_process_on_success, :stop_process_on_failure,
10
+ :success_message, :failure_message
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
+ # subclass should implement
23
+ def post_initialize(_opts)
24
+ nil
25
+ end
26
+
27
+ # @param [Handler] handler
28
+ #
29
+ # @return [Handler]
30
+ def next_handler(handler)
31
+ @next_handler = handler
32
+
33
+ handler
34
+ end
35
+
36
+ # @abstract
37
+ #
38
+ # @param [String] request
39
+ #
40
+ # @return [Boolean, nil]
41
+ def handle(check_obj)
42
+ res, mess = result_and_message(check_obj)
43
+ check_obj.ch_messages << mess
44
+ check_obj.ch_allowed = res
45
+
46
+ return if _stop_here?(res)
47
+
48
+ @next_handler&.handle(check_obj) if @next_handler
49
+ end
50
+
51
+ def result_and_message(check_obj = nil)
52
+ res = result(check_obj)
53
+
54
+ str = res ? success_message : failure_message
55
+ [res, message(res, str)]
56
+ # rescue StandardError => e
57
+ # [false, message(false, e)]
58
+ end
59
+
60
+ # subclass should implement
61
+ def result(_check_obj)
62
+ raise NotImplementedError, "#{self.class} has not implemented method '#{__method__}'"
63
+ end
64
+
65
+ # subclass may override
66
+ def message(res, str)
67
+ "#{res}::#{str}"
68
+ end
69
+
70
+ private
71
+
72
+ def _stop_here?(res)
73
+ (res && stop_process_on_success) || (!res && stop_process_on_failure)
74
+ end
75
+ end
76
+ end
@@ -1,51 +1,59 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'forwardable'
4
+
3
5
  module Checkability
4
6
  # Implements check method to Iterate on chechers
5
7
  # Possible to implemet as Iterator in future
6
8
  #
7
9
  class Checkable
8
- attr_reader :checkable
10
+ attr_accessor :check_obj
11
+
12
+ extend Forwardable
13
+ def_delegators :@check_obj, :ch_messages, :ch_allowed
9
14
 
10
- def initialize(checkable)
11
- @checkable = checkable
12
- @checkable.messages = []
15
+ def initialize(check_obj)
16
+ @check_obj = check_obj
13
17
  end
14
18
 
15
19
  # 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
+ # validator .next_handler(storage)
21
+ # storage .next_handler(api_validator)
22
+ # api_validator.next_handler(api_finder)
23
+ # api_validator.next_handler(nil)
20
24
  #
21
25
  # validator.handle(request)
22
26
  #
23
- def check(opts = {})
24
- require 'pry'; binding.pry
25
- first_handler_name = opts[:first_handler]
26
- _handlers(opts)[first_handler_name].handle(checkable)
27
+ # ChainOfResponsibilty
28
+ #
29
+ def check(handler_confs)
30
+ first_handler_name = handler_confs.keys.first
31
+ first_handler = _handlers(handler_confs)[first_handler_name]
32
+
33
+ first_handler.handle(check_obj)
27
34
  rescue StandardError => e
28
- checkable.messages << "false::#{e}: #{opts}."
35
+ check_obj.ch_messages << "false::#{e}: #{handler_confs}."
29
36
  false
30
37
  end
31
38
 
32
39
  private
33
40
 
34
- def _handlers(opts)
35
- handler_confs = opts[:handler_confs]
36
- handlers = {}
37
- handler_confs.each do |handler_name, handler_conf|
38
- handlers[handler_name] = _make_handler(handler_name, handler_conf)
39
- end
40
- handlers.each do |handler_name, handler|
41
- next_handler_name = handler_confs[handler_name][:next_handler]
42
- handler.next_handler(handlers[next_handler_name])
41
+ def _handlers(handler_confs)
42
+ handlers = _make_handlers(handler_confs)
43
+ handlers.each_value.with_index do |handler, i|
44
+ next_handler_name = handlers.keys[i + 1]
45
+ handler.next_handler(handlers[next_handler_name]) if handlers[next_handler_name]
43
46
  end
47
+ handlers
48
+ end
49
+
50
+ def _make_handlers(confs)
51
+ confs.transform_values { |conf| _make_handler(conf) }
44
52
  end
45
53
 
46
- def _make_handler(_name, conf)
47
- k = Checkability.const_get conf[:name].to_s.camelize
48
- k.new(conf)
54
+ def _make_handler(conf)
55
+ Checkability.const_get(conf[:name].to_s.camelize)
56
+ .new(conf)
49
57
  end
50
58
  end
51
59
  end
@@ -0,0 +1,59 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Checkability
4
+ # @abstract
5
+ class Checker
6
+ # hook method to initialize concreet attributes
7
+ # @abstract
8
+ #
9
+ # @param [Hash]
10
+ #
11
+ # @return new object
12
+ def post_initialize(_opts)
13
+ raise NotImplementedError, "#{self.class} has not implemented method '#{__method__}'"
14
+ end
15
+
16
+ # @abstract
17
+ #
18
+ # @param [Handler] handler
19
+ def next_handler=(_handler)
20
+ raise NotImplementedError, "#{self.class} has not implemented method '#{__method__}'"
21
+ end
22
+
23
+ # @abstract
24
+ #
25
+ # @param [String] request
26
+ #
27
+ # @return [String, nil]
28
+ def handle(_handler)
29
+ raise NotImplementedError, "#{self.class} has not implemented method '#{__method__}'"
30
+ end
31
+
32
+ # @abstract
33
+ #
34
+ # @param [String] request
35
+ #
36
+ # @return Array [ [Boolean, true|false], String, message] ]
37
+ def result_and_message(_object)
38
+ raise NotImplementedError, "#{self.class} has not implemented method '#{__method__}'"
39
+ end
40
+
41
+ # @abstract
42
+ #
43
+ # @param [Checkable object] request
44
+ #
45
+ # @return [Boolean, true|false]
46
+ def result(_object)
47
+ raise NotImplementedError, "#{self.class} has not implemented method '#{__method__}'"
48
+ end
49
+
50
+ # @abstract
51
+ #
52
+ # @params [Boolean], [String]
53
+ #
54
+ # @return [String]
55
+ def message(_res, _str)
56
+ raise NotImplementedError, "#{self.class} has not implemented method '#{__method__}'"
57
+ end
58
+ end
59
+ end
@@ -1,58 +1,47 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'faraday'
4
- require 'net/http'
5
- require 'net/https'
6
- require 'json'
3
+ require 'forwardable'
7
4
 
8
- # frozen_string_literal: true
9
-
10
- require_relative 'chain_of_resp/abstract_handler'
11
5
  module Checkability
12
6
  # Checks if postcode exists in external API
13
7
  #
14
- class ExternalApiChecker < ChainOfResp::AbstractHandler
15
- attr_reader :path, :path_suffix, :check_method, :connection, :http_verb,
16
- :failure_message, :success_message
8
+ class ExternalApiChecker < BaseChecker
9
+ attr_reader :path, :path_suffix, :check_method, :connector, :http_verb
10
+
11
+ extend Forwardable
12
+ def_delegators :@connector, :connection
17
13
 
18
14
  def post_initialize(conf = {})
19
15
  @path = conf[:path]
20
16
  @http_verb = conf[:http_verb] || :get
21
17
  @path_suffix = conf[:path_suffix] || ''
22
18
  @check_method = conf[:check_method]
23
- @failure_message = conf[:failure_message] || 'Failed.'
24
- @success_message = conf[:success_message] || 'Success.'
25
- @connection = Checkability::ExternalApiConnector.new(conf)
19
+ @connector = conf[:connector] ||
20
+ Checkability::ExternalApiConnector.new(conf[:path])
21
+ @resp = nil
26
22
  end
27
23
 
28
- def check_value(checkable)
29
- @resp = connection
30
- .connect
31
- .send(http_verb, "#{checkable.value.delete(' ')}#{path_suffix}")
32
- result, message = _result_and_message
33
- checkable.messages << message
34
- result
24
+ def result(check_obj)
25
+ return false unless resp(check_obj).status == 200
26
+
27
+ check_method.call(_parsed(resp(check_obj)))
35
28
  end
36
29
 
37
- private
30
+ def resp(check_obj)
31
+ @resp ||= connection
32
+ .send(http_verb,
33
+ "#{check_obj.value.delete(' ')}#{path_suffix}")
34
+ # .get('SE17QD')
35
+ end
38
36
 
39
- def _message(str, res)
37
+ def message(res, str = nil)
40
38
  "#{res}::#{path}: #{str}"
41
39
  end
42
40
 
41
+ private
42
+
43
43
  def _parsed(resp)
44
44
  JSON.parse(resp.body)
45
45
  end
46
-
47
- def _result_and_message
48
- return [false, _message(@resp.status, false)] unless @resp.status == 200
49
-
50
- return [true, _message(success_message, true)] if check_method
51
- .call(_parsed(@resp))
52
-
53
- [false, _message(failure_message, false)]
54
- rescue StandardError => e
55
- [false, _message(e, false)]
56
- end
57
46
  end
58
47
  end
@@ -1,16 +1,18 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'faraday'
4
+
3
5
  module Checkability
4
6
  # Create connection
5
7
  #
6
8
  class ExternalApiConnector
7
9
  attr_reader :path
8
10
 
9
- def initialize(conf)
10
- @path = conf[:path]
11
+ def initialize(path)
12
+ @path = path
11
13
  end
12
14
 
13
- def connect
15
+ def connection
14
16
  Faraday.new(url: path) do |faraday|
15
17
  faraday.headers['Content-Type'] = 'application/json'
16
18
  faraday.adapter Faraday.default_adapter
@@ -1,33 +1,30 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative 'chain_of_resp/abstract_handler'
3
+ require_relative 'base_checker'
4
4
  module Checkability
5
5
  # Checks if postcode exists in Storage
6
6
  #
7
- class StorageChecker < ChainOfResp::AbstractHandler
8
- attr_reader :storage_class
7
+ class StorageChecker < BaseChecker
8
+ attr_reader :storage_class, :attr_name
9
9
 
10
10
  def post_initialize(conf = {})
11
11
  @storage_class = conf[:storage_class]
12
+ @attr_name = conf[:attr_name] || :value
12
13
  end
13
14
 
14
- def check_value(checkable)
15
- value = checkable.value.upcase
16
- result = _present_in_storage(value)
17
- checkable.messages << (
18
- result ? _message('Found', result) : _message('Not found', result))
19
- result
15
+ def result(checkable)
16
+ value = _normalize_value(checkable.send(attr_name))
17
+ storage_class.where(attr_name => value).present?
20
18
  end
21
19
 
22
- def _present_in_storage(value)
23
- storage_class.where(value: value)
24
- .or(storage_class.where(value: value.strip))
25
- .or(storage_class.where(value: value.delete(' ')))
26
- .present?
20
+ def message(res, str = nil)
21
+ "#{res}::Allowed #{storage_class}s list: #{str}"
27
22
  end
28
23
 
29
- def _message(str, res)
30
- "#{res}::Allowed #{storage_class}s list: #{str}."
24
+ private
25
+
26
+ def _normalize_value(value)
27
+ value.delete(' ').upcase
31
28
  end
32
29
  end
33
30
  end
@@ -3,27 +3,15 @@
3
3
  module Checkability
4
4
  # Checks if postcode comply with regex
5
5
  #
6
- class Validator < ChainOfResp::AbstractHandler
6
+ class Validator < BaseChecker
7
7
  attr_reader :format
8
8
 
9
9
  def post_initialize(conf = {})
10
10
  @format = conf[:format]
11
11
  end
12
12
 
13
- def check_value(checkable)
14
- result, message = _result_and_message(checkable)
15
- checkable.messages << message
16
- result
17
- end
18
-
19
- private
20
-
21
- def _result_and_message(checkable)
22
- if (checkable.value.delete(' ') =~ format[:regex]).nil?
23
- [false, "false::Value is NOT COMPLY with format of #{format[:name]}."]
24
- else
25
- [true, "true::Value is COMPLY with format of #{format[:name]}."]
26
- end
13
+ def result(checkable)
14
+ !(checkable.value.delete(' ') =~ format[:regex]).nil?
27
15
  end
28
16
  end
29
17
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Checkability
4
- VERSION = '0.6.0'
4
+ VERSION = '1.0.1'
5
5
  end
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.6.0
4
+ version: 1.0.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andrey Eremeev
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-04-03 00:00:00.000000000 Z
11
+ date: 2021-04-06 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: Provide Checkers functionality.
14
14
  email:
@@ -24,9 +24,9 @@ files:
24
24
  - bin/checkability
25
25
  - lib/checkability.rb
26
26
  - lib/checkability/acts_as_checkable.rb
27
- - lib/checkability/chain_of_resp/abstract_handler.rb
28
- - lib/checkability/chain_of_resp/handler.rb
27
+ - lib/checkability/base_checker.rb
29
28
  - lib/checkability/checkable.rb
29
+ - lib/checkability/checker.rb
30
30
  - lib/checkability/external_api_checker.rb
31
31
  - lib/checkability/external_api_connector.rb
32
32
  - lib/checkability/railtie.rb
@@ -1,42 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative 'handler'
4
-
5
- module ChainOfResp
6
- # @abstract
7
- class AbstractHandler < ChainOfResp::Handler
8
- # @return [Handler]
9
- attr_reader :stop_process_on_failure, :stop_process_on_success
10
- attr_accessor :handler, :result
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
- @next_handler = nil
16
- post_initialize(opts) # implemented in subclass
17
- end
18
-
19
- # @param [Handler] handler
20
- #
21
- # @return [Handler]
22
- def next_handler(handler)
23
- @handler = handler if handler
24
-
25
- handler
26
- end
27
-
28
- # @abstract
29
- #
30
- # @param [String] request
31
- #
32
- # @return [Boolean, nil]
33
- def handle(request)
34
- check = check_value(request) # imlemented in subclass
35
- return true if check && stop_process_on_success
36
-
37
- return false if !check && stop_process_on_failure
38
-
39
- handler&.handle(request)
40
- end
41
- end
42
- end
@@ -1,31 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module ChainOfResp
4
- # @abstract
5
- class Handler
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(_request)
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
- end
31
- end