contracts 0.13.0 → 0.17

Sign up to get free protection for your applications and to get access to all the features.
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
+ """