assume 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +12 -0
- data/.rspec +3 -0
- data/CHANGES.md +2 -0
- data/Gemfile +8 -0
- data/LICENSE +15 -0
- data/README.md +219 -0
- data/Rakefile +14 -0
- data/assume.gemspec +45 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/lib/assume.rb +55 -0
- data/lib/assume/core_ext.rb +3 -0
- data/lib/assume/refine.rb +5 -0
- data/lib/assume/version.rb +3 -0
- metadata +118 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 8d8e6d1cef180511bada22d9611eddd535a1f929ca4a38aae70800d66653411e
|
4
|
+
data.tar.gz: ab8ece061eea9f1b900f991ab2197a2ae09e6d832e1e552240bf36651768a6ee
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 3586e10e23cb079f8379235a829dd107106f2aaf444903c8f4a8536522e583e38ed102c1a509673fd660f8e7be5791e0db57839078044ca427b1deeb5a5543d1
|
7
|
+
data.tar.gz: 94fba0ee942779ea52e89342b28ddf358f7c0a0f3ac09440c65a883a21ef4b541c2fd4e3818396e8464a2854f0a11283ba33cb0bae30b41edf777b9370132178
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/CHANGES.md
ADDED
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
ISC License
|
2
|
+
|
3
|
+
Copyright (c) 2020, Odin Heggvold Bekkelund
|
4
|
+
|
5
|
+
Permission to use, copy, modify, and/or distribute this software for any
|
6
|
+
purpose with or without fee is hereby granted, provided that the above
|
7
|
+
copyright notice and this permission notice appear in all copies.
|
8
|
+
|
9
|
+
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
10
|
+
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
11
|
+
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
12
|
+
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
13
|
+
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
14
|
+
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
15
|
+
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,219 @@
|
|
1
|
+
# Assume
|
2
|
+
|
3
|
+
Assume is a tool that helps you record your assumptions about code directly in the code you're writing. It is similiar in functionality to and directly inspired by [solid_assert](https://rubygems.org/gems/solid_assert).
|
4
|
+
|
5
|
+
## What?
|
6
|
+
|
7
|
+
We make lots of assumptions when we write code. [Programming with assertions](https://docs.oracle.com/javase/8/docs/technotes/guides/language/assert.html) is a technique that helps you catch problems with your assumptions earlier in the development process.
|
8
|
+
|
9
|
+
Assertions live in a subtle space between testing your code explicitly and
|
10
|
+
raising exceptions to enforce your api behaviour or handle edge cases. It is not a replacement for either.
|
11
|
+
|
12
|
+
This gem is an attempt to make the concept less computer-sciency and more english, encouraging you to think about and record your assumptions as you go, maybe even leave them in the codebase for your colleagues to find, so they may understand your thinking, and thus your code, better.
|
13
|
+
|
14
|
+
## Why tho?
|
15
|
+
|
16
|
+
You might have found yourself writing something like this:
|
17
|
+
|
18
|
+
```ruby
|
19
|
+
# i is the value of some enum 0-3
|
20
|
+
if i == 0
|
21
|
+
# do something cool
|
22
|
+
elsif i == 1
|
23
|
+
# do something cooler
|
24
|
+
elsif i == 2
|
25
|
+
# do something so cool the sun freezes
|
26
|
+
else # we know i == 3
|
27
|
+
# do something awesome
|
28
|
+
end
|
29
|
+
```
|
30
|
+
|
31
|
+
We know we don't need to perform another check on i, as we've exhausted all other options, but what happens when 'Dave' comes along next month and extends the enum to allow a 4?
|
32
|
+
|
33
|
+
By recording our assumption in code, 'Dave' will (hopefully) test his new enum and quickly discover that he broke our previous assumptions.
|
34
|
+
|
35
|
+
If he happens to read our code, it will say *right there in the code* that he's broken it, and he'll know to fix it.
|
36
|
+
|
37
|
+
```ruby
|
38
|
+
# i is now the value of some enum 0-4
|
39
|
+
if i == 0
|
40
|
+
# do something cool
|
41
|
+
elsif i == 1
|
42
|
+
# do something cooler
|
43
|
+
elsif i == 2
|
44
|
+
# do something so cool the sun freezes
|
45
|
+
else
|
46
|
+
assume { i == 3 } # BadAssumption!
|
47
|
+
end
|
48
|
+
```
|
49
|
+
|
50
|
+
If you had written this only as a comment, 'Dave' might've merged a bug because he had no idea this code even existed.
|
51
|
+
And if you *didn't even write a comment*, 'Dave' might not have noticed, even if he read your code. (Although in this example he probably would)
|
52
|
+
|
53
|
+
## More examples
|
54
|
+
|
55
|
+
You're writing a method and assuming it gets called after a certain point. You're actually assuming that there is a certain state available to you.
|
56
|
+
|
57
|
+
```ruby
|
58
|
+
class ThingDoer
|
59
|
+
# ...
|
60
|
+
|
61
|
+
private def do_the_thing
|
62
|
+
assume { @thingies.size > 0 }
|
63
|
+
end
|
64
|
+
|
65
|
+
# ...
|
66
|
+
end
|
67
|
+
```
|
68
|
+
|
69
|
+
You're doing some control flow you know will never happen
|
70
|
+
|
71
|
+
```ruby
|
72
|
+
def something(arg)
|
73
|
+
case arg
|
74
|
+
when 1
|
75
|
+
when 2
|
76
|
+
when 3
|
77
|
+
else
|
78
|
+
# instead of raise "this should never happen"
|
79
|
+
assume { false } # maybe real users don't need to notice, since this is not actually dangerous
|
80
|
+
end
|
81
|
+
end
|
82
|
+
```
|
83
|
+
|
84
|
+
## Installation
|
85
|
+
|
86
|
+
Add this line to your application's Gemfile:
|
87
|
+
|
88
|
+
```ruby
|
89
|
+
gem "assume"
|
90
|
+
```
|
91
|
+
|
92
|
+
And then execute:
|
93
|
+
|
94
|
+
$ bundle
|
95
|
+
|
96
|
+
Or install it yourself as:
|
97
|
+
|
98
|
+
$ gem install assume
|
99
|
+
|
100
|
+
## Setup
|
101
|
+
|
102
|
+
This:
|
103
|
+
|
104
|
+
```ruby
|
105
|
+
require "assume"
|
106
|
+
|
107
|
+
assume { "this" } # NoMethodError!
|
108
|
+
assumption { "gravity still works" } # NoMethodError!
|
109
|
+
```
|
110
|
+
Does not allow you to use the methods alone. You have three options:
|
111
|
+
|
112
|
+
```ruby
|
113
|
+
require "assume/core_ext" # monkey-patches Object to provide the methods everywhere
|
114
|
+
```
|
115
|
+
|
116
|
+
```ruby
|
117
|
+
require "assume/refine" # Loads Assumptions
|
118
|
+
|
119
|
+
class Whatever
|
120
|
+
using Assumptions # assume's methods are now available in this class
|
121
|
+
|
122
|
+
# ...
|
123
|
+
|
124
|
+
def do_the_thing
|
125
|
+
assume { @true == false }
|
126
|
+
|
127
|
+
@true = true
|
128
|
+
# ...
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
assume { "yes" == "no" } # NoMethodError!
|
133
|
+
```
|
134
|
+
|
135
|
+
or you can just do it yourself:
|
136
|
+
|
137
|
+
```ruby
|
138
|
+
include Assume
|
139
|
+
|
140
|
+
# or
|
141
|
+
|
142
|
+
class Whatever
|
143
|
+
include Assume
|
144
|
+
end
|
145
|
+
|
146
|
+
# etc...
|
147
|
+
```
|
148
|
+
|
149
|
+
## Usage
|
150
|
+
|
151
|
+
```ruby
|
152
|
+
require "assume"
|
153
|
+
require "assume/core_ext"
|
154
|
+
|
155
|
+
# assume does nothing by default
|
156
|
+
assume { true == false } # => nil
|
157
|
+
|
158
|
+
# it is common only to run assertions in development/test environments
|
159
|
+
# prod users get to be blissfully unaware, and the application does less work in prod
|
160
|
+
# Assume.enabled = Whatever.env != "prod"
|
161
|
+
Assume.enabled = true
|
162
|
+
|
163
|
+
assume { "yes" == "no" } # Assume::BadAssumption!
|
164
|
+
|
165
|
+
Assume.handler = proc { |result, block|
|
166
|
+
$stderr.puts "oh noes"
|
167
|
+
}
|
168
|
+
|
169
|
+
assume { true } # => nil
|
170
|
+
assumption { false } # => nil, (on stderr) => "oh noes\n"
|
171
|
+
assert { true } # NoMethodError!
|
172
|
+
|
173
|
+
alias assert assume # (if you're old-school like that)
|
174
|
+
|
175
|
+
assert { true } # => nil
|
176
|
+
```
|
177
|
+
|
178
|
+
## Don'ts
|
179
|
+
|
180
|
+
Don't use assume and rescue BadAssumption as an error handling mechanism.
|
181
|
+
Make your own error class and `raise`/`rescue` it.
|
182
|
+
Don't use assume to enforce the public api of a class/method. `raise ArgumentError` instead.
|
183
|
+
|
184
|
+
You should probably not use assume directly in a test case (you've already got expect/assert/whatever) but if the code under test uses assume and assume is enabled in your test suite, bonus! Your test suite is now more robust!
|
185
|
+
|
186
|
+
## Advanced
|
187
|
+
|
188
|
+
This gem has been developed on ruby 2.6.5 and 2.7.2, but it should work on basically all versions. If it doesn't work for whatever reason, it is probably due to the default broken assumption handler. Consider replacing it with something simpler:
|
189
|
+
|
190
|
+
```ruby
|
191
|
+
Assume.handler = proc { |result, block|
|
192
|
+
raise ::Assume::BadAssumption
|
193
|
+
}
|
194
|
+
```
|
195
|
+
|
196
|
+
Or using Proc#to_source from [sourcify](https://github.com/jhellerstein/sourcify)
|
197
|
+
|
198
|
+
```ruby
|
199
|
+
Assume.handler = proc { |result, block|
|
200
|
+
raise ::Assume::BadAssumption, "failed assumption:\n\n#{block.to_source}\n"
|
201
|
+
}
|
202
|
+
```
|
203
|
+
|
204
|
+
etc...
|
205
|
+
|
206
|
+
The default handler will only print the first line of source code which
|
207
|
+
the block's #source_location method points it at. E.g. it will not print any source code in irb, for example.
|
208
|
+
|
209
|
+
## Development
|
210
|
+
|
211
|
+
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
212
|
+
|
213
|
+
Warning: Do not use `rspec` to run all the tests, they will fail as they are testing require statements. Use `rake`.
|
214
|
+
|
215
|
+
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
216
|
+
|
217
|
+
## Contributing
|
218
|
+
|
219
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/odinhb/assume.
|
data/Rakefile
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "bundler/gem_tasks"
|
4
|
+
|
5
|
+
task :spec do
|
6
|
+
sh "rspec spec/assume_spec.rb"
|
7
|
+
sh "rspec spec/core_ext_spec.rb"
|
8
|
+
sh "rspec spec/refine_spec.rb"
|
9
|
+
end
|
10
|
+
task default: :spec
|
11
|
+
|
12
|
+
task :console do
|
13
|
+
exec 'bin/console'
|
14
|
+
end
|
data/assume.gemspec
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
lib = File.expand_path("../lib", __FILE__)
|
4
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
5
|
+
require "assume/version"
|
6
|
+
|
7
|
+
Gem::Specification.new do |spec|
|
8
|
+
spec.name = "assume"
|
9
|
+
spec.version = Assume::VERSION
|
10
|
+
spec.authors = ["Odin H B"]
|
11
|
+
spec.email = ["odinh2908@gmail.com"]
|
12
|
+
|
13
|
+
spec.summary = "Write your assumptions down - in code"
|
14
|
+
spec.description = "Assume encourages you to communicate with your team members and build confidence in your code"
|
15
|
+
spec.homepage = "https://github.com/odinhb/assume"
|
16
|
+
|
17
|
+
# Prevent pushing this gem to RubyGems.org. To allow pushes either set the 'allowed_push_host'
|
18
|
+
# to allow pushing to a single host or delete this section to allow pushing to any host.
|
19
|
+
if spec.respond_to?(:metadata)
|
20
|
+
spec.metadata["allowed_push_host"] = "https://rubygems.org"
|
21
|
+
|
22
|
+
spec.metadata["homepage_uri"] = spec.homepage
|
23
|
+
spec.metadata["source_code_uri"] = spec.homepage
|
24
|
+
spec.metadata["changelog_uri"] = "#{spec.homepage}/CHANGES.md"
|
25
|
+
else
|
26
|
+
raise "RubyGems 2.0 or newer is required to protect against " \
|
27
|
+
"public gem pushes."
|
28
|
+
end
|
29
|
+
|
30
|
+
# Specify which files should be added to the gem when it is released.
|
31
|
+
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
32
|
+
spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
|
33
|
+
`git ls-files -z`.split("\x0").reject { |f|
|
34
|
+
f.match(%r{^(test|spec|features)/})
|
35
|
+
}
|
36
|
+
end
|
37
|
+
|
38
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
39
|
+
spec.require_paths = ["lib"]
|
40
|
+
|
41
|
+
spec.add_development_dependency "bundler", "~> 2.1"
|
42
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
43
|
+
spec.add_development_dependency "rspec", "~> 3.0"
|
44
|
+
spec.add_development_dependency "irb"
|
45
|
+
end
|
data/bin/console
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "bundler/setup"
|
4
|
+
require "assume"
|
5
|
+
|
6
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
7
|
+
# with your gem easier. You can also use a different console, if you like.
|
8
|
+
|
9
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
10
|
+
# require "pry"
|
11
|
+
# Pry.start
|
12
|
+
|
13
|
+
require "irb"
|
14
|
+
IRB.start(__FILE__)
|
data/bin/setup
ADDED
data/lib/assume.rb
ADDED
@@ -0,0 +1,55 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "assume/version"
|
4
|
+
|
5
|
+
module Assume
|
6
|
+
class BadAssumption < StandardError; end
|
7
|
+
|
8
|
+
DEFAULT_HANDLER = lambda do |result, block|
|
9
|
+
filename, line = block.source_location
|
10
|
+
begin
|
11
|
+
lines = File.readlines(filename)
|
12
|
+
line_content = lines[line - 1]
|
13
|
+
rescue Errno::ENOENT => err
|
14
|
+
line_content = "<unable to open source code file>"
|
15
|
+
end
|
16
|
+
|
17
|
+
raise BadAssumption, "\nin #{filename}\nsource" \
|
18
|
+
"code (line #{line}):\n#{line_content}\n" \
|
19
|
+
"result was: #{result.inspect}"
|
20
|
+
end
|
21
|
+
|
22
|
+
def assume(&block)
|
23
|
+
raise ArgumentError, "assumptions need a block" if block.nil?
|
24
|
+
return unless Assume.enabled?
|
25
|
+
|
26
|
+
result = block.call
|
27
|
+
|
28
|
+
unless result
|
29
|
+
Assume.broken_assumption_handler.call(result, block)
|
30
|
+
end
|
31
|
+
|
32
|
+
nil
|
33
|
+
end
|
34
|
+
alias assumption assume
|
35
|
+
|
36
|
+
class << self
|
37
|
+
def handler=(handler)
|
38
|
+
@assumption_handler = handler
|
39
|
+
end
|
40
|
+
|
41
|
+
def enabled=(val)
|
42
|
+
@enabled = !!val
|
43
|
+
end
|
44
|
+
|
45
|
+
def enabled?
|
46
|
+
@enabled
|
47
|
+
end
|
48
|
+
|
49
|
+
def broken_assumption_handler
|
50
|
+
@assumption_handler || DEFAULT_HANDLER
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
Assume.enabled = false
|
metadata
ADDED
@@ -0,0 +1,118 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: assume
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Odin H B
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2020-12-10 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '2.1'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '2.1'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '10.0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '10.0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rspec
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '3.0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '3.0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: irb
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
description: Assume encourages you to communicate with your team members and build
|
70
|
+
confidence in your code
|
71
|
+
email:
|
72
|
+
- odinh2908@gmail.com
|
73
|
+
executables: []
|
74
|
+
extensions: []
|
75
|
+
extra_rdoc_files: []
|
76
|
+
files:
|
77
|
+
- ".gitignore"
|
78
|
+
- ".rspec"
|
79
|
+
- CHANGES.md
|
80
|
+
- Gemfile
|
81
|
+
- Gemfile.lock
|
82
|
+
- LICENSE
|
83
|
+
- README.md
|
84
|
+
- Rakefile
|
85
|
+
- assume.gemspec
|
86
|
+
- bin/console
|
87
|
+
- bin/setup
|
88
|
+
- lib/assume.rb
|
89
|
+
- lib/assume/core_ext.rb
|
90
|
+
- lib/assume/refine.rb
|
91
|
+
- lib/assume/version.rb
|
92
|
+
homepage: https://github.com/odinhb/assume
|
93
|
+
licenses: []
|
94
|
+
metadata:
|
95
|
+
allowed_push_host: https://rubygems.org
|
96
|
+
homepage_uri: https://github.com/odinhb/assume
|
97
|
+
source_code_uri: https://github.com/odinhb/assume
|
98
|
+
changelog_uri: https://github.com/odinhb/assume/CHANGES.md
|
99
|
+
post_install_message:
|
100
|
+
rdoc_options: []
|
101
|
+
require_paths:
|
102
|
+
- lib
|
103
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
104
|
+
requirements:
|
105
|
+
- - ">="
|
106
|
+
- !ruby/object:Gem::Version
|
107
|
+
version: '0'
|
108
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
109
|
+
requirements:
|
110
|
+
- - ">="
|
111
|
+
- !ruby/object:Gem::Version
|
112
|
+
version: '0'
|
113
|
+
requirements: []
|
114
|
+
rubygems_version: 3.1.4
|
115
|
+
signing_key:
|
116
|
+
specification_version: 4
|
117
|
+
summary: Write your assumptions down - in code
|
118
|
+
test_files: []
|