checkability 0.6.1 → 2.0.1

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
2
  SHA256:
3
- metadata.gz: a02dfee4b2afe386a20062c53ba6961442b50597c0d0edc822f66971155f1431
4
- data.tar.gz: 65710661a0c8c127de790089e47866046c23e23e5a0041f864e2f5d0b38dc48e
3
+ metadata.gz: fa1ae6fc8c72cd3073a9301eb633a23bed7a3912a3e338e54c83aba5fc8f4b08
4
+ data.tar.gz: 8d1935bd53420a47316e76ce952b18c0b8ca4d96e8ee0193fcce5aea16a159e4
5
5
  SHA512:
6
- metadata.gz: ce4d8e4626aa47b7a15fa909bb82ca87334cc106f230b4f62015101a4f274e0e3da288f3f65565fe7abf5aaf8798f446e5908447144c13666b8dbf6da14ba106
7
- data.tar.gz: f26b6d62f724617b2fcf1b141cad53dccdd760720f3f3205792a34ff5d9604fc72b75a4d2b5519f7a76436ed5a7d8c486158ac066c370a15db523e550697c939
6
+ metadata.gz: 971c297f7e4d8da9eb73a02bdad49329c0e84024553d3f864e0a91e02aee71fc5f71e0ab3d4ef9b66b6696047237c3c36f7c22d72004bc70fc6dfceb4d4ec125
7
+ data.tar.gz: 1a22cb5f5f8b25612116f5b302e82b5d914a05aaedfc624c6c635db56fd23d3998b29dc8582f633d78f64f7ef8120d5a87d66052b0c5adba0ec41558174166a6
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,50 +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
- first_handler_name = opts[:first_handler]
25
- _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)
26
34
  rescue StandardError => e
27
- checkable.messages << "false::#{e}: #{opts}."
35
+ check_obj.ch_messages << "false:::#{e}: #{handler_confs}."
28
36
  false
29
37
  end
30
38
 
31
39
  private
32
40
 
33
- def _handlers(opts)
34
- handler_confs = opts[:handler_confs]
35
- handlers = {}
36
- handler_confs.each do |handler_name, handler_conf|
37
- handlers[handler_name] = _make_handler(handler_name, handler_conf)
38
- end
39
- handlers.each do |handler_name, handler|
40
- next_handler_name = handler_confs[handler_name][:next_handler]
41
- 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]
42
46
  end
47
+ handlers
48
+ end
49
+
50
+ def _make_handlers(confs)
51
+ confs.transform_values { |conf| _make_handler(conf) }
43
52
  end
44
53
 
45
- def _make_handler(_name, conf)
46
- k = Checkability.const_get conf[:name].to_s.camelize
47
- k.new(conf)
54
+ def _make_handler(conf)
55
+ Checkability.const_get(conf[:name].to_s.camelize)
56
+ .new(conf)
48
57
  end
49
58
  end
50
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
35
- end
36
-
37
- private
24
+ def result(check_obj)
25
+ return false unless resp(check_obj).status == 200
38
26
 
39
- def _message(str, res)
40
- "#{res}::#{path}: #{str}"
27
+ check_method.call(_parsed(resp(check_obj)))
41
28
  end
42
29
 
43
- def _parsed(resp)
44
- JSON.parse(resp.body)
30
+ def resp(check_obj)
31
+ @resp ||= connection
32
+ .send(http_verb,
33
+ "#{check_obj.value.delete(' ')}#{path_suffix}")
34
+ # .get('SE17QD')
45
35
  end
46
36
 
47
- def _result_and_message
48
- return [false, _message(@resp.status, false)] unless @resp.status == 200
37
+ def message(res, str = nil)
38
+ "#{res}:::#{path}: #{str}"
39
+ end
49
40
 
50
- return [true, _message(success_message, true)] if check_method
51
- .call(_parsed(@resp))
41
+ private
52
42
 
53
- [false, _message(failure_message, false)]
54
- rescue StandardError => e
55
- [false, _message(e, false)]
43
+ def _parsed(resp)
44
+ JSON.parse(resp.body)
56
45
  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.1'
4
+ VERSION = '2.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.1
4
+ version: 2.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