strong_interface 0.1.0 → 0.3.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 +4 -4
- data/CHANGELOG.md +28 -0
- data/Gemfile.lock +1 -1
- data/README.md +21 -10
- data/lib/strong_interface/parameters_validator.rb +40 -0
- data/lib/strong_interface/version.rb +1 -1
- data/lib/strong_interface.rb +21 -7
- data/strong_interface.gemspec +1 -0
- metadata +5 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8cf1e550ee688057b954e398cd8b74fa8c6622c46ff79e3d5783dab70d977ca2
|
4
|
+
data.tar.gz: b6430938ec444d0a5686560b850143626fca0ecadbe06a6961f960fde0f98030
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2734acdbd5793a2746beaafd088b7fc9263b9326034a3e7db3004b159024673c7a02bdd94a1fea3a979b56c84c3cf37ce950f486b4fdd54f8b80355a3f03c131
|
7
|
+
data.tar.gz: 5211b5df2b6f50be7ba05dbe698fa36f5f7bd6f99239ceb4afd14e562d9b4282ec9d09ee0e4bdb03d2bef6bc7fcfd0bcb513bfbef9fea4f4c51dfe52791ad192
|
data/CHANGELOG.md
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
# Changelog
|
2
|
+
|
3
|
+
## main (unreleased)
|
4
|
+
|
5
|
+
---
|
6
|
+
|
7
|
+
## 0.3.1
|
8
|
+
|
9
|
+
## Bugfixes
|
10
|
+
|
11
|
+
- Fixed CHANGELOG.md
|
12
|
+
|
13
|
+
## 0.3.0
|
14
|
+
|
15
|
+
### New Features
|
16
|
+
|
17
|
+
- [#1](https://github.com/programyan/strong_interface/pull/1) Added constants validation
|
18
|
+
|
19
|
+
## 0.2.0
|
20
|
+
|
21
|
+
### New features
|
22
|
+
|
23
|
+
- [9506eb3](https://github.com/programyan/strong_interface/commit/9506eb31666628cd6d06a4a4608ca81081a1315b) Add validation parameters
|
24
|
+
|
25
|
+
## 0.1.0
|
26
|
+
|
27
|
+
- DSL
|
28
|
+
- Basic implementation of methods presence
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -32,8 +32,9 @@ Or install it yourself as:
|
|
32
32
|
|
33
33
|
```ruby
|
34
34
|
module IDog
|
35
|
+
WORD = String
|
35
36
|
def self.create(*); end
|
36
|
-
def eat(
|
37
|
+
def eat(food); end
|
37
38
|
def voice; end
|
38
39
|
end
|
39
40
|
```
|
@@ -45,16 +46,18 @@ class Lessy
|
|
45
46
|
extend StrongInterface
|
46
47
|
implements IDog
|
47
48
|
|
49
|
+
WORD = 'gav'
|
50
|
+
|
48
51
|
def self.create(name)
|
49
|
-
...
|
52
|
+
# Creating...
|
50
53
|
end
|
51
54
|
|
52
55
|
def eat(food)
|
53
|
-
...
|
56
|
+
# Eating...
|
54
57
|
end
|
55
58
|
|
56
59
|
def voice
|
57
|
-
|
60
|
+
WORD
|
58
61
|
end
|
59
62
|
end
|
60
63
|
```
|
@@ -66,6 +69,10 @@ class Lessy
|
|
66
69
|
extend StrongInterface
|
67
70
|
implements IDog
|
68
71
|
|
72
|
+
def eat(food, water)
|
73
|
+
# Eating...
|
74
|
+
end
|
75
|
+
|
69
76
|
def voice
|
70
77
|
'Gav'
|
71
78
|
end
|
@@ -75,8 +82,9 @@ end
|
|
75
82
|
#### Exception will be raised
|
76
83
|
|
77
84
|
```shell
|
78
|
-
StrongInterface::
|
79
|
-
|
85
|
+
StrongInterface::ImplementationError (Constant `WORD` is absent at `Lessy`)
|
86
|
+
Class method `create` is not implemented at `Lessy`
|
87
|
+
Invalid parameters at method `eat`, expected: `def eat(food)`, got: `def eat(food, water)`
|
80
88
|
```
|
81
89
|
|
82
90
|
## Validation Strategies
|
@@ -88,7 +96,7 @@ If the variable is not set, the `raise` strategy will be applied.
|
|
88
96
|
|
89
97
|
#### raise (default)
|
90
98
|
|
91
|
-
This is a default strategy. When validator finds incorrect implementation, it raises the `StrongInterface::
|
99
|
+
This is a default strategy. When validator finds incorrect implementation, it raises the `StrongInterface::ImplementationError` exception,
|
92
100
|
and provides a list of methods which aren't implemented
|
93
101
|
|
94
102
|
#### log
|
@@ -100,7 +108,10 @@ even if it has this kind of a problem in code.
|
|
100
108
|
## TODO
|
101
109
|
|
102
110
|
- [x] Check if methods of interfaces all exists in a class or module
|
103
|
-
- [
|
111
|
+
- [x] Check the arguments of methods
|
112
|
+
- [x] Check constants
|
113
|
+
- [ ] Checking the privacy of methods???
|
114
|
+
- [ ] Allow optional arguments at interface methods???
|
104
115
|
|
105
116
|
## Development
|
106
117
|
|
@@ -110,7 +121,7 @@ To install this gem onto your local machine, run `bundle exec rake install`. To
|
|
110
121
|
|
111
122
|
## Contributing
|
112
123
|
|
113
|
-
Bug reports and pull requests are welcome on GitHub at https://github.com/
|
124
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/programyan/strong_interface. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [code of conduct](https://github.com/programyan/strong_interface/blob/main/CODE_OF_CONDUCT.md).
|
114
125
|
|
115
126
|
|
116
127
|
## License
|
@@ -119,4 +130,4 @@ The gem is available as open source under the terms of the [MIT License](https:/
|
|
119
130
|
|
120
131
|
## Code of Conduct
|
121
132
|
|
122
|
-
Everyone interacting in the StrongInterface project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/
|
133
|
+
Everyone interacting in the StrongInterface project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/programyan/strong_interface/blob/main/CODE_OF_CONDUCT.md).
|
@@ -0,0 +1,40 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module StrongInterface
|
4
|
+
class ParametersValidator
|
5
|
+
def initialize(interface_method, klass_method)
|
6
|
+
@interface_method = interface_method
|
7
|
+
@interface_method_parameters = interface_method.parameters.map { |param| param[0] }
|
8
|
+
@klass_method = klass_method
|
9
|
+
@klass_method_parameters = klass_method.parameters.map { |param| param[0] }
|
10
|
+
end
|
11
|
+
|
12
|
+
def validate
|
13
|
+
return if valid?
|
14
|
+
|
15
|
+
"Invalid parameters at method `#{@klass_method.name}`, expected: `def #{description(@interface_method)}`," \
|
16
|
+
" got: `def #{description(@klass_method)}`"
|
17
|
+
end
|
18
|
+
|
19
|
+
def valid?
|
20
|
+
return true if @interface_method_parameters == [:rest]
|
21
|
+
return true if @klass_method_parameters == [:rest]
|
22
|
+
|
23
|
+
return true if @interface_method_parameters == @klass_method_parameters
|
24
|
+
return false if @interface_method_parameters.size != @klass_method_parameters.size
|
25
|
+
|
26
|
+
@interface_method_parameters.each.with_index.all? do |key, index|
|
27
|
+
case key
|
28
|
+
when :req
|
29
|
+
%i[req opt].include? @klass_method_parameters[index]
|
30
|
+
when :keyreq
|
31
|
+
%i[keyreq key].include? @klass_method_parameters[index]
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def description(metod)
|
37
|
+
metod.inspect.scan(/[.|#](\S+?\(.*?\))/).last.first
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
data/lib/strong_interface.rb
CHANGED
@@ -1,19 +1,21 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require 'strong_interface/version'
|
4
|
+
require 'strong_interface/parameters_validator'
|
4
5
|
|
5
6
|
module StrongInterface
|
6
|
-
|
7
|
+
ImplementationError = Class.new(StandardError)
|
7
8
|
UnknownStrategy = Class.new(StandardError)
|
8
9
|
|
9
10
|
RAISING_STRATEGIES = {
|
10
|
-
'raise' => ->(error) { raise
|
11
|
+
'raise' => ->(error) { raise ImplementationError, error },
|
11
12
|
'log' => ->(error) { Logger.new($stdout).warn { error } }
|
12
13
|
}.freeze
|
13
14
|
|
14
15
|
# @param interfaces [Module|Class|Array<Module|Class>] the list of interfaces that class or module should implements
|
15
|
-
# @raise [UnknownStrategy] if
|
16
|
-
# @raise [ImplementationError] if describing some methods of an interface has been forgotten and
|
16
|
+
# @raise [UnknownStrategy] if SI_VALIDATION_STRATEGY environment variable has wrong value
|
17
|
+
# @raise [ImplementationError] if describing some methods of an interface has been forgotten and
|
18
|
+
# SI_VALIDATION_STRATEGY environment variable is set to `raise`
|
17
19
|
def implements(interfaces)
|
18
20
|
TracePoint.trace(:end) do |t|
|
19
21
|
next if self != t.self
|
@@ -33,20 +35,32 @@ module StrongInterface
|
|
33
35
|
|
34
36
|
def validate(interfaces)
|
35
37
|
Array(interfaces).flat_map do |interface|
|
36
|
-
validate_class_methods(interface) + validate_instance_methods(interface)
|
38
|
+
validate_constants(interface) + validate_class_methods(interface) + validate_instance_methods(interface)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def validate_constants(interface)
|
43
|
+
(interface.constants - constants).map do |missing_constant|
|
44
|
+
"Constant `#{missing_constant}` is absent at `#{self}`"
|
37
45
|
end
|
38
46
|
end
|
39
47
|
|
40
48
|
def validate_class_methods(interface)
|
41
49
|
interface.methods(false).filter_map do |klass_method|
|
42
|
-
|
50
|
+
if !methods(false).include?(klass_method)
|
51
|
+
"Class method `#{klass_method}` is not implemented at `#{self}`"
|
52
|
+
else
|
53
|
+
ParametersValidator.new(interface.method(klass_method), method(klass_method)).validate
|
54
|
+
end
|
43
55
|
end
|
44
56
|
end
|
45
57
|
|
46
58
|
def validate_instance_methods(interface)
|
47
59
|
interface.instance_methods.filter_map do |instance_method|
|
48
|
-
|
60
|
+
if !instance_methods.include?(instance_method)
|
49
61
|
"Instance method `#{instance_method}` is not implemented at `#{self}`"
|
62
|
+
else
|
63
|
+
ParametersValidator.new(interface.instance_method(instance_method), instance_method(instance_method)).validate
|
50
64
|
end
|
51
65
|
end
|
52
66
|
end
|
data/strong_interface.gemspec
CHANGED
@@ -16,6 +16,7 @@ Gem::Specification.new do |spec|
|
|
16
16
|
|
17
17
|
spec.metadata['homepage_uri'] = spec.homepage
|
18
18
|
spec.metadata['source_code_uri'] = 'https://github.com/programyan/strong_interface'
|
19
|
+
spec.metadata['changelog_uri'] = 'https://github.com/programyan/strong_interface/blob/main/CHANGELOG.md'
|
19
20
|
|
20
21
|
# Specify which files should be added to the gem when it is released.
|
21
22
|
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: strong_interface
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1
|
4
|
+
version: 0.3.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Andrew Ageev
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-06-
|
11
|
+
date: 2022-06-11 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: Simple implementation of an interface pattern for Ruby
|
14
14
|
email:
|
@@ -19,6 +19,7 @@ extra_rdoc_files: []
|
|
19
19
|
files:
|
20
20
|
- ".gitignore"
|
21
21
|
- ".rspec"
|
22
|
+
- CHANGELOG.md
|
22
23
|
- CODE_OF_CONDUCT.md
|
23
24
|
- Gemfile
|
24
25
|
- Gemfile.lock
|
@@ -28,6 +29,7 @@ files:
|
|
28
29
|
- bin/console
|
29
30
|
- bin/setup
|
30
31
|
- lib/strong_interface.rb
|
32
|
+
- lib/strong_interface/parameters_validator.rb
|
31
33
|
- lib/strong_interface/version.rb
|
32
34
|
- strong_interface.gemspec
|
33
35
|
homepage: https://github.com/programyan/strong_interface
|
@@ -36,6 +38,7 @@ licenses:
|
|
36
38
|
metadata:
|
37
39
|
homepage_uri: https://github.com/programyan/strong_interface
|
38
40
|
source_code_uri: https://github.com/programyan/strong_interface
|
41
|
+
changelog_uri: https://github.com/programyan/strong_interface/blob/main/CHANGELOG.md
|
39
42
|
post_install_message:
|
40
43
|
rdoc_options: []
|
41
44
|
require_paths:
|