checkability 0.2.0 → 0.6.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: 7c20a76958ba1f8025605a3ded3101c8a0e3eeb2
4
- data.tar.gz: 8b69ff85aea14d3726827e58954cc6efb8bdb502
2
+ SHA256:
3
+ metadata.gz: 0f584d475c0bf9395f3cbdb0d47a436b7f1a56ab93fb4d76095b58de9a0a4485
4
+ data.tar.gz: d9ff4ef5b3a877fd0a8efe830958df8e14d3ae0e221903fbb436623457c14e74
5
5
  SHA512:
6
- metadata.gz: 4fe465c7c77639f20865c2e37df153615298df3b6284587660b030ec0833bedc5bcfb14e59a39252988d1276721ece24fa88d8000291ae188a50ff1897ebb8eb
7
- data.tar.gz: 26494daaeae8b5497b2c2db96ee1c21ddfabf027b93a30e6b1dd91d06936f4dd4fdff616d2391cf5fa1620df07a7806fadb8b69899ee232619d95a67cfa0e8a0
6
+ metadata.gz: e7f9740350a632cea6131709f9e765f0c8e47981b564a8fb426103fe1c55688f7d27ce7190b11278e540807bd0e2dfeabe65d5d47d4e494b4865074db384447d
7
+ data.tar.gz: 4baa39ca9c3aaec3845e2d84a72f38caf74f662bab1b3f6ff453439763393db4865c7a3912b8c09f606d37a2b15860f779750f9d8cc0e8b19f102362310355d5
data/README.md CHANGED
@@ -9,8 +9,47 @@ with return of true|false
9
9
  ## Usage
10
10
  How to use my plugin.
11
11
 
12
- inside of any ruby class include Checkablilty
13
- next
12
+ inside of any rails model do
13
+ ```ruby
14
+ class SomeModel
15
+ acts_as_checkable strategy: proc { |a, b, c| a && (b || c) },
16
+ checkers: uk_postcode_checkers
17
+ end
18
+ ```
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
21
+ then in your controller:
22
+ ```ruby
23
+ class ChecksController < ApplicationController
24
+ def checking
25
+ @check = Check.new
26
+ end
27
+
28
+ def perform
29
+ @check = Check.new(value: check_params[:string])
30
+ message, alert_class =
31
+ if @check.valid?
32
+ @check.perform_check
33
+ [@check.messages.join('<br/>'), _alert_class(@check.allowed)]
34
+ else
35
+ [@check.errors.full_messages.join('<br/>'), _alert_class(false)]
36
+ end
37
+ redirect_to checking_path, flash: { now: message, alert_class: alert_class }
38
+ end
39
+
40
+ private
41
+
42
+ def _alert_class(cond)
43
+ cond ? 'success' : 'danger'
44
+ end
45
+
46
+ def check_params
47
+ params.permit(:string)
48
+ end
49
+ end
50
+ ```
51
+ for more detailed example see application
52
+ in https://github.com/azazelo/postcode_checker
14
53
 
15
54
  ## Installation
16
55
  Add this line to your application's Gemfile:
@@ -34,3 +73,7 @@ Contribution directions go here.
34
73
 
35
74
  ## License
36
75
  The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
76
+
77
+ ## Future works
78
+
79
+ - [ ] Use ChainOfResponsibility pattern to simplify call of checkers
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
 
@@ -8,4 +9,3 @@ puts 'Gem provide acts_as_checkable addon to active record models'
8
9
  puts "Version: #{Checkability::VERSION}"
9
10
  puts ''
10
11
  puts '-----------------'
11
-
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/chain_of_resp/handler'
13
+ require_relative 'checkability/chain_of_resp/abstract_handler'
10
14
 
11
15
  ActiveRecord::Base.include Checkability::ActsAsCheckable
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Checkability
2
4
  # Adding class and instance methods
3
5
  #
@@ -10,9 +12,7 @@ module Checkability
10
12
 
11
13
  class_methods do
12
14
  def acts_as_checkable(options = {})
13
- if !options.is_a?(Hash) && !options.empty?
14
- raise ArgumentError, "Hash expected, got #{options.class.name}"
15
- end
15
+ raise ArgumentError, "Hash expected, got #{options.class.name}" if !options.is_a?(Hash) && !options.empty?
16
16
 
17
17
  class_attribute :checkable_conf
18
18
 
@@ -21,23 +21,30 @@ module Checkability
21
21
  end
22
22
 
23
23
  attr_accessor :allowed, :messages
24
- def setup
25
- self.allowed = nil
26
- self.messages = []
24
+
25
+ def perform_check
26
+ _setup
27
+ self.allowed = Checkability::Checkable.new(self).check(checkable_conf)
28
+ messages << "#{allowed}::'#{_value}' is #{_allowness}. "
27
29
  end
28
30
 
29
- def perform
30
- setup
31
- self.allowed = _check
32
- messages << "#{self.class.name} '#{value}' is #{_allowness}. "
31
+ private
32
+
33
+ def _value
34
+ send(_attr_name)
33
35
  end
34
36
 
35
- def _allowness
36
- allowed ? 'ALLOWED' : 'NOT allowed'
37
+ def _attr_name
38
+ checkable_conf[:attr_name] || :value
37
39
  end
38
40
 
39
- def _check
40
- Checkability::Checkable.new(self).check(checkable_conf)
41
+ def _setup
42
+ self.allowed = nil
43
+ self.messages = []
44
+ end
45
+
46
+ def _allowness
47
+ allowed ? 'ALLOWED' : 'NOT allowed'
41
48
  end
42
49
  end
43
50
  end
@@ -0,0 +1,42 @@
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
@@ -0,0 +1,31 @@
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
@@ -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,21 +9,43 @@ module Checkability
7
9
 
8
10
  def initialize(checkable)
9
11
  @checkable = checkable
12
+ @checkable.messages = []
13
+ end
14
+
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
+ require 'pry'; binding.pry
25
+ first_handler_name = opts[:first_handler]
26
+ _handlers(opts)[first_handler_name].handle(checkable)
27
+ rescue StandardError => e
28
+ checkable.messages << "false::#{e}: #{opts}."
29
+ false
30
+ end
31
+
32
+ private
33
+
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])
43
+ end
10
44
  end
11
45
 
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(conf)
19
- conf[:algoritm].call(
20
- conf[:checkers].map do |checker_name, checker_conf|
21
- k = Checkability.const_get(checker_name.to_s.camelize)
22
- k.new(checker_conf).check_value(checkable)
23
- end
24
- )
46
+ def _make_handler(_name, conf)
47
+ k = Checkability.const_get conf[:name].to_s.camelize
48
+ k.new(conf)
25
49
  end
26
50
  end
27
51
  end
@@ -1,22 +1,34 @@
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
+
10
+ require_relative 'chain_of_resp/abstract_handler'
6
11
  module Checkability
7
12
  # Checks if postcode exists in external API
8
13
  #
9
- class ExternalApiChecker
10
- attr_reader :path, :check_method, :connection
14
+ class ExternalApiChecker < ChainOfResp::AbstractHandler
15
+ attr_reader :path, :path_suffix, :check_method, :connection, :http_verb,
16
+ :failure_message, :success_message
11
17
 
12
- def initialize(conf = {})
18
+ def post_initialize(conf = {})
13
19
  @path = conf[:path]
20
+ @http_verb = conf[:http_verb] || :get
21
+ @path_suffix = conf[:path_suffix] || ''
14
22
  @check_method = conf[:check_method]
23
+ @failure_message = conf[:failure_message] || 'Failed.'
24
+ @success_message = conf[:success_message] || 'Success.'
15
25
  @connection = Checkability::ExternalApiConnector.new(conf)
16
26
  end
17
27
 
18
28
  def check_value(checkable)
19
- @resp = connection.connect.get(checkable.value.delete(' '))
29
+ @resp = connection
30
+ .connect
31
+ .send(http_verb, "#{checkable.value.delete(' ')}#{path_suffix}")
20
32
  result, message = _result_and_message
21
33
  checkable.messages << message
22
34
  result
@@ -24,8 +36,8 @@ module Checkability
24
36
 
25
37
  private
26
38
 
27
- def _message(str)
28
- "#{path}: #{str}"
39
+ def _message(str, res)
40
+ "#{res}::#{path}: #{str}"
29
41
  end
30
42
 
31
43
  def _parsed(resp)
@@ -33,13 +45,14 @@ module Checkability
33
45
  end
34
46
 
35
47
  def _result_and_message
36
- return [false, _message(@resp.status)] unless @resp.status == 200
48
+ return [false, _message(@resp.status, false)] unless @resp.status == 200
37
49
 
38
- return [true, _message('Found.')] if check_method.call(_parsed(@resp))
50
+ return [true, _message(success_message, true)] if check_method
51
+ .call(_parsed(@resp))
39
52
 
40
- [false, _message('Not found in allowed areas.')]
53
+ [false, _message(failure_message, false)]
41
54
  rescue StandardError => e
42
- [false, _message(e)]
55
+ [false, _message(e, false)]
43
56
  end
44
57
  end
45
58
  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,17 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'chain_of_resp/abstract_handler'
1
4
  module Checkability
2
5
  # Checks if postcode exists in Storage
3
6
  #
4
- class StorageChecker
7
+ class StorageChecker < ChainOfResp::AbstractHandler
5
8
  attr_reader :storage_class
6
9
 
7
- def initialize(conf = {})
10
+ def post_initialize(conf = {})
8
11
  @storage_class = conf[:storage_class]
9
12
  end
10
13
 
11
14
  def check_value(checkable)
12
15
  value = checkable.value.upcase
13
16
  result = _present_in_storage(value)
14
- checkable.messages << (result ? _message('Found') : _message('Not found'))
17
+ checkable.messages << (
18
+ result ? _message('Found', result) : _message('Not found', result))
15
19
  result
16
20
  end
17
21
 
@@ -22,8 +26,8 @@ module Checkability
22
26
  .present?
23
27
  end
24
28
 
25
- def _message(str)
26
- "Allowed #{storage_class}s list: #{str}."
29
+ def _message(str, res)
30
+ "#{res}::Allowed #{storage_class}s list: #{str}."
27
31
  end
28
32
  end
29
33
  end
@@ -1,10 +1,12 @@
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 < ChainOfResp::AbstractHandler
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
 
@@ -14,11 +16,13 @@ module Checkability
14
16
  result
15
17
  end
16
18
 
19
+ private
20
+
17
21
  def _result_and_message(checkable)
18
22
  if (checkable.value.delete(' ') =~ format[:regex]).nil?
19
- [false, "Value is not comply with format of #{format[:name]}."]
23
+ [false, "false::Value is NOT COMPLY with format of #{format[:name]}."]
20
24
  else
21
- [true, "Value comply with format of #{format[:name]}."]
25
+ [true, "true::Value is COMPLY with format of #{format[:name]}."]
22
26
  end
23
27
  end
24
28
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Checkability
2
- VERSION = '0.2.0'.freeze
4
+ VERSION = '0.6.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.2.0
4
+ version: 0.6.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-03-30 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:
@@ -24,6 +24,8 @@ 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
29
  - lib/checkability/checkable.rb
28
30
  - lib/checkability/external_api_checker.rb
29
31
  - lib/checkability/external_api_connector.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: []