shaped 0.6.1 → 0.7.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: 21fd29373698c83855364dd4e9dec36d55d99f5ed4f7c3922d95241f8198dc7b
4
- data.tar.gz: 0ec1c71a7d37bc7a6a294f240e9a570a348b1fdee8364fbd405f4d79cd38ddaf
3
+ metadata.gz: b3fda7351bf12258e204d3b16b43728f2d42daeee4cf67a022ad0b6bb2a46c70
4
+ data.tar.gz: 72866461bd6422824d424f2593659d89eab25b66f9f834ecec11aae690f4d5fd
5
5
  SHA512:
6
- metadata.gz: 92f598d534e5162093a978d4787d4f428f874ccacb2390d925dfe66de94e71a8f17933aa2b13ff258d66d15f72a04789e4355c72dc27ef60542cf81d2db5d52c
7
- data.tar.gz: cd4a04e7b0485a8e420f017f905b5568eab443482b95b36057cc4a0c0536e01f871363439665936042e52e7a724e9dc69132266e07d7de0993c2a3e84f0fc884
6
+ metadata.gz: 154eb78ea527ab740be7bea30b6dec6687706707e5c32da17fc68bd0095137d06b6cc18c202358e86967c82fdcb0b983eed25ba19cdffc049138f99f69f18ab7
7
+ data.tar.gz: 6f94a4300de38ad85718ce7f7e953ebc6ed131bb0a77973633a7bf88ced9db1135fa7d20b64da416f77923f409d13ad16119a3673e58fe295679cbc9e5173e58
@@ -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.1 (2020-07-02)
2
+ ### Internal
3
+ - Source Rubocop rules/config from `runger_style` gem
4
+
5
+ ## v0.7.0 (2020-06-24)
6
+ ### BREAKING CHANGES
7
+ - Rename the `Or` shape to `Any`
8
+ - Add a `Method` shape (where the shape description is the name of a method which, when called on a
9
+ test object, must return a truthy value). This is a breaking change because the `Shaped::Shape`
10
+ constructor will now return an instance of `Shaped::Shapes::Method` rather than
11
+ `Shaped::Shapes::Equality` when called with a Symbol argument.
12
+
13
+ ### Added
14
+ - Add an `All` shape (w/ multiple sub-shapes, all of which must be matched)
15
+
16
+ ## v0.6.4 (2020-06-22)
17
+ ### Fixed
18
+ - Make it possible to specify optional keys in a Hash shape (using an `Or` shape as the value)
19
+
20
+ ### Docs
21
+ - Remove explicit `git push` from release instructions
22
+
23
+ ## v0.6.3 (2020-06-21)
24
+ ### Docs
25
+ - Add badges for Dependabot status and RubyGems version
26
+
27
+ ## v0.6.2 (2020-06-21)
28
+ ### Docs
29
+ - Update README.md and `bin/release` to reflect release via RubyGems
30
+
1
31
  ## v0.6.1 (2020-06-20)
2
32
  ### Docs
3
33
  - Add Travis build status badge to README.md
@@ -77,7 +107,7 @@
77
107
  `Shaped::Shapes::Hash`):
78
108
  1. `Shaped::Shapes::Class`
79
109
  2. `Shaped::Shapes::Equality`
80
- 3. `Shaped::Shapes::Or`
110
+ 3. `Shaped::Shapes::Any`
81
111
  - All hashes and arrays in shape definitions are parsed "recursively" as shape definitions. For
82
112
  example, instead of:
83
113
 
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: 6aef7c7978c9b5306e518c18a067e2fdad2c8da1
13
+ specs:
14
+ runger_style (0.2.1)
15
+
10
16
  PATH
11
17
  remote: .
12
18
  specs:
13
- shaped (0.6.1)
19
+ shaped (0.7.1)
14
20
  activemodel (~> 6.0)
15
21
  activesupport (~> 6.0)
16
22
 
@@ -61,9 +67,9 @@ GEM
61
67
  notiffany (0.1.3)
62
68
  nenv (~> 0.1)
63
69
  shellany (~> 0.0)
64
- parallel (1.19.1)
65
- parser (2.7.1.3)
66
- ast (~> 2.4.0)
70
+ parallel (1.19.2)
71
+ parser (2.7.1.4)
72
+ ast (~> 2.4.1)
67
73
  pry (0.13.1)
68
74
  coderay (~> 1.1)
69
75
  method_source (~> 1.0)
@@ -71,7 +77,7 @@ GEM
71
77
  byebug (~> 11.0)
72
78
  pry (~> 0.13.0)
73
79
  rainbow (3.0.0)
74
- rake (12.3.3)
80
+ rake (13.0.1)
75
81
  rb-fsevent (0.10.4)
76
82
  rb-inotify (0.10.1)
77
83
  ffi (~> 1.0)
@@ -90,17 +96,21 @@ GEM
90
96
  diff-lcs (>= 1.2.0, < 2.0)
91
97
  rspec-support (~> 3.9.0)
92
98
  rspec-support (3.9.3)
93
- rubocop (0.85.1)
99
+ rubocop (0.86.0)
94
100
  parallel (~> 1.10)
95
101
  parser (>= 2.7.0.1)
96
102
  rainbow (>= 2.2.2, < 4.0)
97
103
  regexp_parser (>= 1.7)
98
104
  rexml
99
- rubocop-ast (>= 0.0.3)
105
+ rubocop-ast (>= 0.0.3, < 1.0)
100
106
  ruby-progressbar (~> 1.7)
101
107
  unicode-display_width (>= 1.4.0, < 2.0)
102
108
  rubocop-ast (0.0.3)
103
109
  parser (>= 2.7.0.1)
110
+ rubocop-performance (1.6.1)
111
+ rubocop (>= 0.71.0)
112
+ rubocop-rspec (1.40.0)
113
+ rubocop (>= 0.68.1)
104
114
  ruby-progressbar (1.10.1)
105
115
  shellany (0.0.1)
106
116
  simplecov (0.18.5)
@@ -113,7 +123,7 @@ GEM
113
123
  thread_safe (~> 0.1)
114
124
  unicode-display_width (1.7.0)
115
125
  url (0.3.2)
116
- zeitwerk (2.3.0)
126
+ zeitwerk (2.3.1)
117
127
 
118
128
  PLATFORMS
119
129
  ruby
@@ -126,6 +136,9 @@ DEPENDENCIES
126
136
  rake
127
137
  rspec
128
138
  rubocop
139
+ rubocop-performance
140
+ rubocop-rspec
141
+ runger_style!
129
142
  shaped!
130
143
 
131
144
  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
 
@@ -41,11 +45,10 @@ useful), but for now supporting `active_actions` is `shaped`'s *raison d'être*.
41
45
 
42
46
  # Installation
43
47
 
44
- Add the gem to your application's `Gemfile`. Because the gem is not released via RubyGems, you will
45
- need to install it from GitHub.
48
+ Add the gem to your application's `Gemfile`:
46
49
 
47
50
  ```rb
48
- gem 'shaped', git: 'https://github.com/davidrunger/shaped.git'
51
+ gem 'shaped'
49
52
  ```
50
53
 
51
54
  And then execute:
@@ -55,11 +58,10 @@ $ bundle install
55
58
  ```
56
59
 
57
60
  If you want to install the gem on your system independent of a project with a `Gemfile`, then you
58
- can easily do so via [`specific_install`](https://github.com/rdp/specific_install):
61
+ can execute
59
62
 
60
63
  ```
61
- $ gem install specific_install
62
- $ gem specific_install davidrunger/shaped
64
+ $ gem install shaped
63
65
  ```
64
66
 
65
67
  # Usage
@@ -91,7 +93,7 @@ types (all of which inherit from `Shaped::Shape`):
91
93
  1. `Shaped::Shapes::Class`
92
94
  1. `Shaped::Shapes::Callable`
93
95
  1. `Shaped::Shapes::Equality`
94
- 1. `Shaped::Shapes::Or`
96
+ 1. `Shaped::Shapes::Any`
95
97
 
96
98
  Examples illustrating the use of each shape type are below.
97
99
 
@@ -204,6 +206,21 @@ shape.matched_by?('a@b.c') # too short
204
206
  # => false
205
207
  ```
206
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
+
207
224
  ## Shaped::Shapes::Callable
208
225
 
209
226
  This shape is very powerful if you need a very customized shape definition; you can define any
@@ -282,7 +299,7 @@ shape.matched_by?(verification_code: '321cba', new_role: 'SuperAdmin')
282
299
  # => false
283
300
  ```
284
301
 
285
- ## Shaped::Shapes::Or
302
+ ## Shaped::Shapes::Any
286
303
 
287
304
  This shape is used behind the scenes to build "compound matchers", such as an Array shape that
288
305
  allows multiple different classes:
@@ -299,7 +316,7 @@ shape.matched_by?([0.333, 55])
299
316
  # => false
300
317
  ```
301
318
 
302
- 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.
303
320
  Below is a (rather artificial) example illustrating this. To match this `shape`, an object must be
304
321
  either greater than zero OR an Integer (or both).
305
322
 
@@ -316,6 +333,23 @@ shape.matched_by?(-11.5) # it's neither greater than 0 nor an Integer
316
333
  # => false
317
334
  ```
318
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
+
319
353
  ## `#to_s`
320
354
 
321
355
  Each Shape type implements a `#to_s` instance method that aims to provide a relatively clear
@@ -358,8 +392,8 @@ To release a new version:
358
392
  3. update the version number in `version.rb`
359
393
  4. `bundle install` (which will update `Gemfile.lock`)
360
394
  5. commit the changes with a message like `Prepare to release v0.1.1`
361
- 6. push the changes to `origin/master` (GitHub) via `git push`
362
- 7. run `bin/release`, which will create a git tag for the version and push git commits and tags
395
+ 6. run `bin/release` (which will create a git tag for the version, push git commits and
396
+ tags to GitHub, and push the gem to RubyGems)
363
397
 
364
398
  # License
365
399
 
@@ -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.
@@ -13,4 +13,4 @@ if ! [[ $COMMIT_MESSAGE =~ ^Prepare[[:space:]]to[[:space:]]release[[:space:]]v[0
13
13
  exit 1;
14
14
  fi
15
15
 
16
- bundle exec rake build release:guard_clean release:source_control_push
16
+ bundle exec rake release
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.1'
4
+ VERSION = '0.7.1'
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.1
4
+ version: 0.7.1
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-02 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