contracts 0.13.0 → 0.17

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.
Files changed (42) hide show
  1. checksums.yaml +5 -5
  2. data/.github/workflows/code_style_checks.yaml +36 -0
  3. data/.github/workflows/tests.yaml +41 -0
  4. data/CHANGELOG.markdown +54 -7
  5. data/Gemfile +9 -5
  6. data/LICENSE +23 -0
  7. data/README.md +14 -6
  8. data/Rakefile +5 -6
  9. data/TUTORIAL.md +28 -1
  10. data/contracts.gemspec +9 -1
  11. data/dependabot.yml +20 -0
  12. data/features/basics/pretty-print.feature +241 -0
  13. data/features/support/env.rb +2 -0
  14. data/lib/contracts.rb +64 -19
  15. data/lib/contracts/attrs.rb +26 -0
  16. data/lib/contracts/builtin_contracts.rb +85 -7
  17. data/lib/contracts/call_with.rb +50 -28
  18. data/lib/contracts/core.rb +3 -3
  19. data/lib/contracts/decorators.rb +6 -2
  20. data/lib/contracts/engine.rb +2 -0
  21. data/lib/contracts/engine/base.rb +4 -3
  22. data/lib/contracts/engine/eigenclass.rb +3 -2
  23. data/lib/contracts/engine/target.rb +2 -0
  24. data/lib/contracts/errors.rb +3 -0
  25. data/lib/contracts/formatters.rb +17 -11
  26. data/lib/contracts/invariants.rb +8 -4
  27. data/lib/contracts/method_handler.rb +30 -28
  28. data/lib/contracts/method_reference.rb +4 -2
  29. data/lib/contracts/support.rb +14 -10
  30. data/lib/contracts/validators.rb +6 -2
  31. data/lib/contracts/version.rb +3 -1
  32. data/spec/attrs_spec.rb +119 -0
  33. data/spec/builtin_contracts_spec.rb +155 -97
  34. data/spec/contracts_spec.rb +54 -12
  35. data/spec/fixtures/fixtures.rb +49 -2
  36. data/spec/methods_spec.rb +54 -0
  37. data/spec/override_validators_spec.rb +3 -3
  38. data/spec/ruby_version_specific/contracts_spec_2.0.rb +17 -2
  39. data/spec/ruby_version_specific/contracts_spec_2.1.rb +1 -1
  40. data/spec/validators_spec.rb +1 -1
  41. metadata +22 -10
  42. data/script/cucumber +0 -5
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: e31d0dc3c6a107d0255ab5af8229749e6ce825e6
4
- data.tar.gz: 915617473470b5450ee855605380d7d6552d49a8
2
+ SHA256:
3
+ metadata.gz: cbf4bff58a593998c5902920fff3c0a808ca5eb97ec9cad3646df370435421c7
4
+ data.tar.gz: 02e5cffce164a25ae463b22e9f8b85c810d50c9c2875d09a3e83751afebac012
5
5
  SHA512:
6
- metadata.gz: 73c20ffc1467c52de7a44f91cf1711049c2db2f47aaf3b8faf517a0ba05030aa891c3748a0287ed6d5be799f96d3eb9b92eb8ea950041b0ff459e63262388a56
7
- data.tar.gz: 0343d43d8437dcb11255392d53cb57e06119eb0dbd7f20880c0e0646d40b1abf9888e6b1fd5450464eed6ec4635444f7817b87228b1560eca81f0e4997a79eee
6
+ metadata.gz: c6911f4383b0140c40bc08c838a3044897c3c9ac3c577fae4b3806879cbfed12f044f8ee1336305b1599c10af1bfb5aabe9ae2e8f1f9ffd94774d4de789e8402
7
+ data.tar.gz: 25c8ecfe04e846ba55d87b33a43e0a38422440d0a963066ac67217edd8ebc396cbb2309b50704ea6f4dc4609bacbfb3fb3b501ef0a40210fe1877df5c6fbb7f8
@@ -0,0 +1,36 @@
1
+ name: Code Style Checks
2
+
3
+ on:
4
+ pull_request:
5
+ branches:
6
+ - master
7
+ paths-ignore:
8
+ - 'README.md'
9
+ push:
10
+ branches:
11
+ - master
12
+ paths-ignore:
13
+ - 'README.md'
14
+
15
+ jobs:
16
+ rubocop:
17
+ name: Rubocop
18
+ if: "contains(github.event.commits[0].message, '[ci skip]') == false"
19
+ strategy:
20
+ fail-fast: false
21
+ matrix:
22
+ os:
23
+ - ubuntu
24
+ ruby:
25
+ - "3.0"
26
+ runs-on: ${{ matrix.os }}-latest
27
+ steps:
28
+ - name: Checkout
29
+ uses: actions/checkout@v2
30
+ - name: Setup Ruby
31
+ uses: ruby/setup-ruby@v1
32
+ with:
33
+ ruby-version: ${{ matrix.ruby }}
34
+ bundler-cache: true
35
+ - name: Run Rubocop
36
+ run: bundle exec rubocop
@@ -0,0 +1,41 @@
1
+ name: Tests
2
+
3
+ on:
4
+ pull_request:
5
+ branches:
6
+ - master
7
+ paths-ignore:
8
+ - 'README.md'
9
+ push:
10
+ branches:
11
+ - master
12
+ paths-ignore:
13
+ - 'README.md'
14
+
15
+ jobs:
16
+ unit_tests:
17
+ name: Unit Tests
18
+ if: "contains(github.event.commits[0].message, '[ci skip]') == false"
19
+ strategy:
20
+ fail-fast: false
21
+ matrix:
22
+ os:
23
+ - ubuntu
24
+ ruby:
25
+ - "3.0"
26
+ test_command: ["bundle exec rspec && bundle exec cucumber"]
27
+ include:
28
+ - os: ubuntu
29
+ ruby: "3.0"
30
+ test_command: "bundle exec rspec"
31
+ runs-on: ${{ matrix.os }}-latest
32
+ steps:
33
+ - name: Checkout
34
+ uses: actions/checkout@v2
35
+ - name: Setup Ruby
36
+ uses: ruby/setup-ruby@v1
37
+ with:
38
+ ruby-version: ${{ matrix.ruby }}
39
+ bundler-cache: true
40
+ - name: Test
41
+ run: ${{ matrix.test_command }}
data/CHANGELOG.markdown CHANGED
@@ -1,17 +1,58 @@
1
- ## v0.13.0
1
+
2
+ ## [v0.16.1] - 2021-04-17
3
+
4
+ [v0.16.1]: https://github.com/egonSchiele/contracts.ruby/compare/v0.16.0...v0.16.1
5
+
6
+ - Enhancement: Pretty-print contracts in error messages - [Corey Farwell](https://github.com/frewsxcv) [#289](https://github.com/egonSchiele/contracts.ruby/pull/289)
7
+ - Bugfix: Fix `attr_accessor_with_contract` with multiple attribute names input - [Kevin Yeh](https://github.com/kyeah) [#259](https://github.com/egonSchiele/contracts.ruby/pull/259)
8
+ - Bugfix: Fix "stack level too deep" in CI builds - [md-work](https://github.com/md-work) [#283](https://github.com/egonSchiele/contracts.ruby/pull/283)
9
+
10
+ ## [v0.16.0] - 2017-04-24
11
+
12
+ [v0.16.0]: https://github.com/egonSchiele/contracts.ruby/compare/v0.15.0...v0.16.0
13
+
14
+ - **Support for Ruby 1.8 has been discontinued** - [Corey Farwell](https://github.com/frewsxcv) [#256](https://github.com/egonSchiele/contracts.ruby/pull/256)
15
+ - Enhancement: Add a `Contracts::Attrs` module containing attribute w/ contracts utilities - [Corey Farwell](https://github.com/frewsxcv) [#255](https://github.com/egonSchiele/contracts.ruby/pull/255)
16
+ - Bugfix: Fix StrictHash contract for extra keys - [Maciej Malecki](https://github.com/smt116) [#254](https://github.com/egonSchiele/contracts.ruby/pull/254)
17
+
18
+ ## [v0.15.0] - 2017-02-24
19
+
20
+ [v0.15.0]: https://github.com/egonSchiele/contracts.ruby/compare/v0.14.0...v0.15.0
21
+
22
+ - Bugfix: Func contract's return value isn't enforced with blocks - [Piotr Szmielew](https://github.com/esse) [#251](https://github.com/egonSchiele/contracts.ruby/pull/251)
23
+ - Bugfx: Fix contracts used in AR-models - [Gert Goet](https://github.com/eval) [#237](https://github.com/egonSchiele/contracts.ruby/pull/237)
24
+
25
+ ## [v0.14.0] - 2016-04-26
26
+
27
+ [v0.14.0]: https://github.com/egonSchiele/contracts.ruby/compare/v0.13.0...v0.14.0
28
+
29
+ - Enhancement: Add StrictHash contract - [Fyodor](https://github.com/cbrwizard) [#236](https://github.com/egonSchiele/contracts.ruby/pull/236)
30
+ - Bugfix: dont fail if something other than a hash is passed to a KeywordArgs - [Dan Padilha](https://github.com/dpad) [#234](https://github.com/egonSchiele/contracts.ruby/pull/234)
31
+ - LICENSE ADDED: Simplified BSD (same as what is specified in the readme) - [Charles Dale](https://github.com/chuckd) [#233](https://github.com/egonSchiele/contracts.ruby/pull/233)
32
+ - Bugfix: fix constant looking when including a module that includes contracts (requires removing the check to see if contracts is already included) - [Aditya Bhargava](https://github.com/egonSchiele) [#232](https://github.com/egonSchiele/contracts.ruby/pull/232)
33
+ - Bugfix for err case when KeywordArgs and Proc are used together - [Aditya Bhargava](https://github.com/egonSchiele) [#230](https://github.com/egonSchiele/contracts.ruby/pull/230)
34
+ - Enhancement: Add DescendantOf contract - [Miguel Palhas](https://github.com/naps62) [#227](https://github.com/egonSchiele/contracts.ruby/pull/227)
35
+
36
+ ## [v0.13.0] - 2016-01-25
37
+
38
+ [v0.13.0]: https://github.com/egonSchiele/contracts.ruby/compare/v0.12.0...v0.13.0
2
39
 
3
40
  - Enhancement: Add support for Ruby 2.3 - [Oleksii Fedorov](https://github.com/waterlink) [#216](https://github.com/egonSchiele/contracts.ruby/pull/216)
4
41
  - Enhancement: Added Int, Nat and NatPos builtin contracts - [Simon George](https://github.com/sfcgeorge) [#212](https://github.com/egonSchiele/contracts.ruby/pull/212)
5
42
  - Bugfix: Allow contracts on singleton of subclass - [Oleksii Federov](https://github.com/waterlink) [#211](https://github.com/egonSchiele/contracts.ruby/pull/211)
6
43
 
7
- ## v0.12.0
44
+ ## [v0.12.0] - 2015-09-15
45
+
46
+ [v0.12.0]: https://github.com/egonSchiele/contracts.ruby/compare/v0.11.0...v0.12.0
8
47
 
9
48
  - Feature: add `Regexp` validator - [Gert Goet](https://github.com/eval) [#196](https://github.com/egonSchiele/contracts.ruby/pull/196)
10
49
  - Docs: bootstrap cucumber/aruba/relish setup - [Oleksii Fedorov](https://github.com/waterlink) [#195](https://github.com/egonSchiele/contracts.ruby/pull/195)
11
50
  - Bugfix: allow to `extend` module, that has `Contracts` or `Contracts::Core` included without harming current module/class `Contracts` functionality, see: [#176](https://github.com/egonSchiele/contracts.ruby/issues/176) - [Oleksii Fedorov](https://github.com/waterlink) [#198](https://github.com/egonSchiele/contracts.ruby/pull/198)
12
51
  - Enhancement: add `include Contracts::Builtin` to allow users to use builtin contracts without `Contracts::` prefix together with `include Contracts::Core` - [PikachuEXE](https://github.com/PikachuEXE) [#199](https://github.com/egonSchiele/contracts.ruby/pull/199)
13
52
 
14
- ## v0.11.0
53
+ ## [v0.11.0] - 2015-07-30
54
+
55
+ [v0.11.0]: https://github.com/egonSchiele/contracts.ruby/compare/v0.10.1...v0.11.0
15
56
 
16
57
  - Enhancement: add `include Contracts::Core` that doesn't pollute the namespace as much as `include Contracts` - [Oleksii Federov](https://github.com/waterlink) [#185](https://github.com/egonSchiele/contracts.ruby/pull/185)
17
58
  - Bugfix: fail if a non-hash is provided to a `HashOf` contract - [Abe Voelker](https://github.com/abevoelker) [#190](https://github.com/egonSchiele/contracts.ruby/pull/190)
@@ -20,11 +61,15 @@
20
61
  - Feature: range contract added - [Oleksii Fedorov](https://github.com/waterlink) [#184](https://github.com/egonSchiele/contracts.ruby/pull/184)
21
62
  - Feature: enum contract added - [Dennis Günnewig](https://github.com/dg-ratiodata) [#181](https://github.com/egonSchiele/contracts.ruby/pull/181)
22
63
 
23
- ## v0.10.1
64
+ ## [v0.10.1] - 2015-07-16
65
+
66
+ [v0.10.1]: https://github.com/egonSchiele/contracts.ruby/compare/v0.10...v0.10.1
24
67
 
25
68
  - Enhancement: make `@pattern_match` instance variable not render ruby warning. Required to use new aruba versions in rspec tests - [Dennis Günnewig](https://github.com/dg-ratiodata) [#179](https://github.com/egonSchiele/contracts.ruby/pull/179)
26
69
 
27
- ## v0.10
70
+ ## [v0.10] - 2015-07-07
71
+
72
+ [v0.10]: https://github.com/egonSchiele/contracts.ruby/compare/v0.9...v0.10
28
73
 
29
74
  - Bugfix: make `Maybe[Proc]` work correctly - [Simon George](https://github.com/sfcgeorge) [#142](https://github.com/egonSchiele/contracts.ruby/pull/142)
30
75
  - Bugfix: make `Func` contract verified when used as return contract - [Rob Rosenbaum](https://github.com/robnormal) [#145](https://github.com/egonSchiele/contracts.ruby/pull/145)
@@ -35,7 +80,9 @@
35
80
  - Feature: custom validators with `Contract.override_validator` - [Oleksii Fedorov](https://github.com/waterlink) [#159](https://github.com/egonSchiele/contracts.ruby/pull/159)
36
81
  - Feature: add builtin `RangeOf[...]` contract - [Gavin Sinclair](https://github.com/gsinclair) [#171](https://github.com/egonSchiele/contracts.ruby/pull/171)
37
82
 
38
- ## v0.9
83
+ ## [v0.9] - 2015-04-24
84
+
85
+ [v0.9]: https://github.com/egonSchiele/contracts.ruby/compare/0.8...v0.9
39
86
 
40
87
  - MAJOR fix in pattern-matching: If the return contract for a pattern-matched function fails, it should NOT try the next pattern-match function. Pattern-matching is only for params, not return values.
41
88
  - raise an error if multiple defns have the same contract for pattern matching.
@@ -56,7 +103,7 @@
56
103
  - Add `SetOf` contract
57
104
  - various small fixes
58
105
 
59
- ## v0.8
106
+ ## v0.8 - 2015-04-03
60
107
 
61
108
  - code refactored (very slight loss of performance, big increase in readability)
62
109
  - fail when defining a contract on a module without `include Contracts::Modules`
data/Gemfile CHANGED
@@ -1,17 +1,21 @@
1
- source "http://rubygems.org"
1
+ # frozen_string_literal: true
2
+
3
+ source "https://rubygems.org"
2
4
 
3
5
  gemspec
4
6
 
5
7
  group :test do
6
- gem "rspec"
7
8
  gem "aruba"
8
9
  gem "cucumber", "~> 1.3.20"
9
- gem "rubocop", "~> 0.29.1", :platform => [:ruby_20, :ruby_21, :ruby_22]
10
+ gem "rspec"
11
+
12
+ gem "rubocop", ">= 1.0.0"
13
+ gem "rubocop-performance", ">= 1.0.0"
10
14
  end
11
15
 
12
16
  group :development do
13
- gem "relish"
14
17
  gem "method_profiler"
15
- gem "ruby-prof"
16
18
  gem "rake"
19
+ gem "relish"
20
+ gem "ruby-prof"
17
21
  end
data/LICENSE ADDED
@@ -0,0 +1,23 @@
1
+ Copyright (c) 2012-2016 Aditya Bhargava
2
+ All rights reserved.
3
+
4
+ Redistribution and use in source and binary forms, with or without
5
+ modification, are permitted provided that the following conditions are met:
6
+
7
+ * Redistributions of source code must retain the above copyright notice, this
8
+ list of conditions and the following disclaimer.
9
+
10
+ * Redistributions in binary form must reproduce the above copyright notice,
11
+ this list of conditions and the following disclaimer in the documentation
12
+ and/or other materials provided with the distribution.
13
+
14
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
15
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
18
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
20
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
21
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
22
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
data/README.md CHANGED
@@ -1,4 +1,6 @@
1
- # contracts.ruby [![Build Status](https://travis-ci.org/egonSchiele/contracts.ruby.png?branch=master)](https://travis-ci.org/egonSchiele/contracts.ruby) [![Join the chat at https://gitter.im/egonSchiele/contracts.ruby](https://img.shields.io/badge/gitter-join%20chat-brightgreen.svg)](https://gitter.im/egonSchiele/contracts.ruby)
1
+ This project is looking for a new maintainer! [More details here](https://github.com/egonSchiele/contracts.ruby/issues/249)
2
+
3
+ # contracts.ruby [![GitHub Build Status](https://img.shields.io/github/workflow/status/egonSchiele/contracts.ruby/Tests?style=flat-square)](https://github.com/egonSchiele/contracts.ruby/actions?query=workflow%3ATests) [![Join the chat at https://gitter.im/egonSchiele/contracts.ruby](https://img.shields.io/badge/gitter-join%20chat-brightgreen.svg)](https://gitter.im/egonSchiele/contracts.ruby)
2
4
 
3
5
  Contracts let you clearly – even beautifully – express how your code behaves, and free you from writing tons of boilerplate, defensive code.
4
6
 
@@ -39,6 +41,7 @@ puts Example.new.double("oops")
39
41
 
40
42
  Save this in a file and run it. Notice we are calling `double` with `"oops"`, which is not a number. The contract fails with a detailed error message:
41
43
 
44
+ ```
42
45
  ParamContractError: Contract violation for argument 1 of 1:
43
46
  Expected: Num,
44
47
  Actual: "oops"
@@ -46,12 +49,13 @@ ParamContractError: Contract violation for argument 1 of 1:
46
49
  With Contract: Num => Num
47
50
  At: main.rb:8
48
51
  ...stack trace...
52
+ ```
49
53
 
50
54
  Instead of throwing an exception, you could log it, print a clean error message for your user...whatever you want. contracts.ruby is here to help you handle bugs better, not to get in your way.
51
55
 
52
56
  ## Tutorial
53
57
 
54
- Check out [this awesome tutorial](http://egonschiele.github.com/contracts.ruby).
58
+ Check out [this awesome tutorial](https://egonschiele.github.io/contracts.ruby/).
55
59
 
56
60
  ## Use Cases
57
61
 
@@ -67,15 +71,19 @@ To get started do the following:
67
71
 
68
72
  2. Run our test suite
69
73
 
70
- `bundle exec rake`
71
-
74
+ `bundle exec rspec`
75
+
76
+ 3. Run our code style checks
77
+
78
+ `bundle exec rubocop`
79
+
72
80
  ## Performance
73
81
 
74
82
  Using contracts.ruby results in very little slowdown. Check out [this blog post](http://adit.io/posts/2013-03-04-How-I-Made-My-Ruby-Project-10x-Faster.html#seconds-6) for more info.
75
83
 
76
84
  **Q.** What Rubies can I use this with?
77
85
 
78
- **A.** It's been tested with `1.8.7`, `1.9.2`, `1.9.3`, `2.0.0`, `2.1`, `2.2`, and `jruby` (both 1.8 and 1.9 modes).
86
+ **A.** It's been tested with `2.1`, `2.2`, `2.3`, `2.4`, `2.5`, `2.6` and `2.7`.
79
87
 
80
88
  If you're using the library, please [let me know](https://github.com/egonSchiele) what project you're using it on :)
81
89
 
@@ -91,7 +99,7 @@ Michael Tomer
91
99
 
92
100
  ## Credits
93
101
 
94
- Inspired by [contracts.coffee](http://disnetdev.com/contracts.coffee/).
102
+ Inspired by [contracts.coffee](http://disnet.github.io/contracts.coffee/).
95
103
 
96
104
  Copyright 2012-2015 [Aditya Bhargava](http://adit.io).
97
105
  Major improvements by [Alexey Fedorov](https://github.com/waterlink).
data/Rakefile CHANGED
@@ -1,10 +1,9 @@
1
- if RUBY_VERSION >= "2"
2
- task :default => [:spec, :rubocop]
1
+ # frozen_string_literal: true
3
2
 
4
- require "rubocop/rake_task"
5
- RuboCop::RakeTask.new
6
- else
7
- task :default => [:spec]
3
+ task :default => [:spec]
4
+
5
+ task :add_tag do
6
+ `git tag -a v#{Contracts::VERSION} -m 'v#{Contracts::VERSION}'`
8
7
  end
9
8
 
10
9
  require "rspec/core/rake_task"
data/TUTORIAL.md CHANGED
@@ -89,6 +89,7 @@ contracts.ruby comes with a lot of built-in contracts, including the following:
89
89
  * [`ArrayOf`](http://www.rubydoc.info/gems/contracts/Contracts/Builtin/ArrayOf) – checks that the argument is an array, and all elements pass the given contract, e.g. `ArrayOf[Num]`
90
90
  * [`SetOf`](http://www.rubydoc.info/gems/contracts/Contracts/Builtin/SetOf) – checks that the argument is a set, and all elements pass the given contract, e.g. `SetOf[Num]`
91
91
  * [`HashOf`](http://www.rubydoc.info/gems/contracts/Contracts/Builtin/HashOf) – checks that the argument is a hash, and all keys and values pass the given contract, e.g. `HashOf[Symbol => String]` or `HashOf[Symbol,String]`
92
+ * [`StrictHash`](http://www.rubydoc.info/gems/contracts/Contracts/Builtin/StrictHash) – checks that the argument is a hash, and every key passed is present in the given contract, e.g. `StrictHash[{ :description => String, :number => Fixnum }]`
92
93
  * [`RangeOf`](http://www.rubydoc.info/gems/contracts/Contracts/Builtin/RangeOf) – checks that the argument is a range whose elements (#first and #last) pass the given contract, e.g. `RangeOf[Date]`
93
94
  * [`Enum`](http://www.rubydoc.info/gems/contracts/Contracts/Builtin/Enum) – checks that the argument is part of a given collection of objects, e.g. `Enum[:a, :b, :c]`
94
95
 
@@ -270,7 +271,7 @@ You don't need to put a contract on every key. So this call would succeed:
270
271
  person({:name => "Adit", :age => 42, :foo => "bar"})
271
272
  ```
272
273
 
273
- even though we don't specify a type for `:foo`.
274
+ even though we don't specify a type for `:foo`. If you need this check though, use `StrictHash` instead.
274
275
 
275
276
  Peruse this contract on the keys and values of a Hash.
276
277
 
@@ -605,6 +606,32 @@ Possible validator overrides:
605
606
 
606
607
  Default validators can be found here: [lib/contracts/validators.rb](https://github.com/egonSchiele/contracts.ruby/blob/master/lib/contracts/validators.rb).
607
608
 
609
+ ## Contracts with attributes
610
+
611
+ You can include the `Contracts::Attrs` module in your class/module to get access to attribute utilities:
612
+
613
+ - `attr_reader_with_contract <symbol>..., <contract>`
614
+ - Wraps `attr_reader`, validates contract upon 'getting'
615
+ - `attr_writer_with_contract <symbol>..., <contract>`
616
+ - Wraps `attr_writer`, validates contract upon 'setting'
617
+ - `attr_accessor_with_contract <symbol>..., <contract>`
618
+ - Wraps `attr_accessor`, validates contract upon 'getting' or 'setting'
619
+
620
+ ### Example
621
+
622
+ ```ruby
623
+ class Person
624
+ include Contracts::Core
625
+ include Contracts::Attrs
626
+
627
+ attr_accessor_with_contract :name, String
628
+ end
629
+
630
+ person = Person.new
631
+ person.name = 'Jane'
632
+ person.name = 1.4 # This results in a contract error!
633
+ ```
634
+
608
635
  ## Disabling contracts
609
636
 
610
637
  If you want to disable contracts, set the `NO_CONTRACTS` environment variable. This will disable contracts and you won't have a performance hit. Pattern matching will still work if you disable contracts in this way! With NO_CONTRACTS only pattern-matching contracts are defined.
data/contracts.gemspec CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require File.expand_path(File.join(__FILE__, "../lib/contracts/version"))
2
4
 
3
5
  Gem::Specification.new do |s|
@@ -8,5 +10,11 @@ Gem::Specification.new do |s|
8
10
  s.author = "Aditya Bhargava"
9
11
  s.email = "bluemangroupie@gmail.com"
10
12
  s.files = `git ls-files`.split("\n")
11
- s.homepage = "http://github.com/egonSchiele/contracts.ruby"
13
+ s.homepage = "https://github.com/egonSchiele/contracts.ruby"
14
+ s.license = "BSD-2-Clause"
15
+ s.required_ruby_version = [">= 3.0", "< 4"]
16
+ s.post_install_message = "
17
+ 0.16.x will be the supporting Ruby 2.x and be feature frozen (only fixes will be released)
18
+ For Ruby 3.x use 0.17.x or later (might not be released yet)
19
+ "
12
20
  end
data/dependabot.yml ADDED
@@ -0,0 +1,20 @@
1
+ version: 2
2
+ updates:
3
+ - package-ecosystem: bundler
4
+ directory: "/"
5
+ schedule:
6
+ interval: monthly
7
+ time: "06:00"
8
+ timezone: Asia/Hong_Kong
9
+ open-pull-requests-limit: 10
10
+ labels:
11
+ - "dependencies"
12
+ - package-ecosystem: github-actions
13
+ directory: "/"
14
+ schedule:
15
+ interval: monthly
16
+ time: "06:00"
17
+ timezone: Asia/Hong_Kong
18
+ open-pull-requests-limit: 10
19
+ labels:
20
+ - "dependencies"
@@ -0,0 +1,241 @@
1
+ Feature: Pretty printing Contract violations
2
+
3
+ Scenario: Big array argument being passed to big array method parameter
4
+ Given a file named "example.rb" with:
5
+ """ruby
6
+ require "contracts"
7
+ C = Contracts
8
+
9
+ class Example
10
+ include Contracts::Core
11
+
12
+ class << self
13
+ Contract [
14
+ C::Or[String, Symbol],
15
+ C::Or[String, Symbol],
16
+ C::Or[String, Symbol],
17
+ C::Or[String, Symbol],
18
+ C::Or[String, Symbol],
19
+ C::Or[String, Symbol],
20
+ C::Or[String, Symbol]
21
+ ] => nil
22
+ def run(data)
23
+ nil
24
+ end
25
+ end
26
+ end
27
+
28
+ puts Example.run([
29
+ ["foo", "foo"],
30
+ ["foo", "foo"],
31
+ ["foo", "foo"],
32
+ ["foo", "foo"],
33
+ ["foo", "foo"],
34
+ ["foo", "foo"],
35
+ ["foo", "foo"],
36
+ ["foo", "foo"],
37
+ ["foo", "foo"]
38
+ ])
39
+ """
40
+ When I run `ruby example.rb`
41
+ Then the output should contain:
42
+ """
43
+ : Contract violation for argument 1 of 1: (ParamContractError)
44
+ Expected: [(String or Symbol),
45
+ (String or Symbol),
46
+ (String or Symbol),
47
+ (String or Symbol),
48
+ (String or Symbol),
49
+ (String or Symbol),
50
+ (String or Symbol)],
51
+ Actual: [["foo", "foo"],
52
+ ["foo", "foo"],
53
+ ["foo", "foo"],
54
+ ["foo", "foo"],
55
+ ["foo", "foo"],
56
+ ["foo", "foo"],
57
+ ["foo", "foo"],
58
+ ["foo", "foo"],
59
+ ["foo", "foo"]]
60
+ Value guarded in: Example::run
61
+ With Contract: Array => NilClass
62
+ At: example.rb:17
63
+ """
64
+
65
+ Scenario: Big array value being returned from method expecting different big array type
66
+ Given a file named "example.rb" with:
67
+ """ruby
68
+ require "contracts"
69
+ C = Contracts
70
+
71
+ class Example
72
+ include Contracts::Core
73
+
74
+ class << self
75
+ Contract C::None => [
76
+ C::Or[String, Symbol],
77
+ C::Or[String, Symbol],
78
+ C::Or[String, Symbol],
79
+ C::Or[String, Symbol],
80
+ C::Or[String, Symbol],
81
+ C::Or[String, Symbol],
82
+ C::Or[String, Symbol]
83
+ ]
84
+ def run
85
+ [
86
+ ["foo", "foo"],
87
+ ["foo", "foo"],
88
+ ["foo", "foo"],
89
+ ["foo", "foo"],
90
+ ["foo", "foo"],
91
+ ["foo", "foo"],
92
+ ["foo", "foo"],
93
+ ["foo", "foo"],
94
+ ["foo", "foo"]
95
+ ]
96
+ end
97
+ end
98
+ end
99
+
100
+ puts Example.run
101
+ """
102
+ When I run `ruby example.rb`
103
+ Then the output should contain:
104
+ """
105
+ : Contract violation for return value: (ReturnContractError)
106
+ Expected: [(String or Symbol),
107
+ (String or Symbol),
108
+ (String or Symbol),
109
+ (String or Symbol),
110
+ (String or Symbol),
111
+ (String or Symbol),
112
+ (String or Symbol)],
113
+ Actual: [["foo", "foo"],
114
+ ["foo", "foo"],
115
+ ["foo", "foo"],
116
+ ["foo", "foo"],
117
+ ["foo", "foo"],
118
+ ["foo", "foo"],
119
+ ["foo", "foo"],
120
+ ["foo", "foo"],
121
+ ["foo", "foo"]]
122
+ Value guarded in: Example::run
123
+ With Contract: None => Array
124
+ At: example.rb:17
125
+ """
126
+
127
+ Scenario: Big hash argument being passed to big hash method parameter
128
+ Given a file named "example.rb" with:
129
+ """ruby
130
+ require "contracts"
131
+ C = Contracts
132
+
133
+ class Example
134
+ include Contracts::Core
135
+
136
+ class << self
137
+ Contract ({
138
+ a: C::Or[String, Symbol],
139
+ b: C::Or[String, Symbol],
140
+ c: C::Or[String, Symbol],
141
+ d: C::Or[String, Symbol],
142
+ e: C::Or[String, Symbol],
143
+ f: C::Or[String, Symbol],
144
+ g: C::Or[String, Symbol]
145
+ }) => nil
146
+ def run(data)
147
+ nil
148
+ end
149
+ end
150
+ end
151
+
152
+ puts Example.run({
153
+ a: ["foo", "foo"],
154
+ b: ["foo", "foo"],
155
+ c: ["foo", "foo"],
156
+ d: ["foo", "foo"],
157
+ e: ["foo", "foo"],
158
+ f: ["foo", "foo"],
159
+ g: ["foo", "foo"]
160
+ })
161
+ """
162
+ When I run `ruby example.rb`
163
+ Then the output should contain:
164
+ """
165
+ : Contract violation for argument 1 of 1: (ParamContractError)
166
+ Expected: {:a=>(String or Symbol),
167
+ :b=>(String or Symbol),
168
+ :c=>(String or Symbol),
169
+ :d=>(String or Symbol),
170
+ :e=>(String or Symbol),
171
+ :f=>(String or Symbol),
172
+ :g=>(String or Symbol)},
173
+ Actual: {:a=>["foo", "foo"],
174
+ :b=>["foo", "foo"],
175
+ :c=>["foo", "foo"],
176
+ :d=>["foo", "foo"],
177
+ :e=>["foo", "foo"],
178
+ :f=>["foo", "foo"],
179
+ :g=>["foo", "foo"]}
180
+ Value guarded in: Example::run
181
+ With Contract: Hash => NilClass
182
+ At: example.rb:17
183
+ """
184
+
185
+ Scenario: Big hash value being returned from method expecting different big hash type
186
+ Given a file named "example.rb" with:
187
+ """ruby
188
+ require "contracts"
189
+ C = Contracts
190
+
191
+ class Example
192
+ include Contracts::Core
193
+
194
+ class << self
195
+ Contract C::None => ({
196
+ a: C::Or[String, Symbol],
197
+ b: C::Or[String, Symbol],
198
+ c: C::Or[String, Symbol],
199
+ d: C::Or[String, Symbol],
200
+ e: C::Or[String, Symbol],
201
+ f: C::Or[String, Symbol],
202
+ g: C::Or[String, Symbol]
203
+ })
204
+ def run
205
+ {
206
+ a: ["foo", "foo"],
207
+ b: ["foo", "foo"],
208
+ c: ["foo", "foo"],
209
+ d: ["foo", "foo"],
210
+ e: ["foo", "foo"],
211
+ f: ["foo", "foo"],
212
+ g: ["foo", "foo"]
213
+ }
214
+ end
215
+ end
216
+ end
217
+
218
+ puts Example.run
219
+ """
220
+ When I run `ruby example.rb`
221
+ Then the output should contain:
222
+ """
223
+ : Contract violation for return value: (ReturnContractError)
224
+ Expected: {:a=>(String or Symbol),
225
+ :b=>(String or Symbol),
226
+ :c=>(String or Symbol),
227
+ :d=>(String or Symbol),
228
+ :e=>(String or Symbol),
229
+ :f=>(String or Symbol),
230
+ :g=>(String or Symbol)},
231
+ Actual: {:a=>["foo", "foo"],
232
+ :b=>["foo", "foo"],
233
+ :c=>["foo", "foo"],
234
+ :d=>["foo", "foo"],
235
+ :e=>["foo", "foo"],
236
+ :f=>["foo", "foo"],
237
+ :g=>["foo", "foo"]}
238
+ Value guarded in: Example::run
239
+ With Contract: None => Hash
240
+ At: example.rb:17
241
+ """