shaped 0.6.4 → 0.8.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
2
  SHA256:
3
- metadata.gz: 1f6ca9518d2b3b0b55988f53d055a48c1344c54d6c8f8497877fb48e8ad621e1
4
- data.tar.gz: c7e2be555928b918681670b803ea95b70ad97da25f0b4079be7fa6f16c4f6892
3
+ metadata.gz: 9a84f7dd70b2d40e32d1dde68014ec240d1681ef75f9c111d7ef52943a99cbab
4
+ data.tar.gz: bf55523db329247de28c8140a8b4e06392879b6893649bf5de3e4c5da206bbde
5
5
  SHA512:
6
- metadata.gz: 59c995d6a92d07d29b87a565924dbd175f8bce9e7ce158bdc98cf450aa5fb8e5073f78e6eeea5be0a140045e838e3562da9a2562a3263666dceeac23b7ac0368
7
- data.tar.gz: 4c3b1e10af00279e075c7094a06b07b8624f3fc165fcea3704db18a5d52ec48b58bf9a8dffd31320465f2bad598d820f193f901be9bbe7f29e2852e7d8eda5a3
6
+ metadata.gz: 72652921092823a183d70edad881be6e3ad881c5c443ce9b2513b54975e6acda118716ed35e597c3414cfdd40ed0cf93ee884d4429c5f4dce445a254dcfa30de
7
+ data.tar.gz: 0d6e6d2951c4885cf22389da5805211f1410c48b442183067fa862218a967b380e112971f63c08c5e4842723ca77517ebaf4ff3fe7b8b348e0dcc23a8d265fe8
@@ -0,0 +1,21 @@
1
+ name: Run Tests, Linters, Etc.
2
+
3
+ on:
4
+ pull_request:
5
+ branches:
6
+ - master
7
+
8
+ jobs:
9
+ build:
10
+ runs-on: ubuntu-latest
11
+ steps:
12
+ - uses: actions/checkout@v2
13
+ - uses: ruby/setup-ruby@v1
14
+ with:
15
+ bundler-cache: true
16
+ - name: Run Rubocop
17
+ run: bin/rubocop --format clang
18
+ - name: Run RSpec tests
19
+ run: bin/rspec --format progress
20
+ - name: Ensure no git diff
21
+ run: git diff --exit-code && git diff-index --quiet --cached HEAD
@@ -1,142 +1,5 @@
1
- AllCops:
2
- EnabledByDefault: true
3
- Exclude:
4
- - !ruby/regexp /\/db\/migrate/201[1-8].*\.rb\z/
5
- # auto-generated files; best to leave as-is
6
- - bin/{annotate,brakeman,bundle,database_consistency,pallets,rubocop,sidekiq}
7
- - db/schema.rb
8
- - lib/tasks/auto_annotate_models.rake
9
- - node_modules/**/*
10
- TargetRubyVersion: 2.7
11
- Bundler/GemComment:
12
- Enabled: false
13
- Layout/ArgumentAlignment:
14
- EnforcedStyle: with_fixed_indentation
15
- Layout/ClassStructure:
16
- ExpectedOrder:
17
- - module_inclusion
18
- - constants
19
- - public_class_methods
20
- - initializer
21
- - public_methods
22
- - protected_methods
23
- - private_methods
24
- Layout/DotPosition:
25
- EnforcedStyle: trailing
26
- Layout/FirstArgumentIndentation:
27
- Enabled: false # this rule doesn't play nicely with the way that I like to use `memoize`
28
- Layout/FirstArrayElementIndentation:
29
- EnforcedStyle: consistent
30
- Layout/LineLength:
31
- IgnoredPatterns:
32
- # ignore line length if the line is a comment without any spaces; it's probably not something we
33
- # can fix (e.g. a long file path)
34
- - !ruby/regexp /^ *#? [\S]+$/
35
- Max: 100
36
- Layout/MultilineMethodCallIndentation:
37
- EnforcedStyle: indented
38
- Layout/SpaceBeforeBlockBraces:
39
- Enabled: false
40
- Layout/SpaceBeforeSemicolon:
41
- Enabled: false
42
- Layout/SpaceInsideHashLiteralBraces:
43
- EnforcedStyle: space
44
- Lint/RedundantSplatExpansion:
45
- Enabled: false
46
- Metrics/AbcSize:
47
- Enabled: false
48
- Metrics/BlockLength:
49
- Enabled: false
50
- Metrics/ClassLength:
51
- Enabled: false
52
- Metrics/MethodLength:
53
- Max: 30
54
- Naming/RescuedExceptionsVariableName:
55
- Enabled: false
56
- Style/BlockDelimiters:
57
- Enabled: false
58
- Style/ClassAndModuleChildren:
59
- EnforcedStyle: compact
60
- Style/CollectionMethods:
61
- Enabled: false
62
- Style/ConstantVisibility:
63
- Enabled: false
64
- Style/Copyright:
65
- Enabled: false
66
- Style/DisableCopsWithinSourceCodeDirective:
67
- Enabled: false
68
- Style/Documentation:
69
- Enabled: false
70
- Style/DocumentationMethod:
71
- Enabled: false
72
- Style/EmptyCaseCondition:
73
- Enabled: false
74
- Style/FrozenStringLiteralComment:
75
- Enabled: true
76
- Style/GlobalVars:
77
- Enabled: false
78
- Style/GuardClause:
79
- Enabled: false
80
- Style/IfUnlessModifier:
81
- Enabled: false
82
- Style/InlineComment:
83
- Enabled: false
84
- Style/Lambda:
85
- Enabled: false
86
- Style/MethodCallWithArgsParentheses:
87
- IgnoredMethods:
88
- - add_runtime_dependency
89
- - desc
90
- - fail
91
- - file
92
- - gem
93
- - head
94
- - include
95
- - integer
96
- - load
97
- - p
98
- - print
99
- - puts
100
- - render
101
- - require
102
- - require_relative
103
- - ruby
104
- - run
105
- - string
106
- - source
107
- Style/MissingElse:
108
- Enabled: false
109
- Style/NegatedIf:
110
- Enabled: false
111
- Style/ImplicitRuntimeError:
112
- Enabled: false
113
- Style/MethodCalledOnDoEndBlock:
114
- Enabled: false
115
- Style/NumericPredicate:
116
- Enabled: false
117
- Style/ParenthesesAroundCondition:
118
- Enabled: false
119
- Style/RescueModifier:
120
- Enabled: false
121
- Style/RescueStandardError:
122
- Enabled: false
123
- Style/ReturnNil:
124
- Enabled: false
125
- Style/RegexpLiteral:
126
- Enabled: false
127
- Style/Semicolon:
128
- Enabled: false
129
- Style/SignalException:
130
- Enabled: false
131
- Style/StderrPuts:
132
- Enabled: false
133
- Style/StringHashKeys:
134
- Enabled: false
135
- Style/TernaryParentheses:
136
- Enabled: false
137
- Style/TrailingCommaInArguments:
138
- EnforcedStyleForMultiline: comma
139
- Style/TrailingCommaInArrayLiteral:
140
- EnforcedStyleForMultiline: comma
141
- Style/TrailingCommaInHashLiteral:
142
- EnforcedStyleForMultiline: comma
1
+ inherit_gem:
2
+ runger_style:
3
+ - rulesets/default.yml # gem 'rubocop'
4
+ - rulesets/performance.yml # gem 'rubocop-performance'
5
+ - rulesets/rspec.yml # gem 'rubocop-rspec'
@@ -1 +1 @@
1
- 2.7.0
1
+ 2.7.2
@@ -1,3 +1,34 @@
1
+ ## v0.8.0 (2021-01-31)
2
+ ### Added
3
+ - Accept `Method` as a `Callable` shape definition
4
+
5
+ ### Internal
6
+ - Bump Ruby version from 2.7.0 to 2.7.2
7
+ - Move from Travis to GitHub Actions
8
+
9
+ ## v0.7.3 (2021-01-07)
10
+ ### Removed
11
+ - Removed `::name` method for anonymous validator class in `Shaped::Shapes::Class`
12
+
13
+ ## v0.7.2 (2020-07-13)
14
+ ### Dependencies
15
+ - Bump `rubocop` to 0.88.0 and `runger_style` to 0.2.3
16
+
17
+ ## v0.7.1 (2020-07-02)
18
+ ### Internal
19
+ - Source Rubocop rules/config from `runger_style` gem
20
+
21
+ ## v0.7.0 (2020-06-24)
22
+ ### BREAKING CHANGES
23
+ - Rename the `Or` shape to `Any`
24
+ - Add a `Method` shape (where the shape description is the name of a method which, when called on a
25
+ test object, must return a truthy value). This is a breaking change because the `Shaped::Shape`
26
+ constructor will now return an instance of `Shaped::Shapes::Method` rather than
27
+ `Shaped::Shapes::Equality` when called with a Symbol argument.
28
+
29
+ ### Added
30
+ - Add an `All` shape (w/ multiple sub-shapes, all of which must be matched)
31
+
1
32
  ## v0.6.4 (2020-06-22)
2
33
  ### Fixed
3
34
  - Make it possible to specify optional keys in a Hash shape (using an `Or` shape as the value)
@@ -92,7 +123,7 @@
92
123
  `Shaped::Shapes::Hash`):
93
124
  1. `Shaped::Shapes::Class`
94
125
  2. `Shaped::Shapes::Equality`
95
- 3. `Shaped::Shapes::Or`
126
+ 3. `Shaped::Shapes::Any`
96
127
  - All hashes and arrays in shape definitions are parsed "recursively" as shape definitions. For
97
128
  example, instead of:
98
129
 
data/Gemfile CHANGED
@@ -5,10 +5,15 @@ source 'https://rubygems.org'
5
5
  # Specify your gem's dependencies in shaped.gemspec
6
6
  gemspec
7
7
 
8
- gem 'amazing_print'
9
- gem 'pry-byebug'
10
- gem 'rake'
11
- gem 'rubocop'
8
+ group :development, :test do
9
+ gem 'amazing_print'
10
+ gem 'pry-byebug'
11
+ gem 'rake'
12
+ gem 'rubocop', require: false
13
+ gem 'rubocop-performance', require: false
14
+ gem 'rubocop-rspec', require: false
15
+ gem 'runger_style', github: 'davidrunger/runger_style', require: false
16
+ end
12
17
 
13
18
  group :test do
14
19
  gem 'codecov', require: false
@@ -7,35 +7,39 @@ GIT
7
7
  guard-compat (~> 1.1)
8
8
  rspec (>= 2.99.0, < 4.0)
9
9
 
10
+ GIT
11
+ remote: https://github.com/davidrunger/runger_style.git
12
+ revision: ba2f3c3600bd393a3141a4883489ac15e19dbfd0
13
+ specs:
14
+ runger_style (0.2.15)
15
+
10
16
  PATH
11
17
  remote: .
12
18
  specs:
13
- shaped (0.6.4)
19
+ shaped (0.8.0)
14
20
  activemodel (~> 6.0)
15
21
  activesupport (~> 6.0)
16
22
 
17
23
  GEM
18
24
  remote: https://rubygems.org/
19
25
  specs:
20
- activemodel (6.0.3.2)
21
- activesupport (= 6.0.3.2)
22
- activesupport (6.0.3.2)
26
+ activemodel (6.1.1)
27
+ activesupport (= 6.1.1)
28
+ activesupport (6.1.1)
23
29
  concurrent-ruby (~> 1.0, >= 1.0.2)
24
- i18n (>= 0.7, < 2)
25
- minitest (~> 5.1)
26
- tzinfo (~> 1.1)
27
- zeitwerk (~> 2.2, >= 2.2.2)
28
- amazing_print (1.2.1)
30
+ i18n (>= 1.6, < 2)
31
+ minitest (>= 5.1)
32
+ tzinfo (~> 2.0)
33
+ zeitwerk (~> 2.3)
34
+ amazing_print (1.2.2)
29
35
  ast (2.4.1)
30
36
  byebug (11.1.3)
31
- codecov (0.1.17)
32
- json
33
- simplecov
34
- url
37
+ codecov (0.4.0)
38
+ simplecov (>= 0.15, < 0.22)
35
39
  coderay (1.1.3)
36
- concurrent-ruby (1.1.6)
37
- diff-lcs (1.3)
38
- docile (1.3.2)
40
+ concurrent-ruby (1.1.8)
41
+ diff-lcs (1.4.4)
42
+ docile (1.3.5)
39
43
  ffi (1.13.1)
40
44
  formatador (0.2.5)
41
45
  guard (2.16.2)
@@ -48,22 +52,21 @@ GEM
48
52
  shellany (~> 0.0)
49
53
  thor (>= 0.18.1)
50
54
  guard-compat (1.2.1)
51
- i18n (1.8.3)
55
+ i18n (1.8.7)
52
56
  concurrent-ruby (~> 1.0)
53
- json (2.3.0)
54
57
  listen (3.2.1)
55
58
  rb-fsevent (~> 0.10, >= 0.10.3)
56
59
  rb-inotify (~> 0.9, >= 0.9.10)
57
60
  lumberjack (1.2.5)
58
61
  method_source (1.0.0)
59
- minitest (5.14.1)
62
+ minitest (5.14.3)
60
63
  nenv (0.3.0)
61
64
  notiffany (0.1.3)
62
65
  nenv (~> 0.1)
63
66
  shellany (~> 0.0)
64
- parallel (1.19.1)
65
- parser (2.7.1.3)
66
- ast (~> 2.4.0)
67
+ parallel (1.20.1)
68
+ parser (3.0.0.0)
69
+ ast (~> 2.4.1)
67
70
  pry (0.13.1)
68
71
  coderay (~> 1.1)
69
72
  method_source (~> 1.0)
@@ -71,49 +74,55 @@ GEM
71
74
  byebug (~> 11.0)
72
75
  pry (~> 0.13.0)
73
76
  rainbow (3.0.0)
74
- rake (13.0.1)
77
+ rake (13.0.3)
75
78
  rb-fsevent (0.10.4)
76
79
  rb-inotify (0.10.1)
77
80
  ffi (~> 1.0)
78
- regexp_parser (1.7.1)
81
+ regexp_parser (2.0.3)
79
82
  rexml (3.2.4)
80
- rspec (3.9.0)
81
- rspec-core (~> 3.9.0)
82
- rspec-expectations (~> 3.9.0)
83
- rspec-mocks (~> 3.9.0)
84
- rspec-core (3.9.2)
85
- rspec-support (~> 3.9.3)
86
- rspec-expectations (3.9.2)
83
+ rspec (3.10.0)
84
+ rspec-core (~> 3.10.0)
85
+ rspec-expectations (~> 3.10.0)
86
+ rspec-mocks (~> 3.10.0)
87
+ rspec-core (3.10.1)
88
+ rspec-support (~> 3.10.0)
89
+ rspec-expectations (3.10.1)
87
90
  diff-lcs (>= 1.2.0, < 2.0)
88
- rspec-support (~> 3.9.0)
89
- rspec-mocks (3.9.1)
91
+ rspec-support (~> 3.10.0)
92
+ rspec-mocks (3.10.1)
90
93
  diff-lcs (>= 1.2.0, < 2.0)
91
- rspec-support (~> 3.9.0)
92
- rspec-support (3.9.3)
93
- rubocop (0.85.1)
94
+ rspec-support (~> 3.10.0)
95
+ rspec-support (3.10.1)
96
+ rubocop (1.8.1)
94
97
  parallel (~> 1.10)
95
- parser (>= 2.7.0.1)
98
+ parser (>= 3.0.0.0)
96
99
  rainbow (>= 2.2.2, < 4.0)
97
- regexp_parser (>= 1.7)
100
+ regexp_parser (>= 1.8, < 3.0)
98
101
  rexml
99
- rubocop-ast (>= 0.0.3)
102
+ rubocop-ast (>= 1.2.0, < 2.0)
100
103
  ruby-progressbar (~> 1.7)
101
- unicode-display_width (>= 1.4.0, < 2.0)
102
- rubocop-ast (0.0.3)
103
- parser (>= 2.7.0.1)
104
- ruby-progressbar (1.10.1)
104
+ unicode-display_width (>= 1.4.0, < 3.0)
105
+ rubocop-ast (1.4.0)
106
+ parser (>= 2.7.1.5)
107
+ rubocop-performance (1.9.2)
108
+ rubocop (>= 0.90.0, < 2.0)
109
+ rubocop-ast (>= 0.4.0)
110
+ rubocop-rspec (2.1.0)
111
+ rubocop (~> 1.0)
112
+ rubocop-ast (>= 1.1.0)
113
+ ruby-progressbar (1.11.0)
105
114
  shellany (0.0.1)
106
- simplecov (0.18.5)
115
+ simplecov (0.21.2)
107
116
  docile (~> 1.1)
108
117
  simplecov-html (~> 0.11)
109
- simplecov-html (0.12.2)
118
+ simplecov_json_formatter (~> 0.1)
119
+ simplecov-html (0.12.3)
120
+ simplecov_json_formatter (0.1.2)
110
121
  thor (1.0.1)
111
- thread_safe (0.3.6)
112
- tzinfo (1.2.7)
113
- thread_safe (~> 0.1)
114
- unicode-display_width (1.7.0)
115
- url (0.3.2)
116
- zeitwerk (2.3.0)
122
+ tzinfo (2.0.4)
123
+ concurrent-ruby (~> 1.0)
124
+ unicode-display_width (2.0.0)
125
+ zeitwerk (2.4.2)
117
126
 
118
127
  PLATFORMS
119
128
  ruby
@@ -126,7 +135,10 @@ DEPENDENCIES
126
135
  rake
127
136
  rspec
128
137
  rubocop
138
+ rubocop-performance
139
+ rubocop-rspec
140
+ runger_style!
129
141
  shaped!
130
142
 
131
143
  BUNDLED WITH
132
- 2.1.2
144
+ 2.1.4
data/README.md CHANGED
@@ -1,5 +1,4 @@
1
1
  [![codecov](https://codecov.io/gh/davidrunger/shaped/branch/master/graph/badge.svg)](https://codecov.io/gh/davidrunger/shaped)
2
- [![Build Status](https://travis-ci.com/davidrunger/shaped.svg?branch=master)](https://travis-ci.com/davidrunger/shaped)
3
2
  [![Dependabot Status](https://api.dependabot.com/badges/status?host=github&repo=davidrunger/shaped)](https://dependabot.com)
4
3
  [![Gem Version](https://badge.fury.io/rb/shaped.svg)](https://badge.fury.io/rb/shaped)
5
4
 
@@ -21,15 +20,17 @@ Validate the "shape" of Ruby objects!
21
20
  * [Shaped::Shapes::Array](#shapedshapesarray)
22
21
  * [Shaped::Shapes::Class](#shapedshapesclass)
23
22
  * [ActiveModel validations](#activemodel-validations)
23
+ * [Shaped::Shapes::Method](#shapedshapesmethod)
24
24
  * [Shaped::Shapes::Callable](#shapedshapescallable)
25
25
  * [Shaped::Shapes::Equality](#shapedshapesequality)
26
- * [Shaped::Shapes::Or](#shapedshapesor)
26
+ * [Shaped::Shapes::Any](#shapedshapesany)
27
+ * [Shaped::Shapes::All](#shapedshapesall)
27
28
  * [#to_s](#to_s)
28
29
  * [Development](#development)
29
30
  * [For maintainers](#for-maintainers)
30
31
  * [License](#license)
31
32
 
32
- <!-- Added by: david, at: Fri Jun 19 21:29:30 PDT 2020 -->
33
+ <!-- Added by: david, at: Wed Jun 24 13:56:49 PDT 2020 -->
33
34
 
34
35
  <!--te-->
35
36
 
@@ -91,7 +92,7 @@ types (all of which inherit from `Shaped::Shape`):
91
92
  1. `Shaped::Shapes::Class`
92
93
  1. `Shaped::Shapes::Callable`
93
94
  1. `Shaped::Shapes::Equality`
94
- 1. `Shaped::Shapes::Or`
95
+ 1. `Shaped::Shapes::Any`
95
96
 
96
97
  Examples illustrating the use of each shape type are below.
97
98
 
@@ -204,6 +205,21 @@ shape.matched_by?('a@b.c') # too short
204
205
  # => false
205
206
  ```
206
207
 
208
+ ## Shaped::Shapes::Method
209
+
210
+ This shape allows specifying a method name that, when called upon a test object, must return a
211
+ truthy value in order for `matched_by?` to be true.
212
+
213
+ ```rb
214
+ shape = Shaped::Shape(:odd?)
215
+
216
+ shape.matched_by?(55)
217
+ # => true
218
+
219
+ shape.matched_by?(60)
220
+ # => false
221
+ ```
222
+
207
223
  ## Shaped::Shapes::Callable
208
224
 
209
225
  This shape is very powerful if you need a very customized shape definition; you can define any
@@ -223,6 +239,23 @@ shape.matched_by?(5) # fails the `#even?` check
223
239
  shape.matched_by?(10) # fails the `#cover?` check (10 is too high)
224
240
  # => false
225
241
  ```
242
+
243
+ If you'd like to provide a named method rather than an anonymous proc/lambda, you can do that, too:
244
+
245
+ ```rb
246
+ def number_is_greater_than_thirty?(number)
247
+ number > 30
248
+ end
249
+
250
+ shape = Shaped::Shape(method(:number_is_greater_than_thirty?))
251
+
252
+ shape.matched_by?(31)
253
+ # => true
254
+
255
+ shape.matched_by?(29)
256
+ # => false
257
+ ```
258
+
226
259
  You can also provide an instance of a custom class that implements a `#call` instance method:
227
260
 
228
261
  ```rb
@@ -282,7 +315,7 @@ shape.matched_by?(verification_code: '321cba', new_role: 'SuperAdmin')
282
315
  # => false
283
316
  ```
284
317
 
285
- ## Shaped::Shapes::Or
318
+ ## Shaped::Shapes::Any
286
319
 
287
320
  This shape is used behind the scenes to build "compound matchers", such as an Array shape that
288
321
  allows multiple different classes:
@@ -299,7 +332,7 @@ shape.matched_by?([0.333, 55])
299
332
  # => false
300
333
  ```
301
334
 
302
- You can build an `Or` shape by invoking the `Shaped::Shape` constructor with more than one argument.
335
+ You can build an `Any` shape by invoking the `Shaped::Shape` constructor with more than one argument.
303
336
  Below is a (rather artificial) example illustrating this. To match this `shape`, an object must be
304
337
  either greater than zero OR an Integer (or both).
305
338
 
@@ -316,6 +349,23 @@ shape.matched_by?(-11.5) # it's neither greater than 0 nor an Integer
316
349
  # => false
317
350
  ```
318
351
 
352
+ ## Shaped::Shapes::All
353
+
354
+ This shape can be used to combine multiple checks, all of which must be true for a test object in
355
+ order for `#matched_by?` to be true:
356
+
357
+ ```rb
358
+ shape = Shaped::Shapes::All.new(Numeric, ->(number) { number.even? })
359
+ shape.to_s
360
+ # => "Numeric AND Proc test defined at (eval):10"
361
+
362
+ shape.matched_by?(22) # 22 is both a Numeric and `#even?`
363
+ # => true
364
+
365
+ shape.matched_by?(33) # 33 is a Numeric but it's not `#even?`
366
+ # => false
367
+ ```
368
+
319
369
  ## `#to_s`
320
370
 
321
371
  Each Shape type implements a `#to_s` instance method that aims to provide a relatively clear
@@ -17,7 +17,7 @@ ENV['BUNDLE_GEMFILE'] ||= File.expand_path(
17
17
  bundle_binstub = File.expand_path('bundle', __dir__)
18
18
 
19
19
  if File.file?(bundle_binstub)
20
- if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/
20
+ if /This file was generated by Bundler/.match?(File.read(bundle_binstub, 300))
21
21
  load(bundle_binstub)
22
22
  else
23
23
  abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run.
data/bin/guard CHANGED
@@ -17,7 +17,7 @@ ENV['BUNDLE_GEMFILE'] ||= File.expand_path(
17
17
  bundle_binstub = File.expand_path('bundle', __dir__)
18
18
 
19
19
  if File.file?(bundle_binstub)
20
- if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/
20
+ if /This file was generated by Bundler/.match?(File.read(bundle_binstub, 300))
21
21
  load(bundle_binstub)
22
22
  else
23
23
  abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run.
data/bin/rspec CHANGED
@@ -18,7 +18,7 @@ ENV['BUNDLE_GEMFILE'] ||=
18
18
  bundle_binstub = File.expand_path('bundle', __dir__)
19
19
 
20
20
  if File.file?(bundle_binstub)
21
- if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/
21
+ if /This file was generated by Bundler/.match?(File.read(bundle_binstub, 300))
22
22
  load(bundle_binstub)
23
23
  else
24
24
  abort(<<~ERROR)
@@ -14,7 +14,7 @@ ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', Pathname.new(__FILE_
14
14
  bundle_binstub = File.expand_path('bundle', __dir__)
15
15
 
16
16
  if File.file?(bundle_binstub)
17
- if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/
17
+ if /This file was generated by Bundler/.match?(File.read(bundle_binstub, 300))
18
18
  load(bundle_binstub)
19
19
  else
20
20
  abort(<<~ERROR)
@@ -6,14 +6,14 @@ module Shaped::Shapes ; end
6
6
  require 'active_support/all'
7
7
  require 'active_model'
8
8
  require_relative './shaped/shape.rb'
9
- Dir[File.dirname(__FILE__) + '/**/*.rb'].sort.each { |file| require file }
9
+ Dir["#{File.dirname(__FILE__)}/**/*.rb"].sort.each { |file| require file }
10
10
 
11
11
  module Shaped
12
12
  # rubocop:disable Naming/MethodName, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
13
13
  def self.Shape(*shape_descriptions)
14
14
  validation_options = shape_descriptions.extract_options!
15
15
  if shape_descriptions.size >= 2
16
- Shaped::Shapes::Or.new(*shape_descriptions, validation_options)
16
+ Shaped::Shapes::Any.new(*shape_descriptions, validation_options)
17
17
  else
18
18
  # If the shape_descriptions argument list was just one hash, then `extract_options!` would
19
19
  # have removed it, making `shape_descriptions` an empty array, so we need to "restore" the
@@ -30,6 +30,7 @@ module Shaped
30
30
  when Shaped::Shape then shape_description
31
31
  when Hash then Shaped::Shapes::Hash.new(shape_description)
32
32
  when Array then Shaped::Shapes::Array.new(shape_description)
33
+ when Symbol then Shaped::Shapes::Method.new(shape_description)
33
34
  when Class then Shaped::Shapes::Class.new(shape_description, validation_options)
34
35
  else
35
36
  if shape_description.respond_to?(:call)
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Shaped::Shapes::All < Shaped::Shape
4
+ def initialize(*shape_descriptions)
5
+ validation_options = shape_descriptions.extract_options!
6
+ if shape_descriptions.size <= 1
7
+ raise(Shaped::InvalidShapeDescription, <<~ERROR.squish)
8
+ A #{self.class} description must be a list of two or more shape descriptions.
9
+ ERROR
10
+ end
11
+
12
+ @shapes =
13
+ shape_descriptions.map do |description|
14
+ Shaped::Shape(description, validation_options)
15
+ end
16
+ end
17
+
18
+ def matched_by?(object)
19
+ @shapes.all? { |shape| shape.matched_by?(object) }
20
+ end
21
+
22
+ def to_s
23
+ @shapes.map(&:to_s).join(' AND ')
24
+ end
25
+ end
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- class Shaped::Shapes::Or < Shaped::Shape
3
+ class Shaped::Shapes::Any < Shaped::Shape
4
4
  def initialize(*shape_descriptions)
5
5
  validation_options = shape_descriptions.extract_options!
6
6
  if shape_descriptions.size <= 1
@@ -11,6 +11,7 @@ class Shaped::Shapes::Callable < Shaped::Shape
11
11
 
12
12
  def to_s
13
13
  case @callable
14
+ when Method then "Method defined at #{@callable.source_location.map(&:to_s).join(':')}"
14
15
  when Proc then "Proc test defined at #{@callable.source_location.map(&:to_s).join(':')}"
15
16
  else "#call test defined at #{@callable.method(:call).source_location.map(&:to_s).join(':')}"
16
17
  end
@@ -34,13 +34,6 @@ class Shaped::Shapes::Class < Shaped::Shape
34
34
  attr_accessor :value
35
35
 
36
36
  validates :value, validations
37
-
38
- class << self
39
- # ActiveModel requires the class to have a `name`
40
- def name
41
- 'Shaped::Shapes::Class::AnonymousValidator'
42
- end
43
- end
44
37
  end
45
38
  end
46
39
 
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Shaped::Shapes::Method < Shaped::Shape
4
+ def initialize(method_name)
5
+ @method_name = method_name
6
+ end
7
+
8
+ def matched_by?(object)
9
+ !!object.public_send(@method_name)
10
+ end
11
+
12
+ def to_s
13
+ "object returning truthy for ##{@method_name}"
14
+ end
15
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Shaped
4
- VERSION = '0.6.4'
4
+ VERSION = '0.8.0'
5
5
  end
@@ -12,7 +12,7 @@ Gem::Specification.new do |spec|
12
12
  spec.description = 'Validate the "shape" of Ruby objects.'
13
13
  spec.homepage = 'https://github.com/davidrunger/shaped'
14
14
  spec.license = 'MIT'
15
- spec.required_ruby_version = Gem::Requirement.new('>= 2.3.0')
15
+ spec.required_ruby_version = Gem::Requirement.new('>= 2.7.0')
16
16
 
17
17
  spec.metadata['homepage_uri'] = spec.homepage
18
18
  spec.metadata['source_code_uri'] = 'https://github.com/davidrunger/shaped'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: shaped
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.4
4
+ version: 0.8.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - David Runger
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-06-22 00:00:00.000000000 Z
11
+ date: 2021-02-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activemodel
@@ -45,11 +45,11 @@ executables: []
45
45
  extensions: []
46
46
  extra_rdoc_files: []
47
47
  files:
48
+ - ".github/workflows/ruby.yml"
48
49
  - ".gitignore"
49
50
  - ".rspec"
50
51
  - ".rubocop.yml"
51
52
  - ".ruby-version"
52
- - ".travis.yml"
53
53
  - CHANGELOG.md
54
54
  - Gemfile
55
55
  - Gemfile.lock
@@ -65,12 +65,14 @@ files:
65
65
  - bin/setup
66
66
  - lib/shaped.rb
67
67
  - lib/shaped/shape.rb
68
+ - lib/shaped/shapes/all.rb
69
+ - lib/shaped/shapes/any.rb
68
70
  - lib/shaped/shapes/array.rb
69
71
  - lib/shaped/shapes/callable.rb
70
72
  - lib/shaped/shapes/class.rb
71
73
  - lib/shaped/shapes/equality.rb
72
74
  - lib/shaped/shapes/hash.rb
73
- - lib/shaped/shapes/or.rb
75
+ - lib/shaped/shapes/method.rb
74
76
  - lib/shaped/version.rb
75
77
  - shaped.gemspec
76
78
  homepage: https://github.com/davidrunger/shaped
@@ -80,7 +82,7 @@ metadata:
80
82
  homepage_uri: https://github.com/davidrunger/shaped
81
83
  source_code_uri: https://github.com/davidrunger/shaped
82
84
  changelog_uri: https://github.com/davidrunger/shaped/blob/master/CHANGELOG.md
83
- post_install_message:
85
+ post_install_message:
84
86
  rdoc_options: []
85
87
  require_paths:
86
88
  - lib
@@ -88,15 +90,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
88
90
  requirements:
89
91
  - - ">="
90
92
  - !ruby/object:Gem::Version
91
- version: 2.3.0
93
+ version: 2.7.0
92
94
  required_rubygems_version: !ruby/object:Gem::Requirement
93
95
  requirements:
94
96
  - - ">="
95
97
  - !ruby/object:Gem::Version
96
98
  version: '0'
97
99
  requirements: []
98
- rubygems_version: 3.1.2
99
- signing_key:
100
+ rubygems_version: 3.1.4
101
+ signing_key:
100
102
  specification_version: 4
101
103
  summary: Validate the "shape" of Ruby objects.
102
104
  test_files: []
@@ -1,14 +0,0 @@
1
- ---
2
- language: ruby
3
- os: linux
4
- dist: bionic
5
- cache: bundler
6
- rvm:
7
- - 2.7.0
8
- notifications:
9
- email:
10
- on_success: never
11
- on_failure: always
12
- script:
13
- - bin/rubocop $(git ls-tree -r HEAD --name-only) --force-exclusion --format clang
14
- - bin/rspec