fear 0.1.0 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.yardopts +1 -0
- data/README.md +8 -0
- data/fear.gemspec +1 -1
- data/lib/fear/either.rb +192 -97
- data/lib/fear/failure.rb +15 -7
- data/lib/fear/for.rb +22 -7
- data/lib/fear/left.rb +21 -20
- data/lib/fear/none.rb +15 -6
- data/lib/fear/option.rb +123 -40
- data/lib/fear/right.rb +25 -20
- data/lib/fear/right_biased.rb +5 -9
- data/lib/fear/some.rb +13 -8
- data/lib/fear/success.rb +16 -11
- data/lib/fear/try.rb +203 -66
- data/lib/fear/utils.rb +1 -0
- data/lib/fear/version.rb +1 -1
- data/spec/fear/failure_spec.rb +7 -1
- data/spec/fear/left_spec.rb +12 -2
- data/spec/fear/none_spec.rb +10 -7
- data/spec/fear/option_spec.rb +7 -24
- data/spec/fear/right_spec.rb +16 -2
- data/spec/fear/some_spec.rb +11 -7
- data/spec/fear/success_spec.rb +5 -0
- metadata +4 -3
data/lib/fear/try.rb
CHANGED
@@ -1,16 +1,16 @@
|
|
1
1
|
module Fear
|
2
|
-
# The
|
3
|
-
# in an exception, or return a successfully computed value.
|
2
|
+
# The +Try+ represents a computation that may either result
|
3
|
+
# in an exception, or return a successfully computed value. Instances of +Try+,
|
4
|
+
# are either an instance of +Success+ or +Failure+.
|
4
5
|
#
|
5
|
-
#
|
6
|
-
# `Failure`.
|
7
|
-
#
|
8
|
-
# For example, `Try` can be used to perform division on a
|
6
|
+
# For example, +Try+ can be used to perform division on a
|
9
7
|
# user-defined input, without the need to do explicit
|
10
8
|
# exception-handling in all of the places that an exception
|
11
9
|
# might occur.
|
12
10
|
#
|
13
11
|
# @example
|
12
|
+
# include Fear::Try::Mixin
|
13
|
+
#
|
14
14
|
# dividend = Try { Integer(params[:dividend]) }
|
15
15
|
# divisor = Try { Integer(params[:divisor]) }
|
16
16
|
# problem = dividend.flat_map { |x| divisor.map { |y| x / y }
|
@@ -22,89 +22,226 @@ module Fear
|
|
22
22
|
# puts "Info from the exception: #{problem.exception.message}"
|
23
23
|
# end
|
24
24
|
#
|
25
|
-
# An important property of
|
26
|
-
# ability to
|
27
|
-
# along the way. The
|
25
|
+
# An important property of +Try+ shown in the above example is its
|
26
|
+
# ability to _pipeline_, or chain, operations, catching exceptions
|
27
|
+
# along the way. The +flat_map+ and +map+ combinators in the above
|
28
28
|
# example each essentially pass off either their successfully completed
|
29
|
-
# value, wrapped in the
|
29
|
+
# value, wrapped in the +Success+ type for it to be further operated
|
30
30
|
# upon by the next combinator in the chain, or the exception wrapped
|
31
|
-
# in the
|
32
|
-
# Combinators such as
|
31
|
+
# in the +Failure+ type usually to be simply passed on down the chain.
|
32
|
+
# Combinators such as +recover_with+ and +recover+ are designed to provide some
|
33
33
|
# type of default behavior in the case of failure.
|
34
34
|
#
|
35
|
-
# @note only non-fatal exceptions are caught by the combinators on
|
36
|
-
#
|
37
|
-
#
|
38
|
-
# @note all
|
39
|
-
#
|
40
|
-
#
|
41
|
-
#
|
42
|
-
# Success
|
43
|
-
#
|
44
|
-
#
|
45
|
-
#
|
46
|
-
#
|
47
|
-
#
|
48
|
-
#
|
49
|
-
#
|
50
|
-
#
|
51
|
-
#
|
52
|
-
#
|
53
|
-
#
|
54
|
-
#
|
55
|
-
#
|
56
|
-
#
|
57
|
-
#
|
58
|
-
#
|
59
|
-
#
|
60
|
-
#
|
61
|
-
#
|
62
|
-
#
|
63
|
-
#
|
64
|
-
#
|
65
|
-
#
|
66
|
-
#
|
67
|
-
#
|
68
|
-
#
|
69
|
-
#
|
70
|
-
#
|
71
|
-
#
|
72
|
-
#
|
73
|
-
#
|
74
|
-
#
|
75
|
-
#
|
76
|
-
#
|
77
|
-
#
|
78
|
-
#
|
35
|
+
# @note only non-fatal exceptions are caught by the combinators on +Try+.
|
36
|
+
# Serious system errors, on the other hand, will be thrown.
|
37
|
+
#
|
38
|
+
# @note all +Try+ combinators will catch exceptions and return failure unless
|
39
|
+
# otherwise specified in the documentation.
|
40
|
+
#
|
41
|
+
# @!method get_or_else(*args)
|
42
|
+
# Returns the value from this +Success+ or evaluates the given
|
43
|
+
# default argument if this is a +Failure+.
|
44
|
+
# @overload get_or_else(&default)
|
45
|
+
# @yieldreturn [any]
|
46
|
+
# @return [any]
|
47
|
+
# @example
|
48
|
+
# Success(42).get_or_else { 24/2 } #=> 42
|
49
|
+
# Failure(ArgumentError.new).get_or_else { 24/2 } #=> 12
|
50
|
+
# @overload get_or_else(default)
|
51
|
+
# @return [any]
|
52
|
+
# @example
|
53
|
+
# Success(42).get_or_else(12) #=> 42
|
54
|
+
# Failure(ArgumentError.new).get_or_else(12) #=> 12
|
55
|
+
#
|
56
|
+
# @!method include?(other_value)
|
57
|
+
# Returns +true+ if it has an element that is equal
|
58
|
+
# (as determined by +==+) to +other_value+, +false+ otherwise.
|
59
|
+
# @param [any]
|
60
|
+
# @return [Boolean]
|
61
|
+
# @example
|
62
|
+
# Success(17).include?(17) #=> true
|
63
|
+
# Success(17).include?(7) #=> false
|
64
|
+
# Failure(ArgumentError.new).include?(17) #=> false
|
65
|
+
#
|
66
|
+
# @!method each(&block)
|
67
|
+
# Performs the given block if this is a +Success+.
|
68
|
+
# @note if block raise an error, then this method may raise an exception.
|
69
|
+
# @yieldparam [any] value
|
70
|
+
# @yieldreturn [void]
|
71
|
+
# @return [Try] itself
|
72
|
+
# @example
|
73
|
+
# Success(17).each do |value|
|
74
|
+
# puts value
|
75
|
+
# end #=> prints 17
|
76
|
+
#
|
77
|
+
# Failure(ArgumentError.new).each do |value|
|
78
|
+
# puts value
|
79
|
+
# end #=> does nothing
|
80
|
+
#
|
81
|
+
# @!method map(&block)
|
82
|
+
# Maps the given block to the value from this +Success+ or
|
83
|
+
# returns this if this is a +Failure+.
|
84
|
+
# @yieldparam [any] value
|
85
|
+
# @yieldreturn [any]
|
86
|
+
# @example
|
87
|
+
# Success(42).map { |v| v/2 } #=> Success(21)
|
88
|
+
# Failure(ArgumentError.new).map { |v| v/2 } #=> Failure(ArgumentError.new)
|
89
|
+
#
|
90
|
+
# @!method flat_map(&block)
|
91
|
+
# Returns the given block applied to the value from this +Success+
|
92
|
+
# or returns this if this is a +Failure+.
|
93
|
+
# @yieldparam [any] value
|
94
|
+
# @yieldreturn [Try]
|
95
|
+
# @return [Try]
|
96
|
+
# @example
|
97
|
+
# Success(42).flat_map { |v| Success(v/2) }
|
98
|
+
# #=> Success(21)
|
99
|
+
# Failure(ArgumentError.new).flat_map { |v| Success(v/2) }
|
100
|
+
# #=> Failure(ArgumentError.new)
|
101
|
+
#
|
102
|
+
# @!method to_a
|
103
|
+
# Returns an +Array+ containing the +Success+ value or an
|
104
|
+
# empty +Array+ if this is a +Failure+.
|
105
|
+
# @return [Array]
|
106
|
+
# @example
|
107
|
+
# Success(42).to_a #=> [21]
|
108
|
+
# Failure(ArgumentError.new).to_a #=> []
|
109
|
+
#
|
110
|
+
# @!method to_option
|
111
|
+
# Returns an +Some+ containing the +Success+ value or a +None+ if
|
112
|
+
# this is a +Failure+.
|
113
|
+
# @return [Option]
|
114
|
+
# @example
|
115
|
+
# Success(42).to_option #=> Some(21)
|
116
|
+
# Failure(ArgumentError.new).to_option #=> None()
|
117
|
+
#
|
118
|
+
# @!method any?(&predicate)
|
119
|
+
# Returns +false+ if +Failure+ or returns the result of the
|
120
|
+
# application of the given predicate to the +Success+ value.
|
121
|
+
# @yieldparam [any] value
|
122
|
+
# @yieldreturn [Boolean]
|
123
|
+
# @return [Boolean]
|
124
|
+
# @example
|
125
|
+
# Success(12).any?( |v| v > 10) #=> true
|
126
|
+
# Success(7).any?( |v| v > 10) #=> false
|
127
|
+
# Failure(ArgumentError.new).any?( |v| v > 10) #=> false
|
128
|
+
#
|
129
|
+
# ---
|
130
|
+
#
|
131
|
+
# @!method success?
|
132
|
+
# Returns +true+ if it is a +Success+, +false+ otherwise.
|
133
|
+
# @return [Boolean]
|
134
|
+
#
|
135
|
+
# @!method failure?
|
136
|
+
# Returns +true+ if it is a +Failure+, +false+ otherwise.
|
137
|
+
# @return [Boolean]
|
138
|
+
#
|
139
|
+
# @!method get
|
140
|
+
# Returns the value from this +Success+ or raise the exception
|
141
|
+
# if this is a +Failure+.
|
142
|
+
# @return [any]
|
143
|
+
# @example
|
144
|
+
# Success(42).get #=> 42
|
145
|
+
# Failure(ArgumentError.new).get #=> ArgumentError: ArgumentError
|
146
|
+
#
|
147
|
+
# @!method or_else(&default)
|
148
|
+
# Returns this +Try+ if it's a +Success+ or the given default
|
149
|
+
# argument if this is a +Failure+.
|
150
|
+
# @return [Try]
|
151
|
+
# @example
|
152
|
+
# Success(42).or_else { -1 } #=> Success(42)
|
153
|
+
# Failure(ArgumentError.new).or_else { -1 } #=> Success(-1)
|
154
|
+
# Failure(ArgumentError.new).or_else { 1/0 } #=> Failure(ZeroDivisionError.new('divided by 0'))
|
155
|
+
#
|
156
|
+
# @!method flatten
|
157
|
+
# Transforms a nested +Try+, ie, a +Success+ of +Success+,
|
158
|
+
# into an un-nested +Try+, ie, a +Success+.
|
159
|
+
# @return [Try]
|
160
|
+
# @example
|
161
|
+
# Success(42).flatten #=> Success(42)
|
162
|
+
# Success(Success(42)).flatten #=> Success(42)
|
163
|
+
# Success(Failure(ArgumentError.new)).flatten #=> Failure(ArgumentError.new)
|
164
|
+
# Failure(ArgumentError.new).flatten { -1 } #=> Failure(ArgumentError.new)
|
165
|
+
#
|
166
|
+
# @!method select(&predicate)
|
167
|
+
# Converts this to a +Failure+ if the predicate is not satisfied.
|
168
|
+
# @yieldparam [any] value
|
169
|
+
# @yieldreturn [Boolean]
|
170
|
+
# @return [Try]
|
171
|
+
# @example
|
172
|
+
# Success(42).select { |v| v > 40 }
|
173
|
+
# #=> Success(21)
|
174
|
+
# Success(42).select { |v| v < 40 }
|
175
|
+
# #=> Failure(Fear::NoSuchElementError.new("Predicate does not hold for 42"))
|
176
|
+
# Failure(ArgumentError.new).select { |v| v < 40 }
|
177
|
+
# #=> Failure(ArgumentError.new)
|
178
|
+
#
|
179
|
+
# @!method recover_with(&block)
|
180
|
+
# Applies the given block to exception. This is like +flat_map+
|
181
|
+
# for the exception.
|
182
|
+
# @yieldparam [Exception] exception
|
183
|
+
# @yieldreturn [Try]
|
184
|
+
# @return [Try]
|
185
|
+
# @example
|
186
|
+
# Success(42).recover_with { |e| Success(e.massage) }
|
187
|
+
# #=> Success(42)
|
188
|
+
# Failure(ArgumentError.new).recover_with { |e| Success(e.massage) }
|
189
|
+
# #=> Success('ArgumentError')
|
190
|
+
# Failure(ArgumentError.new).recover_with { |e| fail }
|
191
|
+
# #=> Failure(RuntimeError)
|
192
|
+
#
|
193
|
+
# @!method recover(&block)
|
194
|
+
# Applies the given block to exception. This is like +map+ for the exception.
|
195
|
+
# @yieldparam [Exception] exception
|
196
|
+
# @yieldreturn [any]
|
197
|
+
# @return [Try]
|
198
|
+
# @example #recover
|
199
|
+
# Success(42).recover { |e| e.massage }
|
200
|
+
# #=> Success(42)
|
201
|
+
# Failure(ArgumentError.new).recover { |e| e.massage }
|
202
|
+
# #=> Success('ArgumentError')
|
203
|
+
# Failure(ArgumentError.new).recover { |e| fail }
|
204
|
+
# #=> Failure(RuntimeError)
|
205
|
+
#
|
206
|
+
# @!method to_either
|
207
|
+
# Returns +Left+ with exception if this is a +Failure+, otherwise
|
208
|
+
# returns +Right+ with +Success+ value.
|
209
|
+
# @return [Right<any>, Left<StandardError>]
|
210
|
+
# @example
|
211
|
+
# Success(42).to_either #=> Right(42)
|
212
|
+
# Failure(ArgumentError.new).to_either #=> Left(ArgumentError.new)
|
79
213
|
#
|
80
214
|
# @author based on Twitter's original implementation.
|
81
215
|
# @see https://github.com/scala/scala/blob/2.11.x/src/library/scala/util/Try.scala
|
82
216
|
#
|
83
217
|
module Try
|
218
|
+
# @private
|
84
219
|
def left_class
|
85
220
|
Failure
|
86
221
|
end
|
87
222
|
|
223
|
+
# @private
|
88
224
|
def right_class
|
89
225
|
Success
|
90
226
|
end
|
91
227
|
|
92
|
-
#
|
93
|
-
#
|
228
|
+
# Include this mixin to access convenient factory methods.
|
229
|
+
# @example
|
230
|
+
# include Fear::Try::Mixin
|
231
|
+
#
|
232
|
+
# Try { 4/2 } #=> #<Fear::Success value=2>
|
233
|
+
# Try { 4/0 } #=> #<Fear::Failure value=#<ZeroDivisionError: divided by 0>>
|
234
|
+
# Success(2) #=> #<Fear::Success value=2>
|
94
235
|
#
|
95
|
-
def failure?
|
96
|
-
!success?
|
97
|
-
end
|
98
|
-
|
99
236
|
module Mixin
|
100
|
-
# Constructs a
|
101
|
-
# method will ensure any non-fatal exception is caught and a
|
102
|
-
#
|
237
|
+
# Constructs a +Try+ using the block. This
|
238
|
+
# method will ensure any non-fatal exception )is caught and a
|
239
|
+
# +Failure+ object is returned.
|
103
240
|
# @return [Try]
|
104
241
|
#
|
105
242
|
def Try
|
106
243
|
Success.new(yield)
|
107
|
-
rescue
|
244
|
+
rescue => error
|
108
245
|
Failure.new(error)
|
109
246
|
end
|
110
247
|
|
data/lib/fear/utils.rb
CHANGED
data/lib/fear/version.rb
CHANGED
data/spec/fear/failure_spec.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
RSpec.describe Fear::Failure do
|
2
|
-
let(:
|
2
|
+
let(:exception) { RuntimeError.new('error') }
|
3
|
+
let(:failure) { described_class.new(exception) }
|
3
4
|
|
4
5
|
it_behaves_like Fear::RightBiased::Left do
|
5
6
|
let(:left) { failure }
|
@@ -75,4 +76,9 @@ RSpec.describe Fear::Failure do
|
|
75
76
|
it { expect { recover.get }.to raise_error(RuntimeError, 'unexpected error') }
|
76
77
|
end
|
77
78
|
end
|
79
|
+
|
80
|
+
describe '#to_either' do
|
81
|
+
subject { failure.to_either }
|
82
|
+
it { is_expected.to eq(Fear::Left.new(exception)) }
|
83
|
+
end
|
78
84
|
end
|
data/spec/fear/left_spec.rb
CHANGED
@@ -17,9 +17,9 @@ RSpec.describe Fear::Left do
|
|
17
17
|
it { is_expected.to be_left }
|
18
18
|
end
|
19
19
|
|
20
|
-
describe '#
|
20
|
+
describe '#select_or_else' do
|
21
21
|
subject do
|
22
|
-
left.
|
22
|
+
left.select_or_else(default) { |v| v == 'value' }
|
23
23
|
end
|
24
24
|
|
25
25
|
context 'proc default' do
|
@@ -39,6 +39,16 @@ RSpec.describe Fear::Left do
|
|
39
39
|
end
|
40
40
|
end
|
41
41
|
|
42
|
+
describe '#select' do
|
43
|
+
subject do
|
44
|
+
left.select { |v| v == 'value' }
|
45
|
+
end
|
46
|
+
|
47
|
+
it 'return self' do
|
48
|
+
is_expected.to eq(left)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
42
52
|
describe '#swap' do
|
43
53
|
subject { left.swap }
|
44
54
|
it { is_expected.to eq(Right('value')) }
|
data/spec/fear/none_spec.rb
CHANGED
@@ -7,16 +7,19 @@ RSpec.describe Fear::None do
|
|
7
7
|
|
8
8
|
subject(:none) { None() }
|
9
9
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
end.to raise_error(NoMethodError)
|
10
|
+
describe '#get' do
|
11
|
+
subject { proc { none.get } }
|
12
|
+
it { is_expected.to raise_error(Fear::NoSuchElementError) }
|
14
13
|
end
|
15
14
|
|
16
|
-
|
17
|
-
|
15
|
+
describe '#or_nil' do
|
16
|
+
subject { none.or_nil }
|
17
|
+
it { is_expected.to eq(nil) }
|
18
|
+
end
|
18
19
|
|
19
|
-
|
20
|
+
describe '#empty?' do
|
21
|
+
subject { none.empty? }
|
22
|
+
it { is_expected.to eq(true) }
|
20
23
|
end
|
21
24
|
|
22
25
|
describe '#select' do
|
data/spec/fear/option_spec.rb
CHANGED
@@ -1,32 +1,15 @@
|
|
1
1
|
RSpec.describe Fear::Option do
|
2
2
|
include Fear::Option::Mixin
|
3
3
|
|
4
|
-
describe 'Option()' do
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
expect(option).to be_kind_of(Fear::Some)
|
9
|
-
end
|
10
|
-
|
11
|
-
it 'returns None if value is nil' do
|
12
|
-
option = Option(nil)
|
13
|
-
|
14
|
-
expect(option).to be_kind_of(Fear::None)
|
15
|
-
end
|
16
|
-
end
|
17
|
-
|
18
|
-
let(:some) { Some(42) }
|
19
|
-
let(:none) { None() }
|
20
|
-
|
21
|
-
describe '#empty?' do
|
22
|
-
context 'Some' do
|
23
|
-
subject { some.empty? }
|
24
|
-
it { is_expected.to eq(false) }
|
4
|
+
describe '#Option()' do
|
5
|
+
context 'value is nil' do
|
6
|
+
subject { Option(nil) }
|
7
|
+
it { is_expected.to eq(None()) }
|
25
8
|
end
|
26
9
|
|
27
|
-
context '
|
28
|
-
subject {
|
29
|
-
it { is_expected.to eq(
|
10
|
+
context 'value is not nil' do
|
11
|
+
subject { Option(42) }
|
12
|
+
it { is_expected.to eq(Some(42)) }
|
30
13
|
end
|
31
14
|
end
|
32
15
|
end
|
data/spec/fear/right_spec.rb
CHANGED
@@ -15,8 +15,8 @@ RSpec.describe Fear::Right do
|
|
15
15
|
it { is_expected.not_to be_left }
|
16
16
|
end
|
17
17
|
|
18
|
-
describe '#
|
19
|
-
subject { right.
|
18
|
+
describe '#select_or_else' do
|
19
|
+
subject { right.select_or_else(default, &predicate) }
|
20
20
|
|
21
21
|
context 'predicate evaluates to true' do
|
22
22
|
let(:predicate) { ->(v) { v == 'value' } }
|
@@ -37,6 +37,20 @@ RSpec.describe Fear::Right do
|
|
37
37
|
end
|
38
38
|
end
|
39
39
|
|
40
|
+
describe '#select' do
|
41
|
+
subject { right.select(&predicate) }
|
42
|
+
|
43
|
+
context 'predicate evaluates to true' do
|
44
|
+
let(:predicate) { ->(v) { v == 'value' } }
|
45
|
+
it { is_expected.to eq(right) }
|
46
|
+
end
|
47
|
+
|
48
|
+
context 'predicate evaluates to false' do
|
49
|
+
let(:predicate) { ->(v) { v != 'value' } }
|
50
|
+
it { is_expected.to eq(Fear::Left.new('value')) }
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
40
54
|
describe '#swap' do
|
41
55
|
subject { right.swap }
|
42
56
|
it { is_expected.to eq(Fear::Left.new('value')) }
|
data/spec/fear/some_spec.rb
CHANGED
@@ -5,8 +5,7 @@ RSpec.describe Fear::Some do
|
|
5
5
|
let(:right) { described_class.new('value') }
|
6
6
|
end
|
7
7
|
|
8
|
-
subject(:some) { Some(
|
9
|
-
let(:value) { 42 }
|
8
|
+
subject(:some) { Some(42) }
|
10
9
|
|
11
10
|
describe '#select' do
|
12
11
|
subject { some.select(&predicate) }
|
@@ -36,13 +35,18 @@ RSpec.describe Fear::Some do
|
|
36
35
|
end
|
37
36
|
end
|
38
37
|
|
39
|
-
|
40
|
-
|
38
|
+
describe '#get' do
|
39
|
+
subject { some.get }
|
40
|
+
it { is_expected.to eq(42) }
|
41
41
|
end
|
42
42
|
|
43
|
-
|
44
|
-
|
43
|
+
describe '#or_nil' do
|
44
|
+
subject { some.or_nil }
|
45
|
+
it { is_expected.to eq(42) }
|
46
|
+
end
|
45
47
|
|
46
|
-
|
48
|
+
describe '#empty?' do
|
49
|
+
subject { some.empty? }
|
50
|
+
it { is_expected.to eq(false) }
|
47
51
|
end
|
48
52
|
end
|
data/spec/fear/success_spec.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: fear
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Tema Bolshakov
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-12-
|
11
|
+
date: 2016-12-10 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: dry-equalizer
|
@@ -105,6 +105,7 @@ files:
|
|
105
105
|
- ".rspec"
|
106
106
|
- ".rubocop.yml"
|
107
107
|
- ".travis.yml"
|
108
|
+
- ".yardopts"
|
108
109
|
- Gemfile
|
109
110
|
- LICENSE.txt
|
110
111
|
- README.md
|
@@ -136,7 +137,7 @@ files:
|
|
136
137
|
- spec/fear/success_spec.rb
|
137
138
|
- spec/fear/utils_spec.rb
|
138
139
|
- spec/spec_helper.rb
|
139
|
-
homepage: https://github.com/bolshakov/
|
140
|
+
homepage: https://github.com/bolshakov/fear
|
140
141
|
licenses:
|
141
142
|
- MIT
|
142
143
|
metadata: {}
|