shaped 0.6.2 → 0.7.2

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: b652bad6c74a2a070b673bd751e54809d2164f27b296fb24925dbc83c5906921
4
- data.tar.gz: 24b055aa823685eaa4a7e94d5b4e7a2a0f0ba9606c95cf4614e380c6d4869ab0
3
+ metadata.gz: c17eca1a62726455801d77acc63877eadf199ad58ceba789262917f93a8fd56a
4
+ data.tar.gz: 723367acf980be0ac1e427aa792825f9e4b513b917e8929ed41f16b02ee67d5c
5
5
  SHA512:
6
- metadata.gz: 017fa0101043d18e9f9421f01d6275f22aedc4ac76323c43c359f3bded23f1e71fde3156877eb7ee1998370d67f7060d16582ac8b78ac435f0c2aaf7e7c5af39
7
- data.tar.gz: 2d1c6c3f4199eb179e39511d6590dad3166d93506790b8b133846be707ced15c6c5f13ad33424319ce0a8a8b635d904f4c3bbedf020e166f5a400e55c6838939
6
+ metadata.gz: 6232fb1b87dca1f98184ef631444c05b9a74be191ed82d12af8263b30dad6df8826b91eb27ad9ed85543fb65f9a19c2900cd925cde0730b582b7806be17ee491
7
+ data.tar.gz: 53b0b230f2b1fe6f0b13c1cfd624ec2f62284ad7aafb4d60bf2625fc33c8f2d83cdd2cc6bb657eff88166ea4cdb171de4adcff76aabedd8de079db022ff7e160
@@ -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'
@@ -10,5 +10,5 @@ notifications:
10
10
  on_success: never
11
11
  on_failure: always
12
12
  script:
13
- - bin/rubocop $(git ls-tree -r HEAD --name-only) --force-exclusion --format clang
13
+ - bin/rubocop --format clang
14
14
  - bin/rspec
@@ -1,3 +1,33 @@
1
+ ## v0.7.2 (2020-07-13)
2
+ ### Dependencies
3
+ - Bump `rubocop` to 0.88.0 and `runger_style` to 0.2.3
4
+
5
+ ## v0.7.1 (2020-07-02)
6
+ ### Internal
7
+ - Source Rubocop rules/config from `runger_style` gem
8
+
9
+ ## v0.7.0 (2020-06-24)
10
+ ### BREAKING CHANGES
11
+ - Rename the `Or` shape to `Any`
12
+ - Add a `Method` shape (where the shape description is the name of a method which, when called on a
13
+ test object, must return a truthy value). This is a breaking change because the `Shaped::Shape`
14
+ constructor will now return an instance of `Shaped::Shapes::Method` rather than
15
+ `Shaped::Shapes::Equality` when called with a Symbol argument.
16
+
17
+ ### Added
18
+ - Add an `All` shape (w/ multiple sub-shapes, all of which must be matched)
19
+
20
+ ## v0.6.4 (2020-06-22)
21
+ ### Fixed
22
+ - Make it possible to specify optional keys in a Hash shape (using an `Or` shape as the value)
23
+
24
+ ### Docs
25
+ - Remove explicit `git push` from release instructions
26
+
27
+ ## v0.6.3 (2020-06-21)
28
+ ### Docs
29
+ - Add badges for Dependabot status and RubyGems version
30
+
1
31
  ## v0.6.2 (2020-06-21)
2
32
  ### Docs
3
33
  - Update README.md and `bin/release` to reflect release via RubyGems
@@ -81,7 +111,7 @@
81
111
  `Shaped::Shapes::Hash`):
82
112
  1. `Shaped::Shapes::Class`
83
113
  2. `Shaped::Shapes::Equality`
84
- 3. `Shaped::Shapes::Or`
114
+ 3. `Shaped::Shapes::Any`
85
115
  - All hashes and arrays in shape definitions are parsed "recursively" as shape definitions. For
86
116
  example, instead of:
87
117
 
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,10 +7,16 @@ 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: 3d13e2985df67c4b9ce60c6039433ffa14ea87c9
13
+ specs:
14
+ runger_style (0.2.3)
15
+
10
16
  PATH
11
17
  remote: .
12
18
  specs:
13
- shaped (0.6.2)
19
+ shaped (0.7.2)
14
20
  activemodel (~> 6.0)
15
21
  activesupport (~> 6.0)
16
22
 
@@ -28,11 +34,12 @@ GEM
28
34
  amazing_print (1.2.1)
29
35
  ast (2.4.1)
30
36
  byebug (11.1.3)
31
- codecov (0.1.17)
37
+ codecov (0.2.0)
38
+ colorize
32
39
  json
33
40
  simplecov
34
- url
35
41
  coderay (1.1.3)
42
+ colorize (0.8.1)
36
43
  concurrent-ruby (1.1.6)
37
44
  diff-lcs (1.3)
38
45
  docile (1.3.2)
@@ -50,7 +57,7 @@ GEM
50
57
  guard-compat (1.2.1)
51
58
  i18n (1.8.3)
52
59
  concurrent-ruby (~> 1.0)
53
- json (2.3.0)
60
+ json (2.3.1)
54
61
  listen (3.2.1)
55
62
  rb-fsevent (~> 0.10, >= 0.10.3)
56
63
  rb-inotify (~> 0.9, >= 0.9.10)
@@ -61,9 +68,9 @@ GEM
61
68
  notiffany (0.1.3)
62
69
  nenv (~> 0.1)
63
70
  shellany (~> 0.0)
64
- parallel (1.19.1)
65
- parser (2.7.1.3)
66
- ast (~> 2.4.0)
71
+ parallel (1.19.2)
72
+ parser (2.7.1.4)
73
+ ast (~> 2.4.1)
67
74
  pry (0.13.1)
68
75
  coderay (~> 1.1)
69
76
  method_source (~> 1.0)
@@ -71,7 +78,7 @@ GEM
71
78
  byebug (~> 11.0)
72
79
  pry (~> 0.13.0)
73
80
  rainbow (3.0.0)
74
- rake (12.3.3)
81
+ rake (13.0.1)
75
82
  rb-fsevent (0.10.4)
76
83
  rb-inotify (0.10.1)
77
84
  ffi (~> 1.0)
@@ -90,30 +97,34 @@ GEM
90
97
  diff-lcs (>= 1.2.0, < 2.0)
91
98
  rspec-support (~> 3.9.0)
92
99
  rspec-support (3.9.3)
93
- rubocop (0.85.1)
100
+ rubocop (0.88.0)
94
101
  parallel (~> 1.10)
95
- parser (>= 2.7.0.1)
102
+ parser (>= 2.7.1.1)
96
103
  rainbow (>= 2.2.2, < 4.0)
97
104
  regexp_parser (>= 1.7)
98
105
  rexml
99
- rubocop-ast (>= 0.0.3)
106
+ rubocop-ast (>= 0.1.0, < 1.0)
100
107
  ruby-progressbar (~> 1.7)
101
108
  unicode-display_width (>= 1.4.0, < 2.0)
102
- rubocop-ast (0.0.3)
109
+ rubocop-ast (0.1.0)
103
110
  parser (>= 2.7.0.1)
111
+ rubocop-performance (1.7.0)
112
+ rubocop (>= 0.82.0)
113
+ rubocop-rspec (1.42.0)
114
+ rubocop (>= 0.87.0)
104
115
  ruby-progressbar (1.10.1)
105
116
  shellany (0.0.1)
106
- simplecov (0.18.5)
117
+ simplecov (0.17.1)
107
118
  docile (~> 1.1)
108
- simplecov-html (~> 0.11)
109
- simplecov-html (0.12.2)
119
+ json (>= 1.8, < 3)
120
+ simplecov-html (~> 0.10.0)
121
+ simplecov-html (0.10.2)
110
122
  thor (1.0.1)
111
123
  thread_safe (0.3.6)
112
124
  tzinfo (1.2.7)
113
125
  thread_safe (~> 0.1)
114
126
  unicode-display_width (1.7.0)
115
- url (0.3.2)
116
- zeitwerk (2.3.0)
127
+ zeitwerk (2.3.1)
117
128
 
118
129
  PLATFORMS
119
130
  ruby
@@ -126,6 +137,9 @@ DEPENDENCIES
126
137
  rake
127
138
  rspec
128
139
  rubocop
140
+ rubocop-performance
141
+ rubocop-rspec
142
+ runger_style!
129
143
  shaped!
130
144
 
131
145
  BUNDLED WITH
data/README.md CHANGED
@@ -1,5 +1,7 @@
1
1
  [![codecov](https://codecov.io/gh/davidrunger/shaped/branch/master/graph/badge.svg)](https://codecov.io/gh/davidrunger/shaped)
2
2
  [![Build Status](https://travis-ci.com/davidrunger/shaped.svg?branch=master)](https://travis-ci.com/davidrunger/shaped)
3
+ [![Dependabot Status](https://api.dependabot.com/badges/status?host=github&repo=davidrunger/shaped)](https://dependabot.com)
4
+ [![Gem Version](https://badge.fury.io/rb/shaped.svg)](https://badge.fury.io/rb/shaped)
3
5
 
4
6
  # Shaped
5
7
 
@@ -19,15 +21,17 @@ Validate the "shape" of Ruby objects!
19
21
  * [Shaped::Shapes::Array](#shapedshapesarray)
20
22
  * [Shaped::Shapes::Class](#shapedshapesclass)
21
23
  * [ActiveModel validations](#activemodel-validations)
24
+ * [Shaped::Shapes::Method](#shapedshapesmethod)
22
25
  * [Shaped::Shapes::Callable](#shapedshapescallable)
23
26
  * [Shaped::Shapes::Equality](#shapedshapesequality)
24
- * [Shaped::Shapes::Or](#shapedshapesor)
27
+ * [Shaped::Shapes::Any](#shapedshapesany)
28
+ * [Shaped::Shapes::All](#shapedshapesall)
25
29
  * [#to_s](#to_s)
26
30
  * [Development](#development)
27
31
  * [For maintainers](#for-maintainers)
28
32
  * [License](#license)
29
33
 
30
- <!-- Added by: david, at: Fri Jun 19 21:29:30 PDT 2020 -->
34
+ <!-- Added by: david, at: Wed Jun 24 13:56:49 PDT 2020 -->
31
35
 
32
36
  <!--te-->
33
37
 
@@ -89,7 +93,7 @@ types (all of which inherit from `Shaped::Shape`):
89
93
  1. `Shaped::Shapes::Class`
90
94
  1. `Shaped::Shapes::Callable`
91
95
  1. `Shaped::Shapes::Equality`
92
- 1. `Shaped::Shapes::Or`
96
+ 1. `Shaped::Shapes::Any`
93
97
 
94
98
  Examples illustrating the use of each shape type are below.
95
99
 
@@ -202,6 +206,21 @@ shape.matched_by?('a@b.c') # too short
202
206
  # => false
203
207
  ```
204
208
 
209
+ ## Shaped::Shapes::Method
210
+
211
+ This shape allows specifying a method name that, when called upon a test object, must return a
212
+ truthy value in order for `matched_by?` to be true.
213
+
214
+ ```rb
215
+ shape = Shaped::Shape(:odd?)
216
+
217
+ shape.matched_by?(55)
218
+ # => true
219
+
220
+ shape.matched_by?(60)
221
+ # => false
222
+ ```
223
+
205
224
  ## Shaped::Shapes::Callable
206
225
 
207
226
  This shape is very powerful if you need a very customized shape definition; you can define any
@@ -280,7 +299,7 @@ shape.matched_by?(verification_code: '321cba', new_role: 'SuperAdmin')
280
299
  # => false
281
300
  ```
282
301
 
283
- ## Shaped::Shapes::Or
302
+ ## Shaped::Shapes::Any
284
303
 
285
304
  This shape is used behind the scenes to build "compound matchers", such as an Array shape that
286
305
  allows multiple different classes:
@@ -297,7 +316,7 @@ shape.matched_by?([0.333, 55])
297
316
  # => false
298
317
  ```
299
318
 
300
- You can build an `Or` shape by invoking the `Shaped::Shape` constructor with more than one argument.
319
+ You can build an `Any` shape by invoking the `Shaped::Shape` constructor with more than one argument.
301
320
  Below is a (rather artificial) example illustrating this. To match this `shape`, an object must be
302
321
  either greater than zero OR an Integer (or both).
303
322
 
@@ -314,6 +333,23 @@ shape.matched_by?(-11.5) # it's neither greater than 0 nor an Integer
314
333
  # => false
315
334
  ```
316
335
 
336
+ ## Shaped::Shapes::All
337
+
338
+ This shape can be used to combine multiple checks, all of which must be true for a test object in
339
+ order for `#matched_by?` to be true:
340
+
341
+ ```rb
342
+ shape = Shaped::Shapes::All.new(Numeric, ->(number) { number.even? })
343
+ shape.to_s
344
+ # => "Numeric AND Proc test defined at (eval):10"
345
+
346
+ shape.matched_by?(22) # 22 is both a Numeric and `#even?`
347
+ # => true
348
+
349
+ shape.matched_by?(33) # 33 is a Numeric but it's not `#even?`
350
+ # => false
351
+ ```
352
+
317
353
  ## `#to_s`
318
354
 
319
355
  Each Shape type implements a `#to_s` instance method that aims to provide a relatively clear
@@ -356,8 +392,7 @@ To release a new version:
356
392
  3. update the version number in `version.rb`
357
393
  4. `bundle install` (which will update `Gemfile.lock`)
358
394
  5. commit the changes with a message like `Prepare to release v0.1.1`
359
- 6. push the changes to `origin/master` (GitHub) via `git push`
360
- 7. run `bin/release` (which will create a git tag for the version, push git commits and
395
+ 6. run `bin/release` (which will create a git tag for the version, push git commits and
361
396
  tags to GitHub, and push the gem to RubyGems)
362
397
 
363
398
  # License
@@ -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)
@@ -13,7 +13,7 @@ module Shaped
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
@@ -27,8 +27,10 @@ module Shaped
27
27
  end
28
28
 
29
29
  case shape_description
30
+ when Shaped::Shape then shape_description
30
31
  when Hash then Shaped::Shapes::Hash.new(shape_description)
31
32
  when Array then Shaped::Shapes::Array.new(shape_description)
33
+ when Symbol then Shaped::Shapes::Method.new(shape_description)
32
34
  when Class then Shaped::Shapes::Class.new(shape_description, validation_options)
33
35
  else
34
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
@@ -12,9 +12,6 @@ class Shaped::Shapes::Hash < Shaped::Shape
12
12
  def matched_by?(hash)
13
13
  return false if !hash.is_a?(Hash)
14
14
 
15
- missing_keys = expected_keys - hash.keys
16
- return false if missing_keys.any?
17
-
18
15
  @hash_description.all? do |key, expected_value_shape|
19
16
  expected_value_shape.matched_by?(hash[key])
20
17
  end
@@ -28,10 +25,4 @@ class Shaped::Shapes::Hash < Shaped::Shape
28
25
 
29
26
  "{ #{printable_shape_description} }"
30
27
  end
31
-
32
- private
33
-
34
- def expected_keys
35
- @hash_description.keys
36
- end
37
28
  end
@@ -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.2'
4
+ VERSION = '0.7.2'
5
5
  end
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.2
4
+ version: 0.7.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - David Runger
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-06-22 00:00:00.000000000 Z
11
+ date: 2020-07-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activemodel
@@ -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