mal 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 460e0eb3883bf8c602f014845e5b878d8e07abbc
4
+ data.tar.gz: 52f32e1f129c60b75edfe5f4e4b8b2f979895e00
5
+ SHA512:
6
+ metadata.gz: 453e66b57683c0afc28c7a5ec1a28ae721208d4e113701e685cfc2e475c03e9edca0a06c27d95e949a9912172a6060b05aaca89d9116c64f07e4e6d12d20b9b9
7
+ data.tar.gz: cbfeb3a92260eeeb93639471b86e83b18efbd2f7da9f532b866f850cd6ab53446c0eaa3f830bb483b499781cf48cea74f7b1a3e22c8e4c7d82fb9bf2316b00db
data/.document ADDED
@@ -0,0 +1,5 @@
1
+ lib/**/*.rb
2
+ bin/*
3
+ -
4
+ features/**/*.feature
5
+ LICENSE.txt
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --color
data/Gemfile ADDED
@@ -0,0 +1,9 @@
1
+ source "https://rubygems.org"
2
+
3
+ group :development do
4
+ gem 'rack', '~> 1'
5
+ gem "rspec", "~> 3.2"
6
+ gem "bundler", "~> 1.0"
7
+ gem "jeweler", "~> 2.0.1"
8
+ gem "simplecov", ">= 0"
9
+ end
data/LICENSE.txt ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2016 Julik Tarkhanov
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,46 @@
1
+ # mal
2
+
3
+ Minuscule (Type) Algerba - a type-matching thing for Ruby.
4
+
5
+ The library allows you to do simple type matching based on _any_ Ruby types that support the "triqual"
6
+ operator (type equality). It is distantly related to libraries like rb_dry_types
7
+
8
+ A basic building block for these checks can be any object that supports `===`.
9
+ For example, to verify that a certain variable is either a String or a Numeric
10
+
11
+ Mal.Either(Numeric, String) === "ohai" # => true
12
+ Mal.Either(Numeric, String) === false # => false
13
+
14
+ Where this gets interesting is when you use combinations and unions. For instance, you can check if an
15
+ Array only contains booleans:
16
+
17
+ Mal.ArrayOf(Mal.Either(true, false)) === [true, false, false] #=> true
18
+
19
+ You can also match Hashes, which lends itself to JSON assertions quite nicely:
20
+
21
+ Mal.HashOf(name: String, age: Numeric) === {name: 'Jane', age: 22, accepted_license_agreement: true} #=> true
22
+
23
+ You can also use these type matchers for case statements:
24
+
25
+ case fetch_api_response
26
+ when Mal.HashWith(error: Mal.Anything())
27
+ raise ...
28
+ when Mal.HashWith(inserted: Mal.Boolean())
29
+ # insert successful
30
+ end
31
+
32
+ ## Contributing to mal
33
+
34
+ * Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet.
35
+ * Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it.
36
+ * Fork the project.
37
+ * Start a feature/bugfix branch.
38
+ * Commit and push until you are happy with your contribution.
39
+ * Make sure to add tests for it. This is important so I don't break it in a future version unintentionally.
40
+ * Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.
41
+
42
+ ## Copyright
43
+
44
+ Copyright (c) 2016 Julik Tarkhanov. See LICENSE.txt for
45
+ further details.
46
+
data/Rakefile ADDED
@@ -0,0 +1,53 @@
1
+ # encoding: utf-8
2
+
3
+ require 'rubygems'
4
+ require 'bundler'
5
+ begin
6
+ Bundler.setup(:default, :development)
7
+ rescue Bundler::BundlerError => e
8
+ $stderr.puts e.message
9
+ $stderr.puts "Run `bundle install` to install missing gems"
10
+ exit e.status_code
11
+ end
12
+ require 'rake'
13
+
14
+ require 'jeweler'
15
+ require_relative 'lib/mal'
16
+
17
+ Jeweler::Tasks.new do |gem|
18
+ # gem is a Gem::Specification... see http://guides.rubygems.org/specification-reference/ for more options
19
+ gem.version = Mal::VERSION
20
+ gem.name = "mal"
21
+ gem.homepage = "http://github.com/julik/mal"
22
+ gem.license = "MIT"
23
+ gem.summary = 'Minuscule algebraic types for Ruby'
24
+ gem.description = 'Minuscule algebraic types for Ruby'
25
+ gem.email = "me@julik.nl"
26
+ gem.authors = ["Julik Tarkhanov"]
27
+ # dependencies defined in Gemfile
28
+ end
29
+ Jeweler::RubygemsDotOrgTasks.new
30
+
31
+ require 'rspec/core'
32
+ require 'rspec/core/rake_task'
33
+ RSpec::Core::RakeTask.new(:spec) do |spec|
34
+ spec.pattern = FileList['spec/**/*_spec.rb']
35
+ end
36
+
37
+ desc "Code coverage detail"
38
+ task :simplecov do
39
+ ENV['COVERAGE'] = "true"
40
+ Rake::Task['spec'].execute
41
+ end
42
+
43
+ task :default => :spec
44
+
45
+ require 'rdoc/task'
46
+ Rake::RDocTask.new do |rdoc|
47
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
48
+
49
+ rdoc.rdoc_dir = 'rdoc'
50
+ rdoc.title = "mal #{version}"
51
+ rdoc.rdoc_files.include('README*')
52
+ rdoc.rdoc_files.include('lib/**/*.rb')
53
+ end
data/lib/mal.rb ADDED
@@ -0,0 +1,215 @@
1
+ module Mal
2
+ VERSION = '0.0.1'
3
+
4
+ class AnythingT
5
+ def ===(value)
6
+ true
7
+ end
8
+ def inspect
9
+ 'Anything()'
10
+ end
11
+ end
12
+
13
+ class OnlyT
14
+ def initialize(matchable)
15
+ @matchable = matchable
16
+ end
17
+
18
+ def ===(value)
19
+ @matchable === value
20
+ end
21
+
22
+ def inspect
23
+ 'Only(%s)' % @matchable.inspect
24
+ end
25
+ end
26
+
27
+ class NilT < OnlyT
28
+ def inspect; 'Nil()'; end
29
+ end
30
+
31
+ class HashT
32
+ def initialize(**required_keys_to_matchers)
33
+ @required_keys_to_matchers = required_keys_to_matchers
34
+ end
35
+
36
+ def ===(value)
37
+ return false unless value.is_a?(Hash)
38
+ @required_keys_to_matchers.each_pair do |k,value_matcher|
39
+ return false unless value.key? k
40
+ return false unless value_matcher === value[k]
41
+ end
42
+ true
43
+ end
44
+
45
+ def inspect
46
+ 'HashWith(%s)' % @required_keys_to_matchers.inspect[1..-2]
47
+ end
48
+ end
49
+
50
+ class HashOfOnlyT < HashT
51
+ def ===(value)
52
+ return false unless super
53
+ @required_keys_to_matchers.keys == value.keys
54
+ end
55
+
56
+ def inspect
57
+ 'HashOf(%s)' % @required_keys_to_matchers.inspect[1..-2]
58
+ end
59
+ end
60
+
61
+ class ArrayT < OnlyT
62
+ def initialize(matcher_for_each_array_element)
63
+ @matcher_for_each_array_element = matcher_for_each_array_element
64
+ end
65
+
66
+ def ===(value)
67
+ return false unless Array === value
68
+ return false unless value.any?
69
+ value.each do |value_element|
70
+ return false unless @matcher_for_each_array_element === value_element
71
+ end
72
+ true
73
+ end
74
+
75
+ def inspect
76
+ 'ArrayOf(%s)' % @matcher_for_each_array_element.inspect
77
+ end
78
+ end
79
+
80
+ class LengthT < OnlyT
81
+ def initialize(desired_length)
82
+ @desired_length = length
83
+ end
84
+
85
+ def ===(value)
86
+ return false unless value.respond_to? :length
87
+ @desired_length == value.length
88
+ end
89
+ end
90
+
91
+ class MinLengthT < LengthT
92
+ def ===(value)
93
+ return false unless value.respond_to? :length
94
+ @desired_length >= value.length
95
+ end
96
+ def inspect; 'OfAtLeastElements(%d)' % @desired_length; end
97
+ end
98
+
99
+ class MaxLengthT < LengthT
100
+ def ===(value)
101
+ return false unless value.respond_to? :length
102
+ @desired_length <= value.length
103
+ end
104
+ def inspect; 'OfAtMostElements(%d)' % @desired_length; end
105
+ end
106
+
107
+ class EitherT < OnlyT
108
+ def initialize(*types)
109
+ @types = types
110
+ end
111
+
112
+ def ===(value)
113
+ @types.any? {|type| type === value }
114
+ end
115
+
116
+ def inspect
117
+ 'Either(%s)' % @types.map{|e| e.inspect }.join(', ')
118
+ end
119
+ end
120
+
121
+ class UnionT < OnlyT
122
+ def initialize(*types)
123
+ @types = types
124
+ end
125
+
126
+ def ===(value)
127
+ @types.all? {|type| type === value}
128
+ end
129
+
130
+ def inspect
131
+ 'Both(%s)' % @types.map{|e| e.inspect }.join(', ')
132
+ end
133
+ end
134
+
135
+ class MaybeT < EitherT
136
+ def inspect; 'Maybe(%s)' % @types[1].inspect; end
137
+ end
138
+
139
+ class BoolT < EitherT
140
+ def initialize; super(TrueClass, FalseClass); end
141
+ def inspect; 'Bool()'; end
142
+ end
143
+
144
+ private_constant :NilT, :BoolT, :EitherT, :MaybeT, :ArrayT, :HashT, :BoolT, :HashOfOnlyT, :MaxLengthT, :MinLengthT
145
+
146
+ # Specifies a value that may only ever be `nil` and nothing else
147
+ def Nil()
148
+ NilT.new(NilClass)
149
+ end
150
+
151
+ # Specifies a value that is either `true` or `false` (truthy or falsy values do not work)
152
+ def Bool()
153
+ BoolT.new
154
+ end
155
+
156
+ # Specifies a value that matches only the given matcher
157
+ def Only(matchable)
158
+ OnlyT.new(matchable)
159
+ end
160
+
161
+ # Specifies a value that matches both the given matchers. For instance,
162
+ # can be a matcher for both a String and a Regexp
163
+ def Both(*matchables)
164
+ UnionT.new(*matchables)
165
+ end
166
+
167
+ # Specifies a value that matches either one of the given speciciers
168
+ def Either(*matchables)
169
+ EitherT.new(*matchables)
170
+ end
171
+
172
+ # Specifies a value that is either matching the given typespec, or is nil
173
+ def Maybe(matchable)
174
+ MaybeT.new(NilClass, matchable)
175
+ end
176
+
177
+ # Specifies an Array of at least 1 element, where each element matches the
178
+ # typespec for the array element
179
+ def ArrayOf(typespec_for_array_element)
180
+ ArrayT.new(typespec_for_array_element)
181
+ end
182
+
183
+ # Specifies a Hash containing at least the given keys, with values at those
184
+ # keys matching the given matchers. For example, for a Hash having at
185
+ # least the `:name` key with a corresponding value that is a String:
186
+ # HashOf(name: String)
187
+ # Since the match is non-strict, it will also match a Hash having more keys
188
+ # HashOf(name: String) === {name: 'John Doe', age: 21} #=> true
189
+ def HashWith(**keys_to_values)
190
+ HashT.new(**keys_to_values)
191
+ end
192
+
193
+ def OfAtLeastElements(n)
194
+ MinLengthT.new(n)
195
+ end
196
+
197
+ def OfAtMostElements(n)
198
+ MaxLengthT.new(n)
199
+ end
200
+
201
+ # Specifies a Hash containing only the given keys, with values at those
202
+ # keys matching the given matchers. For example, for a Hash having at
203
+ # the `:name` key with a corresponding value that is a String:
204
+ #
205
+ # HashOfOnly(name: String)
206
+ #
207
+ # Because the match is-strict, it will not match a Hash having additional keys
208
+ #
209
+ # HashOf(name: String) === {name: 'John Doe', age: 21} #=> false
210
+ def HashOf(**keys_to_values)
211
+ HashOfOnlyT.new(**keys_to_values)
212
+ end
213
+
214
+ extend self
215
+ end
data/mal.gemspec ADDED
@@ -0,0 +1,62 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
+ # -*- encoding: utf-8 -*-
5
+ # stub: mal 0.0.1 ruby lib
6
+
7
+ Gem::Specification.new do |s|
8
+ s.name = "mal"
9
+ s.version = "0.0.1"
10
+
11
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
12
+ s.require_paths = ["lib"]
13
+ s.authors = ["Julik Tarkhanov"]
14
+ s.date = "2016-09-16"
15
+ s.description = "Minuscule algebraic types for Ruby"
16
+ s.email = "me@julik.nl"
17
+ s.extra_rdoc_files = [
18
+ "LICENSE.txt",
19
+ "README.md"
20
+ ]
21
+ s.files = [
22
+ ".document",
23
+ ".rspec",
24
+ "Gemfile",
25
+ "LICENSE.txt",
26
+ "README.md",
27
+ "Rakefile",
28
+ "lib/mal.rb",
29
+ "mal.gemspec",
30
+ "spec/mal_spec.rb",
31
+ "spec/spec_helper.rb"
32
+ ]
33
+ s.homepage = "http://github.com/julik/mal"
34
+ s.licenses = ["MIT"]
35
+ s.rubygems_version = "2.5.1"
36
+ s.summary = "Minuscule algebraic types for Ruby"
37
+
38
+ if s.respond_to? :specification_version then
39
+ s.specification_version = 4
40
+
41
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
42
+ s.add_development_dependency(%q<rack>, ["~> 1"])
43
+ s.add_development_dependency(%q<rspec>, ["~> 3.2"])
44
+ s.add_development_dependency(%q<bundler>, ["~> 1.0"])
45
+ s.add_development_dependency(%q<jeweler>, ["~> 2.0.1"])
46
+ s.add_development_dependency(%q<simplecov>, [">= 0"])
47
+ else
48
+ s.add_dependency(%q<rack>, ["~> 1"])
49
+ s.add_dependency(%q<rspec>, ["~> 3.2"])
50
+ s.add_dependency(%q<bundler>, ["~> 1.0"])
51
+ s.add_dependency(%q<jeweler>, ["~> 2.0.1"])
52
+ s.add_dependency(%q<simplecov>, [">= 0"])
53
+ end
54
+ else
55
+ s.add_dependency(%q<rack>, ["~> 1"])
56
+ s.add_dependency(%q<rspec>, ["~> 3.2"])
57
+ s.add_dependency(%q<bundler>, ["~> 1.0"])
58
+ s.add_dependency(%q<jeweler>, ["~> 2.0.1"])
59
+ s.add_dependency(%q<simplecov>, [">= 0"])
60
+ end
61
+ end
62
+
data/spec/mal_spec.rb ADDED
@@ -0,0 +1,221 @@
1
+ require_relative 'spec_helper'
2
+
3
+ describe 'Mal' do
4
+ include Mal
5
+
6
+ def expect_match_of(typespec, value)
7
+ match_v = typespec === value
8
+ expect(match_v).to eq(true), "Expected #{value.inspect} to match #{typespec.inspect}"
9
+ end
10
+
11
+ def expect_no_match_of(typespec, value)
12
+ match_v = typespec === value
13
+ expect(match_v).to eq(false), "Expected #{value.inspect} not to match #{typespec.inspect}"
14
+ end
15
+
16
+ describe 'Nil()' do
17
+ it 'provides a good inspect' do
18
+ expect(Nil().inspect).to eq('Nil()')
19
+ end
20
+
21
+ it 'matches nil only' do
22
+ expect_match_of(Nil(), nil)
23
+ expect_no_match_of(Nil(), 0)
24
+ expect_no_match_of(Nil(), Object.new)
25
+ expect_no_match_of(Nil(), self)
26
+ end
27
+ end
28
+
29
+ describe 'Bool()' do
30
+ it 'provides a good inspect' do
31
+ expect(Bool().inspect).to eq('Bool()')
32
+ end
33
+
34
+ it 'matches only true and false' do
35
+ expect_match_of(Bool(), true)
36
+ expect_match_of(Bool(), false)
37
+ expect_no_match_of(Bool(), nil)
38
+ expect_no_match_of(Bool(), self)
39
+ expect_no_match_of(Bool(), 'hello world')
40
+ expect_no_match_of(Bool(), 123)
41
+ end
42
+ end
43
+
44
+ describe 'Either()' do
45
+ it 'provides a good inspect' do
46
+ expect(Either(String, Hash).inspect).to eq('Either(String, Hash)')
47
+ end
48
+
49
+ it 'matches either of given' do
50
+ m = Either(String, TrueClass)
51
+ expect_match_of(m, 'hello world')
52
+ expect_match_of(m, true)
53
+ expect_no_match_of(m, false)
54
+ expect_no_match_of(m, nil)
55
+ expect_no_match_of(m, self)
56
+ end
57
+ end
58
+
59
+ describe 'Maybe()' do
60
+ it 'provides a good inspect' do
61
+ expect(Maybe(String).inspect).to eq('Maybe(String)')
62
+ end
63
+
64
+ it 'matches a nil or a given type' do
65
+ m = Maybe(String)
66
+ expect_match_of(m, nil)
67
+ expect_match_of(m, 'foo')
68
+ expect_no_match_of(m, false)
69
+ expect_no_match_of(m, self)
70
+ end
71
+ end
72
+
73
+ describe 'ArrayOf()' do
74
+ it 'provides a good inspect' do
75
+ expect(ArrayOf(Maybe(Fixnum)).inspect).to eq('ArrayOf(Maybe(Fixnum))')
76
+ end
77
+
78
+ it 'does not match objects of other types' do
79
+ expect_no_match_of(ArrayOf(TrueClass), nil)
80
+ expect_no_match_of(ArrayOf(TrueClass), false)
81
+ expect_no_match_of(ArrayOf(TrueClass), self)
82
+ expect_no_match_of(ArrayOf(TrueClass), 123)
83
+ end
84
+
85
+ it 'does not match an empty Array' do
86
+ expect_no_match_of(ArrayOf(TrueClass), [])
87
+ end
88
+
89
+ it 'matches an Array containing objects of matching types' do
90
+ m = ArrayOf(Fixnum)
91
+ expect_no_match_of(m, [true, false, 1, 'foo'])
92
+ expect_match_of(m, [1, 78451, 546])
93
+ end
94
+
95
+ it 'matches an Array of elements parametrized via union types' do
96
+ m = ArrayOf(Either(Fixnum, Bool()))
97
+ expect_no_match_of(m, [true, false, 1, 'foo'])
98
+ expect_match_of(m, [true, false, 1])
99
+ end
100
+ end
101
+
102
+ describe 'Both()' do
103
+ it 'provides a good inspect' do
104
+ m = Both(String, /abc/)
105
+ expect(m.inspect).to eq("Both(String, /abc/)")
106
+ end
107
+
108
+ it 'provides matching against all the elements' do
109
+ m = Both(String, /abc/)
110
+ expect_match_of(m, 'this is an abc string')
111
+ expect_no_match_of(m, 'this is a string that does match the second parameter')
112
+ end
113
+ end
114
+
115
+ describe 'HashWith()' do
116
+ it 'provides a good inspect' do
117
+ m = HashWith(foo: Maybe(Fixnum))
118
+ expect(m.inspect).to eq("HashWith(:foo=>Maybe(Fixnum))")
119
+ end
120
+
121
+ it 'does not match other types' do
122
+ m = HashWith(foo: Symbol)
123
+ expect_no_match_of(m, nil)
124
+ expect_no_match_of(m, [])
125
+ expect_no_match_of(m, self)
126
+ end
127
+
128
+ it 'does match an empty Hash when asked to' do
129
+ m = HashWith({})
130
+ expect_match_of(m, {})
131
+ end
132
+
133
+ it 'does not match a Hash whose value does not satisfy the matcher' do
134
+ m = HashWith(some_key: Nil())
135
+ expect_no_match_of(m, {some_key: true})
136
+ end
137
+
138
+ it 'does match a Hash whose keys/values do satisfy the matcher' do
139
+ m = HashWith(some_key: Maybe(String))
140
+ expect_match_of(m, {some_key: nil})
141
+ expect_match_of(m, {some_key: 'hello world'})
142
+ end
143
+
144
+ it 'does match a Hash that has more keys than requested' do
145
+ m = HashWith(name: String)
146
+ expect_match_of(m, {name: 'John Doe', age: 21})
147
+ end
148
+ end
149
+
150
+ describe 'HashOf()' do
151
+ it 'provides a good inspect' do
152
+ m = HashOf(foo: Maybe(Fixnum))
153
+ expect(m.inspect).to eq("HashOf(:foo=>Maybe(Fixnum))")
154
+ end
155
+
156
+ it 'does not match other types' do
157
+ m = HashOf(foo: Symbol)
158
+ expect_no_match_of(m, nil)
159
+ expect_no_match_of(m, [])
160
+ expect_no_match_of(m, self)
161
+ end
162
+
163
+ it 'does match an empty Hash when asked to' do
164
+ m = HashOf({})
165
+ expect_match_of(m, {})
166
+ end
167
+
168
+ it 'does not match a Hash whose value does not satisfy the matcher' do
169
+ m = HashOf(some_key: Nil())
170
+ expect_no_match_of(m, {some_key: true})
171
+ end
172
+
173
+ it 'does match a Hash whose keys/values do satisfy the matcher' do
174
+ m = HashOf(some_key: Maybe(String))
175
+ expect_match_of(m, {some_key: nil})
176
+ expect_match_of(m, {some_key: 'hello world'})
177
+ end
178
+
179
+ it 'does not match a Hash that has more keys than requested' do
180
+ m = HashOf(name: String)
181
+ expect_no_match_of(m, {name: 'John Doe', age: 21})
182
+ end
183
+ end
184
+
185
+ describe 'HashOf with complex nested matchers' do
186
+ it 'matches the User response' do
187
+ m = Mal::HashWith(
188
+ user: Mal::HashWith(
189
+ active_subscription: Mal::Bool(),
190
+ profile_picture_url: Mal::Maybe(String),
191
+ full_name: String,
192
+ id: Integer
193
+ )
194
+ )
195
+
196
+ expect_match_of(m, {user: {
197
+ id: 123,
198
+ active_subscription: true,
199
+ profile_picture_url: 'http://url.com',
200
+ full_name: 'John Doe',
201
+ }})
202
+
203
+ expect_match_of(m, {user: {
204
+ id: 123,
205
+ interests: ['Fishing', 'Hiking'],
206
+ active_subscription: true,
207
+ profile_picture_url: 'http://url.com',
208
+ full_name: 'John Doe',
209
+ }})
210
+
211
+ expect_no_match_of(m, {user: {
212
+ # skip the "id" field and let the matcher fail
213
+ interests: ['Fishing', 'Hiking'],
214
+ active_subscription: true,
215
+ profile_picture_url: 'http://url.com',
216
+ full_name: 'John Doe',
217
+ }})
218
+ end
219
+ end
220
+
221
+ end
@@ -0,0 +1,9 @@
1
+ require 'rspec'
2
+
3
+ RSpec.configure do |config|
4
+ config.order = 'random'
5
+ end
6
+
7
+ require 'simplecov'
8
+ SimpleCov.start
9
+ require_relative '../lib/mal'
metadata ADDED
@@ -0,0 +1,125 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: mal
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Julik Tarkhanov
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2016-09-16 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rack
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rspec
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '3.2'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '3.2'
41
+ - !ruby/object:Gem::Dependency
42
+ name: bundler
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '1.0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '1.0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: jeweler
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: 2.0.1
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: 2.0.1
69
+ - !ruby/object:Gem::Dependency
70
+ name: simplecov
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ description: Minuscule algebraic types for Ruby
84
+ email: me@julik.nl
85
+ executables: []
86
+ extensions: []
87
+ extra_rdoc_files:
88
+ - LICENSE.txt
89
+ - README.md
90
+ files:
91
+ - ".document"
92
+ - ".rspec"
93
+ - Gemfile
94
+ - LICENSE.txt
95
+ - README.md
96
+ - Rakefile
97
+ - lib/mal.rb
98
+ - mal.gemspec
99
+ - spec/mal_spec.rb
100
+ - spec/spec_helper.rb
101
+ homepage: http://github.com/julik/mal
102
+ licenses:
103
+ - MIT
104
+ metadata: {}
105
+ post_install_message:
106
+ rdoc_options: []
107
+ require_paths:
108
+ - lib
109
+ required_ruby_version: !ruby/object:Gem::Requirement
110
+ requirements:
111
+ - - ">="
112
+ - !ruby/object:Gem::Version
113
+ version: '0'
114
+ required_rubygems_version: !ruby/object:Gem::Requirement
115
+ requirements:
116
+ - - ">="
117
+ - !ruby/object:Gem::Version
118
+ version: '0'
119
+ requirements: []
120
+ rubyforge_project:
121
+ rubygems_version: 2.5.1
122
+ signing_key:
123
+ specification_version: 4
124
+ summary: Minuscule algebraic types for Ruby
125
+ test_files: []