slide_rule 0.1.2 → 0.2.0
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.
- checksums.yaml +4 -4
- data/.gitignore +0 -4
- data/README.md +5 -44
- data/lib/slide_rule/distance_calculator.rb +15 -70
- data/lib/slide_rule/distance_calculators/day_of_month.rb +0 -1
- data/lib/slide_rule/distance_calculators/day_of_year.rb +0 -1
- data/lib/slide_rule/version.rb +1 -1
- data/spec/slide_rule/distance_calculator_spec.rb +33 -83
- data/spec/slide_rule/distance_calculators/day_of_month_spec.rb +0 -4
- data/spec/slide_rule/distance_calculators/day_of_year_spec.rb +0 -4
- data/spec/slide_rule/distance_calculators/levenshtein_spec.rb +2 -10
- data/spec/spec_helper.rb +0 -1
- metadata +33 -34
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d6f0cc115c650f57a1ebc32fb16dedb8647df5c4
|
4
|
+
data.tar.gz: cf1f0ba21b49a34ebc56d7595366180adec9d744
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2fc5aff23287ff405bdc120e5378e48f3b10c30ef23bbd311766cf6cebd7b149dd0fcfc3a34e2fe94cbc45ffe0cbd8a5b6310f3e02031ead580922ff0ead0bba
|
7
|
+
data.tar.gz: e8913245a2286590fa8e8560885ce86024506fc132424813187103a71de0e625532cea53edc59c476038e3be29c46af6d009a03f3c7d605c31ae23022d861f15
|
data/.gitignore
CHANGED
data/README.md
CHANGED
@@ -19,26 +19,25 @@ _Note: weights are assumed to be equal if not provided_
|
|
19
19
|
|
20
20
|
#API
|
21
21
|
|
22
|
-
##Describe the field
|
22
|
+
##Describe the field calculators
|
23
23
|
|
24
24
|
Each field to be considered in the distance calculation should be described
|
25
25
|
with a calculation method and weight(optional)
|
26
26
|
|
27
27
|
Valid calculators:
|
28
28
|
|
29
|
-
*
|
30
|
-
*
|
31
|
-
* levenshtein
|
29
|
+
* day_of_month (this needs to be factored into configurable date_recurrence)
|
30
|
+
* float_range_distance
|
32
31
|
|
33
32
|
```ruby
|
34
33
|
distance_rules = {
|
35
34
|
:description => {
|
36
35
|
:weight => 0.80,
|
37
|
-
:
|
36
|
+
:type => :levenshtein,
|
38
37
|
},
|
39
38
|
:date => {
|
40
39
|
:weight => 0.90,
|
41
|
-
:
|
40
|
+
:type => :day_of_month,
|
42
41
|
},
|
43
42
|
}
|
44
43
|
```
|
@@ -82,41 +81,3 @@ matcher.closest_match(candidate, [example, example2], 0.2)
|
|
82
81
|
=> example
|
83
82
|
|
84
83
|
```
|
85
|
-
|
86
|
-
## Custom Field Distance Calculators
|
87
|
-
|
88
|
-
To define a custom field distance calculator, define a class with a `calculate(value1, value2)` method.
|
89
|
-
|
90
|
-
Requirements:
|
91
|
-
* Class must be stateless
|
92
|
-
* Calculate should return a float from `0` (perfect match) to `1.0` (no match)
|
93
|
-
* Calculation should not be order dependent (e.g. `calculate(a, b) == calculate(b, a)`)
|
94
|
-
|
95
|
-
```ruby
|
96
|
-
class StringLengthCalculator
|
97
|
-
def calculate(l1, l2)
|
98
|
-
diff = (l1 - l2).abs.to_f
|
99
|
-
return diff / [l1, l2].max
|
100
|
-
end
|
101
|
-
end
|
102
|
-
|
103
|
-
matcher = ::SlideRule::DistanceCalculator.new(
|
104
|
-
:length => {
|
105
|
-
:weight => 1.0,
|
106
|
-
:calculator => StringLengthCalculator
|
107
|
-
}
|
108
|
-
)
|
109
|
-
|
110
|
-
# Find the string with the closest length
|
111
|
-
matcher.closest_match("Howdy Doody Time!", ["Felix the cat", "Mighty Mouse"], 0.5)
|
112
|
-
# => { :item=>"Mighty Mouse", :distance=>0.29411764705882354 }
|
113
|
-
```
|
114
|
-
|
115
|
-
See the [distance_calculators](https://github.com/mattnichols/slide_rule/tree/master/lib/slide_rule/distance_calculators) directory in source for more examples.
|
116
|
-
|
117
|
-
|
118
|
-
# To Do
|
119
|
-
|
120
|
-
* Add more field distance calculators
|
121
|
-
|
122
|
-
|
@@ -1,9 +1,7 @@
|
|
1
1
|
module SlideRule
|
2
2
|
class DistanceCalculator
|
3
|
-
attr_accessor :rules
|
4
|
-
|
5
3
|
def initialize(rules)
|
6
|
-
@rules =
|
4
|
+
@rules = normalize_weights(rules)
|
7
5
|
end
|
8
6
|
|
9
7
|
# TODO: Figure this out. Very inefficient!
|
@@ -22,21 +20,19 @@ module SlideRule
|
|
22
20
|
end
|
23
21
|
end
|
24
22
|
|
25
|
-
def closest_match(obj, array, threshold
|
26
|
-
matches(obj, array, threshold).
|
23
|
+
def closest_match(obj, array, threshold)
|
24
|
+
matches(obj, array, threshold).sort { |match| match[:distance] }.first
|
27
25
|
end
|
28
26
|
|
29
|
-
def
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
match[:item]
|
27
|
+
def is_match?(obj_1, obj_2, threshold)
|
28
|
+
distance = calculate_distance(obj_1, obj_2)
|
29
|
+
distance < threshold
|
34
30
|
end
|
35
31
|
|
36
32
|
def matches(obj, array, threshold)
|
37
33
|
array.map do |item|
|
38
34
|
distance = calculate_distance(obj, item)
|
39
|
-
next nil unless distance
|
35
|
+
next nil unless distance < threshold
|
40
36
|
{
|
41
37
|
item: item,
|
42
38
|
distance: distance
|
@@ -52,40 +48,23 @@ module SlideRule
|
|
52
48
|
# {
|
53
49
|
# :attribute_name => {
|
54
50
|
# :weight => 0.90,
|
55
|
-
# :
|
51
|
+
# :type => :distance_calculator,
|
56
52
|
# }
|
57
53
|
# }
|
58
54
|
def calculate_distance(i1, i2)
|
59
|
-
|
60
|
-
distance + (obj[:distance] * obj[:weight])
|
61
|
-
end
|
62
|
-
end
|
63
|
-
|
64
|
-
private
|
65
|
-
|
66
|
-
def calculate_weighted_distances(i1, i2)
|
67
|
-
distances = @rules.map do |attribute, rule|
|
55
|
+
@rules.map do |attribute, rule|
|
68
56
|
val1 = i1.send(attribute)
|
69
57
|
val2 = i2.send(attribute)
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
nil
|
74
|
-
end
|
75
|
-
normalize_weights_array(distances) if distances.compact!
|
76
|
-
|
77
|
-
distances
|
58
|
+
calculator = get_calculator(rule[:type])
|
59
|
+
calculator.calculate(val1, val2).to_f * rule[:weight]
|
60
|
+
end.reduce(0.0, &:+)
|
78
61
|
end
|
79
62
|
|
80
63
|
def get_calculator(calculator)
|
81
64
|
return calculator.new if calculator.is_a?(Class)
|
82
65
|
|
83
66
|
klass_name = "#{calculator.to_s.split('_').collect(&:capitalize).join}"
|
84
|
-
klass =
|
85
|
-
::SlideRule::DistanceCalculators.const_get(klass_name)
|
86
|
-
rescue(::NameError)
|
87
|
-
nil
|
88
|
-
end
|
67
|
+
klass = ::SlideRule::DistanceCalculators.const_get(klass_name)
|
89
68
|
|
90
69
|
fail ArgumentError, "Unable to find calculator #{klass_name}" if klass.nil?
|
91
70
|
|
@@ -94,46 +73,12 @@ module SlideRule
|
|
94
73
|
|
95
74
|
# Ensures all weights add up to 1.0
|
96
75
|
#
|
97
|
-
def normalize_weights(
|
76
|
+
def normalize_weights(rules_hash)
|
77
|
+
rules = rules_hash.dup
|
98
78
|
weight_total = rules.map { |_attr, rule| rule[:weight] }.reduce(0.0, &:+)
|
99
79
|
rules.each do |_attr, rule|
|
100
80
|
rule[:weight] = rule[:weight] / weight_total
|
101
81
|
end
|
102
82
|
end
|
103
|
-
|
104
|
-
# Ensures all weights add up to 1.0 in array of hashes
|
105
|
-
#
|
106
|
-
def normalize_weights_array(rules)
|
107
|
-
weight_total = rules.map { |rule| rule[:weight] }.reduce(0.0, &:+)
|
108
|
-
rules.each do |rule|
|
109
|
-
rule[:weight] = rule[:weight] / weight_total
|
110
|
-
end
|
111
|
-
end
|
112
|
-
|
113
|
-
# Prepares a duplicate of given rules hash with normalized weights and calculator instances
|
114
|
-
#
|
115
|
-
def prepare_rules(rules)
|
116
|
-
prepared_rules = rules.each_with_object({}) do |(attribute, rule), copy|
|
117
|
-
rule = copy[attribute] = safe_dup(rule)
|
118
|
-
|
119
|
-
if rule[:type]
|
120
|
-
puts 'Rule key `:type` is deprecated. Use `:calculator` instead.'
|
121
|
-
rule[:calculator] = rule[:type]
|
122
|
-
end
|
123
|
-
|
124
|
-
rule[:calculator] = get_calculator(rule[:calculator])
|
125
|
-
|
126
|
-
copy
|
127
|
-
end
|
128
|
-
prepared_rules = normalize_weights(prepared_rules)
|
129
|
-
|
130
|
-
prepared_rules
|
131
|
-
end
|
132
|
-
|
133
|
-
def safe_dup(obj)
|
134
|
-
obj.dup
|
135
|
-
rescue
|
136
|
-
obj
|
137
|
-
end
|
138
83
|
end
|
139
84
|
end
|
data/lib/slide_rule/version.rb
CHANGED
@@ -19,12 +19,6 @@ describe ::SlideRule::DistanceCalculator do
|
|
19
19
|
end
|
20
20
|
end
|
21
21
|
|
22
|
-
class NilCalc
|
23
|
-
def calculate(_first, _second)
|
24
|
-
nil
|
25
|
-
end
|
26
|
-
end
|
27
|
-
|
28
22
|
let(:examples) do
|
29
23
|
[
|
30
24
|
::ExampleTransaction.new(amount: 25.00, date: '2015-02-05', description: 'Audible.com'),
|
@@ -42,31 +36,50 @@ describe ::SlideRule::DistanceCalculator do
|
|
42
36
|
::SlideRule::DistanceCalculator.new(
|
43
37
|
description: {
|
44
38
|
weight: 0.80,
|
45
|
-
|
39
|
+
type: :levenshtein
|
46
40
|
},
|
47
41
|
date: {
|
48
42
|
weight: 0.90,
|
49
|
-
|
43
|
+
type: :day_of_month
|
50
44
|
}
|
51
45
|
)
|
52
46
|
end
|
53
47
|
|
54
|
-
it 'finds
|
48
|
+
it 'finds recurring transaction' do
|
55
49
|
example = ExampleTransaction.new(description: 'Wells Fargo Dealer SVC', date: '2015-06-17')
|
56
50
|
expect(calculator.closest_match(example, examples, 0.2)[:item]).to eq(examples[3])
|
57
51
|
|
58
52
|
example = ExampleTransaction.new(description: 'Audible.com', date: '2015-06-05')
|
59
53
|
expect(calculator.closest_match(example, examples, 0.2)[:item]).to eq(examples[0])
|
60
54
|
end
|
55
|
+
end
|
61
56
|
|
62
|
-
|
63
|
-
|
64
|
-
|
57
|
+
describe '#is_match?' do
|
58
|
+
let(:calculator) do
|
59
|
+
::SlideRule::DistanceCalculator.new(
|
60
|
+
description: {
|
61
|
+
weight: 0.80,
|
62
|
+
type: :levenshtein
|
63
|
+
},
|
64
|
+
date: {
|
65
|
+
weight: 0.90,
|
66
|
+
type: :day_of_month
|
67
|
+
}
|
68
|
+
)
|
65
69
|
end
|
66
70
|
|
67
|
-
it '
|
68
|
-
|
69
|
-
|
71
|
+
it 'returns true if there is a match' do
|
72
|
+
example_1 = ExampleTransaction.new(description: 'Wells Fargo Dealer SVC', date: '2015-06-17')
|
73
|
+
example_2 = ExampleTransaction.new(description: 'Wells Fargo Dealer SVC', date: '2015-06-17')
|
74
|
+
|
75
|
+
expect(calculator.is_match?(example_1, example_2, 0.2)).to be(true)
|
76
|
+
end
|
77
|
+
|
78
|
+
it 'returns false if there is a match' do
|
79
|
+
example_1 = ExampleTransaction.new(description: 'Wells Fargo Dealer SVC', date: '2015-06-17')
|
80
|
+
example_2 = ExampleTransaction.new(description: 'Taco Bell', date: '2015-06-17')
|
81
|
+
|
82
|
+
expect(calculator.is_match?(example_1, example_2, 0.2)).to be(false)
|
70
83
|
end
|
71
84
|
end
|
72
85
|
|
@@ -76,11 +89,11 @@ describe ::SlideRule::DistanceCalculator do
|
|
76
89
|
calculator = ::SlideRule::DistanceCalculator.new(
|
77
90
|
description: {
|
78
91
|
weight: 1.00,
|
79
|
-
|
92
|
+
type: :levenshtein
|
80
93
|
},
|
81
94
|
date: {
|
82
95
|
weight: 0.50,
|
83
|
-
|
96
|
+
type: :day_of_month
|
84
97
|
}
|
85
98
|
)
|
86
99
|
example = ::ExampleTransaction.new(amount: 25.00, date: '2015-02-05', description: 'Audible.com')
|
@@ -92,11 +105,11 @@ describe ::SlideRule::DistanceCalculator do
|
|
92
105
|
calculator = ::SlideRule::DistanceCalculator.new(
|
93
106
|
description: {
|
94
107
|
weight: 0.50,
|
95
|
-
|
108
|
+
type: :levenshtein
|
96
109
|
},
|
97
110
|
date: {
|
98
111
|
weight: 0.50,
|
99
|
-
|
112
|
+
type: :day_of_month
|
100
113
|
}
|
101
114
|
)
|
102
115
|
example = ::ExampleTransaction.new(amount: 25.00, date: '2015-02-05', description: 'Audible.com')
|
@@ -112,23 +125,6 @@ describe ::SlideRule::DistanceCalculator do
|
|
112
125
|
distance = calculator.calculate_distance(example, candidate)
|
113
126
|
expect(distance.round(4)).to eq(((3.0 * 0.5 / 15) + (4.0 * 0.5 / 11)).round(4))
|
114
127
|
end
|
115
|
-
|
116
|
-
it 'should renormalize on nil' do
|
117
|
-
calculator = ::SlideRule::DistanceCalculator.new(
|
118
|
-
description: {
|
119
|
-
weight: 0.50,
|
120
|
-
calculator: :levenshtein
|
121
|
-
},
|
122
|
-
date: {
|
123
|
-
weight: 0.50,
|
124
|
-
calculator: NilCalc
|
125
|
-
}
|
126
|
-
)
|
127
|
-
example1 = ::ExampleTransaction.new(amount: 25.00, date: '2015-02-05', description: 'Audible.com')
|
128
|
-
example2 = ::ExampleTransaction.new(amount: 25.00, date: '2015-06-08', description: 'Audible Inc')
|
129
|
-
|
130
|
-
expect(calculator.calculate_distance(example1, example2).round(4)).to eq((4.0 / 11).round(4))
|
131
|
-
end
|
132
128
|
end
|
133
129
|
|
134
130
|
context 'uses custom calculator' do
|
@@ -136,7 +132,7 @@ describe ::SlideRule::DistanceCalculator do
|
|
136
132
|
calculator = ::SlideRule::DistanceCalculator.new(
|
137
133
|
description: {
|
138
134
|
weight: 1.00,
|
139
|
-
|
135
|
+
type: CustomCalc
|
140
136
|
}
|
141
137
|
)
|
142
138
|
example = ::ExampleTransaction.new
|
@@ -146,51 +142,5 @@ describe ::SlideRule::DistanceCalculator do
|
|
146
142
|
expect(distance).to eq(0.9)
|
147
143
|
end
|
148
144
|
end
|
149
|
-
|
150
|
-
describe '#initialize' do
|
151
|
-
context 'validates rules on initialize' do
|
152
|
-
it 'should allow :type' do
|
153
|
-
::SlideRule::DistanceCalculator.new(
|
154
|
-
description: {
|
155
|
-
weight: 1.00,
|
156
|
-
type: CustomCalc
|
157
|
-
}
|
158
|
-
)
|
159
|
-
end
|
160
|
-
|
161
|
-
it 'should not modify input rule hash' do
|
162
|
-
rules = {
|
163
|
-
description: {
|
164
|
-
weight: 1.0,
|
165
|
-
calculator: CustomCalc
|
166
|
-
},
|
167
|
-
name: {
|
168
|
-
weight: 1.0,
|
169
|
-
type: CustomCalc
|
170
|
-
}
|
171
|
-
}
|
172
|
-
::SlideRule::DistanceCalculator.new(rules)
|
173
|
-
# Run a second time to ensure that no calculator instance is in rules. Will currently throw an error.
|
174
|
-
::SlideRule::DistanceCalculator.new(rules)
|
175
|
-
|
176
|
-
# :type should still be in original hash
|
177
|
-
expect(rules[:name].key?(:calculator)).to eq(false)
|
178
|
-
|
179
|
-
# :weight should not be normalized in original hash
|
180
|
-
expect(rules[:name][:weight]).to eq(1.0)
|
181
|
-
end
|
182
|
-
|
183
|
-
it 'should raise error if not valid calculator' do
|
184
|
-
expect do
|
185
|
-
::SlideRule::DistanceCalculator.new(
|
186
|
-
description: {
|
187
|
-
weight: 1.00,
|
188
|
-
calculator: :some_junk
|
189
|
-
}
|
190
|
-
)
|
191
|
-
end.to raise_error(::ArgumentError, 'Unable to find calculator SomeJunk')
|
192
|
-
end
|
193
|
-
end
|
194
|
-
end
|
195
145
|
end
|
196
146
|
end
|
@@ -6,10 +6,6 @@ describe ::SlideRule::DistanceCalculators::DayOfMonth do
|
|
6
6
|
expect(described_class.new.calculate('2012-03-19', '2014-08-19')).to eq(0.0)
|
7
7
|
end
|
8
8
|
|
9
|
-
it 'should accept epoch date' do
|
10
|
-
expect(described_class.new.calculate(1_444_262_400, 1_444_262_400)).to eq(0.0)
|
11
|
-
end
|
12
|
-
|
13
9
|
it 'should calculate when date is in the same month' do
|
14
10
|
expect(described_class.new.calculate('2012-03-19', '2014-08-22')).to eq(3.0 / 15)
|
15
11
|
expect(described_class.new.calculate('2012-03-19', '2014-08-09')).to eq(10.0 / 15)
|
@@ -5,10 +5,6 @@ describe ::SlideRule::DistanceCalculators::DayOfYear do
|
|
5
5
|
it 'should return a 0 distance' do
|
6
6
|
expect(described_class.new.calculate('2015-10-8', '2015-10-8')).to eq(0.0)
|
7
7
|
end
|
8
|
-
|
9
|
-
it 'should accept epoch date' do
|
10
|
-
expect(described_class.new.calculate(1_444_262_400, 1_444_262_400)).to eq(0.0)
|
11
|
-
end
|
12
8
|
end
|
13
9
|
|
14
10
|
context 'when dates are more than a year apart' do
|
@@ -1,19 +1,11 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe ::SlideRule::DistanceCalculators::Levenshtein do
|
4
|
-
let(:subject) { described_class.new }
|
5
|
-
|
6
4
|
it 'should calculate perfect match' do
|
7
|
-
expect(
|
5
|
+
expect(described_class.new.calculate('this is a test', 'this is a test')).to eq(0.0)
|
8
6
|
end
|
9
7
|
|
10
8
|
it 'should calculate distance as distance divided by length of longest string' do
|
11
|
-
expect(
|
12
|
-
end
|
13
|
-
|
14
|
-
it 'should handle nils' do
|
15
|
-
expect(subject.calculate(nil, nil)).to eq(0.0)
|
16
|
-
expect(subject.calculate(nil, 'goodbye')).to eq(1.0)
|
17
|
-
expect(subject.calculate('hello', nil)).to eq(1.0)
|
9
|
+
expect(described_class.new.calculate('this is a test', 'this is a test!').round(4)).to eq((1.0 / 15).round(4))
|
18
10
|
end
|
19
11
|
end
|
data/spec/spec_helper.rb
CHANGED
metadata
CHANGED
@@ -1,97 +1,96 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: slide_rule
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- mattnichols
|
8
8
|
- fergmastaflex
|
9
|
-
autorequire:
|
9
|
+
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2016-01-11 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
|
-
name: vladlev
|
16
15
|
requirement: !ruby/object:Gem::Requirement
|
17
16
|
requirements:
|
18
|
-
- -
|
17
|
+
- - ~>
|
19
18
|
- !ruby/object:Gem::Version
|
20
19
|
version: '1.0'
|
21
|
-
|
20
|
+
name: vladlev
|
22
21
|
prerelease: false
|
22
|
+
type: :runtime
|
23
23
|
version_requirements: !ruby/object:Gem::Requirement
|
24
24
|
requirements:
|
25
|
-
- -
|
25
|
+
- - ~>
|
26
26
|
- !ruby/object:Gem::Version
|
27
27
|
version: '1.0'
|
28
28
|
- !ruby/object:Gem::Dependency
|
29
|
-
name: rake
|
30
29
|
requirement: !ruby/object:Gem::Requirement
|
31
30
|
requirements:
|
32
|
-
- -
|
31
|
+
- - ~>
|
33
32
|
- !ruby/object:Gem::Version
|
34
33
|
version: '10'
|
35
|
-
|
34
|
+
name: rake
|
36
35
|
prerelease: false
|
36
|
+
type: :development
|
37
37
|
version_requirements: !ruby/object:Gem::Requirement
|
38
38
|
requirements:
|
39
|
-
- -
|
39
|
+
- - ~>
|
40
40
|
- !ruby/object:Gem::Version
|
41
41
|
version: '10'
|
42
42
|
- !ruby/object:Gem::Dependency
|
43
|
-
name: pry
|
44
43
|
requirement: !ruby/object:Gem::Requirement
|
45
44
|
requirements:
|
46
|
-
- -
|
45
|
+
- - ~>
|
47
46
|
- !ruby/object:Gem::Version
|
48
47
|
version: '0'
|
49
|
-
|
48
|
+
name: pry
|
50
49
|
prerelease: false
|
50
|
+
type: :development
|
51
51
|
version_requirements: !ruby/object:Gem::Requirement
|
52
52
|
requirements:
|
53
|
-
- -
|
53
|
+
- - ~>
|
54
54
|
- !ruby/object:Gem::Version
|
55
55
|
version: '0'
|
56
56
|
- !ruby/object:Gem::Dependency
|
57
|
-
name: rspec
|
58
57
|
requirement: !ruby/object:Gem::Requirement
|
59
58
|
requirements:
|
60
|
-
- -
|
59
|
+
- - ~>
|
61
60
|
- !ruby/object:Gem::Version
|
62
61
|
version: '3'
|
63
|
-
|
62
|
+
name: rspec
|
64
63
|
prerelease: false
|
64
|
+
type: :development
|
65
65
|
version_requirements: !ruby/object:Gem::Requirement
|
66
66
|
requirements:
|
67
|
-
- -
|
67
|
+
- - ~>
|
68
68
|
- !ruby/object:Gem::Version
|
69
69
|
version: '3'
|
70
70
|
- !ruby/object:Gem::Dependency
|
71
|
-
name: rubocop
|
72
71
|
requirement: !ruby/object:Gem::Requirement
|
73
72
|
requirements:
|
74
|
-
- -
|
73
|
+
- - ~>
|
75
74
|
- !ruby/object:Gem::Version
|
76
75
|
version: '0'
|
77
|
-
|
76
|
+
name: rubocop
|
78
77
|
prerelease: false
|
78
|
+
type: :development
|
79
79
|
version_requirements: !ruby/object:Gem::Requirement
|
80
80
|
requirements:
|
81
|
-
- -
|
81
|
+
- - ~>
|
82
82
|
- !ruby/object:Gem::Version
|
83
83
|
version: '0'
|
84
|
-
description: Calculates the distance between 2 arbitrary objects using specified fields
|
85
|
-
and algorithms.
|
84
|
+
description: Calculates the distance between 2 arbitrary objects using specified fields and algorithms.
|
86
85
|
email:
|
87
86
|
- dev@mx.com
|
88
87
|
executables: []
|
89
88
|
extensions: []
|
90
89
|
extra_rdoc_files: []
|
91
90
|
files:
|
92
|
-
-
|
93
|
-
-
|
94
|
-
-
|
91
|
+
- .gitignore
|
92
|
+
- .rubocop.yml
|
93
|
+
- .travis.yml
|
95
94
|
- CODE_OF_CONDUCT.md
|
96
95
|
- Gemfile
|
97
96
|
- LICENSE
|
@@ -113,24 +112,24 @@ homepage: https://github.com/mattnichols/slide_rule
|
|
113
112
|
licenses:
|
114
113
|
- MIT
|
115
114
|
metadata: {}
|
116
|
-
post_install_message:
|
115
|
+
post_install_message:
|
117
116
|
rdoc_options: []
|
118
117
|
require_paths:
|
119
118
|
- lib
|
120
119
|
required_ruby_version: !ruby/object:Gem::Requirement
|
121
120
|
requirements:
|
122
|
-
- -
|
121
|
+
- - '>='
|
123
122
|
- !ruby/object:Gem::Version
|
124
123
|
version: '0'
|
125
124
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
126
125
|
requirements:
|
127
|
-
- -
|
126
|
+
- - '>='
|
128
127
|
- !ruby/object:Gem::Version
|
129
128
|
version: '0'
|
130
129
|
requirements: []
|
131
|
-
rubyforge_project:
|
132
|
-
rubygems_version: 2.4.
|
133
|
-
signing_key:
|
130
|
+
rubyforge_project:
|
131
|
+
rubygems_version: 2.4.8
|
132
|
+
signing_key:
|
134
133
|
specification_version: 4
|
135
134
|
summary: Ruby object distance calculator
|
136
135
|
test_files:
|