functional-light-service 0.5.4 → 6.0.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/.github/workflows/project-build.yml +35 -11
- data/.rubocop.yml +101 -160
- data/AUDIT-functional-light-service.md +352 -0
- data/CHANGELOG.md +38 -0
- data/README.md +54 -2
- data/audit/bench.rb +99 -0
- data/audit/verify_findings.rb +172 -0
- data/functional-light-service.gemspec +15 -21
- data/lib/functional-light-service/action.rb +97 -101
- data/lib/functional-light-service/configuration.rb +26 -24
- data/lib/functional-light-service/context/key_verifier.rb +124 -118
- data/lib/functional-light-service/context.rb +63 -20
- data/lib/functional-light-service/deprecations.rb +26 -0
- data/lib/functional-light-service/errors.rb +8 -6
- data/lib/functional-light-service/functional/enum.rb +286 -250
- data/lib/functional-light-service/functional/maybe.rb +21 -15
- data/lib/functional-light-service/functional/monad.rb +77 -66
- data/lib/functional-light-service/functional/null.rb +88 -74
- data/lib/functional-light-service/functional/option.rb +100 -97
- data/lib/functional-light-service/functional/result.rb +129 -116
- data/lib/functional-light-service/localization_adapter.rb +48 -47
- data/lib/functional-light-service/organizer/execute.rb +16 -14
- data/lib/functional-light-service/organizer/iterate.rb +30 -25
- data/lib/functional-light-service/organizer/reduce_if.rb +19 -17
- data/lib/functional-light-service/organizer/reduce_until.rb +22 -20
- data/lib/functional-light-service/organizer/scoped_reducable.rb +15 -13
- data/lib/functional-light-service/organizer/with_callback.rb +28 -26
- data/lib/functional-light-service/organizer/with_reducer.rb +81 -77
- data/lib/functional-light-service/organizer/with_reducer_factory.rb +20 -18
- data/lib/functional-light-service/organizer/with_reducer_log_decorator.rb +110 -108
- data/lib/functional-light-service/organizer.rb +114 -114
- data/lib/functional-light-service/testing/context_factory.rb +48 -42
- data/lib/functional-light-service/testing.rb +3 -1
- data/lib/functional-light-service/version.rb +5 -3
- data/lib/functional-light-service.rb +30 -28
- data/spec/acceptance/after_actions_spec.rb +87 -71
- data/spec/acceptance/before_actions_spec.rb +115 -98
- data/spec/acceptance/custom_log_from_organizer_spec.rb +61 -60
- data/spec/acceptance/deprecation_warnings_spec.rb +82 -0
- data/spec/acceptance/fail_spec.rb +52 -50
- data/spec/acceptance/message_localization_spec.rb +119 -118
- data/spec/acceptance/organizer/context_failure_and_skipping_spec.rb +68 -65
- data/spec/acceptance/organizer/reduce_if_spec.rb +89 -89
- data/spec/acceptance/organizer/with_callback_spec.rb +113 -110
- data/spec/acceptance/{not_having_call_method_warning_spec.rb → organizer_entry_point_spec.rb} +10 -7
- data/spec/acceptance/rollback_spec.rb +183 -132
- data/spec/action_expects_and_promises_spec.rb +97 -93
- data/spec/action_promised_keys_spec.rb +126 -122
- data/spec/context_spec.rb +289 -197
- data/spec/examples/controller_spec.rb +63 -63
- data/spec/examples/validate_address_spec.rb +38 -37
- data/spec/lib/deterministic/currify_spec.rb +90 -88
- data/spec/lib/deterministic/null_spec.rb +6 -1
- data/spec/lib/deterministic/option_spec.rb +140 -137
- data/spec/lib/deterministic/result/result_map_spec.rb +155 -154
- data/spec/lib/deterministic/result/result_shared.rb +3 -2
- data/spec/lib/deterministic/result_spec.rb +2 -2
- data/spec/lib/edge_cases_spec.rb +156 -0
- data/spec/lib/enum_spec.rb +1 -1
- data/spec/lib/native_pattern_matching_spec.rb +74 -0
- data/spec/organizer_spec.rb +115 -114
- data/spec/readme_spec.rb +45 -47
- data/spec/sample/calculates_order_tax_action_spec.rb +16 -16
- data/spec/sample/calculates_tax_spec.rb +1 -1
- data/spec/sample/looks_up_tax_percentage_action_spec.rb +55 -55
- data/spec/sample/tax/calculates_order_tax_action.rb +10 -9
- data/spec/sample/tax/looks_up_tax_percentage_action.rb +28 -27
- data/spec/sample/tax/provides_free_shipping_action.rb +11 -10
- data/spec/spec_helper.rb +6 -0
- data/spec/test_doubles.rb +628 -599
- data/spec/testing/context_factory_spec.rb +21 -0
- metadata +45 -161
- data/lib/functional-light-service/organizer/verify_call_method_exists.rb +0 -29
- data/spec/acceptance/include_warning_spec.rb +0 -29
|
@@ -1,250 +1,286 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
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
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
end
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module FunctionalLightService
|
|
4
|
+
module Enum
|
|
5
|
+
class MatchError < StandardError; end
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
class EnumBuilder
|
|
9
|
+
def initialize(parent)
|
|
10
|
+
@parent = parent
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
class DataType
|
|
14
|
+
module AnyEnum
|
|
15
|
+
include FunctionalLightService::Monad
|
|
16
|
+
|
|
17
|
+
def match(&)
|
|
18
|
+
parent.match(self, &)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def to_s
|
|
22
|
+
value.to_s
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def name
|
|
26
|
+
self.class.name.split("::")[-1]
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
# Returns array. Will fail on Nullary objects.
|
|
30
|
+
# TODO: define a Unary module so we can define this method differently on Unary vs Binary
|
|
31
|
+
def wrapped_values
|
|
32
|
+
if is_a?(FunctionalLightService::EnumBuilder::DataType::Binary)
|
|
33
|
+
value.values
|
|
34
|
+
else
|
|
35
|
+
[value]
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
# Supporto al pattern matching nativo di Ruby (case/in):
|
|
40
|
+
# case result
|
|
41
|
+
# in FunctionalLightService::Result::Success(s) then ...
|
|
42
|
+
# in FunctionalLightService::Result::Failure(f) then ...
|
|
43
|
+
# end
|
|
44
|
+
def deconstruct
|
|
45
|
+
is_a?(FunctionalLightService::EnumBuilder::DataType::Nullary) ? [] : wrapped_values
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def deconstruct_keys(_keys)
|
|
49
|
+
if is_a?(FunctionalLightService::EnumBuilder::DataType::Binary)
|
|
50
|
+
value.dup
|
|
51
|
+
elsif is_a?(FunctionalLightService::EnumBuilder::DataType::Nullary)
|
|
52
|
+
{}
|
|
53
|
+
else
|
|
54
|
+
{ args[0] => value }
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
module Nullary
|
|
60
|
+
def initialize(*_args)
|
|
61
|
+
@value = nil
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def inspect
|
|
65
|
+
name
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
# TODO: this should probably be named Multary
|
|
70
|
+
module Binary
|
|
71
|
+
def initialize(*init)
|
|
72
|
+
unless (init.one? && init[0].is_a?(Hash)) || init.count == args.count
|
|
73
|
+
raise ArgumentError, "Expected arguments for #{args}, got #{init}"
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
@value = if init.one? && init[0].is_a?(Hash)
|
|
77
|
+
args.zip(init[0].values).to_h
|
|
78
|
+
else
|
|
79
|
+
args.zip(init).to_h
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
def inspect
|
|
84
|
+
params = value.map { |k, v| "#{k}: #{v.inspect}" }
|
|
85
|
+
"#{name}(#{params.join(', ')})"
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
# rubocop:disable Metrics/MethodLength
|
|
90
|
+
def self.create(parent, args)
|
|
91
|
+
if args.include? :value
|
|
92
|
+
raise ArgumentError, "#{args} may not contain the reserved name :value"
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
dt = Class.new(parent)
|
|
96
|
+
|
|
97
|
+
dt.instance_eval do
|
|
98
|
+
public_class_method :new
|
|
99
|
+
include AnyEnum
|
|
100
|
+
|
|
101
|
+
define_method(:args) { args }
|
|
102
|
+
|
|
103
|
+
define_method(:parent) { parent }
|
|
104
|
+
private :parent
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
case args.count
|
|
108
|
+
when 0
|
|
109
|
+
dt.instance_eval do
|
|
110
|
+
include Nullary
|
|
111
|
+
|
|
112
|
+
private :value
|
|
113
|
+
end
|
|
114
|
+
when 1
|
|
115
|
+
dt.instance_eval do
|
|
116
|
+
define_method(args[0].to_sym) { value }
|
|
117
|
+
end
|
|
118
|
+
else
|
|
119
|
+
dt.instance_eval do
|
|
120
|
+
include Binary
|
|
121
|
+
|
|
122
|
+
args.each do |m|
|
|
123
|
+
define_method(m) do
|
|
124
|
+
@value[m]
|
|
125
|
+
end
|
|
126
|
+
end
|
|
127
|
+
end
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
dt
|
|
131
|
+
end
|
|
132
|
+
# rubocop:enable Metrics/MethodLength
|
|
133
|
+
|
|
134
|
+
class << self
|
|
135
|
+
public :new
|
|
136
|
+
end
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
def method_missing(m, *args)
|
|
140
|
+
if @parent.const_defined?(m)
|
|
141
|
+
raise ArgumentError, "variant #{m} is already defined for this enum"
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
@parent.const_set(m, DataType.create(@parent, args))
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
def respond_to_missing?(_m, _include_all = false)
|
|
148
|
+
true
|
|
149
|
+
end
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
module_function
|
|
153
|
+
|
|
154
|
+
# rubocop:disable Metrics/AbcSize
|
|
155
|
+
# rubocop:disable Metrics/CyclomaticComplexity
|
|
156
|
+
# rubocop:disable Metrics/MethodLength
|
|
157
|
+
# rubocop:disable Metrics/PerceivedComplexity
|
|
158
|
+
def enum(&block)
|
|
159
|
+
mod = Class.new do # the enum to be built
|
|
160
|
+
private_class_method :new
|
|
161
|
+
|
|
162
|
+
def self.match(obj, &block)
|
|
163
|
+
# Binding#receiver: stesso risultato di binding.eval('self') senza eval
|
|
164
|
+
caller_ctx = block.binding.receiver
|
|
165
|
+
|
|
166
|
+
matcher = self::Matcher.new(obj)
|
|
167
|
+
matcher.instance_eval(&block)
|
|
168
|
+
|
|
169
|
+
# exhaustiveness check su classi memoizzate: niente split/sort di
|
|
170
|
+
# stringhe per chiamata
|
|
171
|
+
covered = matcher.matches.map { |e| e[1] }
|
|
172
|
+
missing = variant_classes.reject { |klass| covered.include?(klass) }
|
|
173
|
+
unless missing.empty?
|
|
174
|
+
missing_names = missing.map { |klass| klass.name.split('::')[-1].to_sym }
|
|
175
|
+
raise Enum::MatchError, "Match is non-exhaustive, #{missing_names} not covered"
|
|
176
|
+
end
|
|
177
|
+
|
|
178
|
+
type_matches = matcher.matches.select { |r| r[0].is_a?(r[1]) }
|
|
179
|
+
|
|
180
|
+
type_matches.each do |match|
|
|
181
|
+
obj, _type, block, args, guard = match
|
|
182
|
+
|
|
183
|
+
return caller_ctx.instance_eval(&block) if args.empty?
|
|
184
|
+
|
|
185
|
+
if args.count != obj.args.count
|
|
186
|
+
msg = "Pattern (#{args.join(', ')}) must match (#{obj.args.join(', ')})"
|
|
187
|
+
raise Enum::MatchError, msg
|
|
188
|
+
end
|
|
189
|
+
|
|
190
|
+
guard_ctx = guard_context(obj, args)
|
|
191
|
+
return caller_ctx.instance_exec(* obj.wrapped_values, &block) unless guard
|
|
192
|
+
|
|
193
|
+
if guard && guard_ctx.instance_exec(obj, &guard)
|
|
194
|
+
return caller_ctx.instance_exec(* obj.wrapped_values, &block)
|
|
195
|
+
end
|
|
196
|
+
end
|
|
197
|
+
|
|
198
|
+
raise Enum::MatchError, "No match could be made"
|
|
199
|
+
end
|
|
200
|
+
|
|
201
|
+
def self.variants
|
|
202
|
+
constants - %i[Matcher MatchError]
|
|
203
|
+
end
|
|
204
|
+
|
|
205
|
+
def self.variant_classes
|
|
206
|
+
@variant_classes ||= variants.map { |v| const_get(v) }.freeze
|
|
207
|
+
end
|
|
208
|
+
|
|
209
|
+
def self.guard_context(obj, args)
|
|
210
|
+
# Struct.new definisce una classe: va fatto una volta per firma,
|
|
211
|
+
# non a ogni match con guard
|
|
212
|
+
@guard_structs ||= {}
|
|
213
|
+
struct = @guard_structs[args] ||= Struct.new(*args)
|
|
214
|
+
|
|
215
|
+
if obj.is_a?(FunctionalLightService::EnumBuilder::DataType::Binary)
|
|
216
|
+
struct.new(*obj.value.values)
|
|
217
|
+
else
|
|
218
|
+
struct.new(obj.value)
|
|
219
|
+
end
|
|
220
|
+
end
|
|
221
|
+
end
|
|
222
|
+
enum = EnumBuilder.new(mod)
|
|
223
|
+
enum.instance_eval(&block)
|
|
224
|
+
|
|
225
|
+
type_variants = mod.constants
|
|
226
|
+
|
|
227
|
+
matcher = Class.new do
|
|
228
|
+
def initialize(obj)
|
|
229
|
+
@obj = obj
|
|
230
|
+
@matches = []
|
|
231
|
+
@vars = []
|
|
232
|
+
end
|
|
233
|
+
|
|
234
|
+
attr_reader :matches, :vars
|
|
235
|
+
|
|
236
|
+
def where(&guard)
|
|
237
|
+
guard
|
|
238
|
+
end
|
|
239
|
+
|
|
240
|
+
type_variants.each do |m|
|
|
241
|
+
define_method(m) do |guard = nil, &inner_block|
|
|
242
|
+
raise ArgumentError, "No block given to `#{m}`" if inner_block.nil?
|
|
243
|
+
|
|
244
|
+
params_spec = inner_block.parameters
|
|
245
|
+
if params_spec.any? { |spec| spec.size < 2 }
|
|
246
|
+
msg = "Unnamed param found in block parameters: #{params_spec.inspect}"
|
|
247
|
+
raise ArgumentError, msg
|
|
248
|
+
end
|
|
249
|
+
if params_spec.any? { |spec| spec[0] != :req && spec[0] != :opt }
|
|
250
|
+
msg = "Only :req & :opt params allowed; parameters=#{params_spec.inspect}"
|
|
251
|
+
raise ArgumentError, msg
|
|
252
|
+
end
|
|
253
|
+
|
|
254
|
+
args = params_spec.map { |spec| spec[1] }
|
|
255
|
+
|
|
256
|
+
type = mod.const_get(m)
|
|
257
|
+
|
|
258
|
+
guard = nil if guard && !guard.is_a?(Proc)
|
|
259
|
+
|
|
260
|
+
@matches << [@obj, type, inner_block, args, guard]
|
|
261
|
+
end
|
|
262
|
+
end
|
|
263
|
+
end
|
|
264
|
+
|
|
265
|
+
mod.const_set(:Matcher, matcher)
|
|
266
|
+
|
|
267
|
+
type_variants.each do |variant|
|
|
268
|
+
mod.singleton_class.class_exec do
|
|
269
|
+
define_method(variant) do |*args|
|
|
270
|
+
const_get(variant).new(*args)
|
|
271
|
+
end
|
|
272
|
+
end
|
|
273
|
+
end
|
|
274
|
+
mod
|
|
275
|
+
end
|
|
276
|
+
# rubocop:enable Metrics/AbcSize
|
|
277
|
+
# rubocop:enable Metrics/CyclomaticComplexity
|
|
278
|
+
# rubocop:enable Metrics/MethodLength
|
|
279
|
+
# rubocop:enable Metrics/PerceivedComplexity
|
|
280
|
+
|
|
281
|
+
def impl(enum_type, &block)
|
|
282
|
+
enum_type.variants.each do |v|
|
|
283
|
+
enum_type.const_get(v).class_eval(&block)
|
|
284
|
+
end
|
|
285
|
+
end
|
|
286
|
+
end
|
|
@@ -1,15 +1,21 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
class Object
|
|
4
|
+
def null?
|
|
5
|
+
false
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
def some?
|
|
9
|
+
true
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
# rubocop:disable Naming/MethodName
|
|
14
|
+
def Maybe(obj)
|
|
15
|
+
FunctionalLightService::Deprecations.warn(
|
|
16
|
+
"Maybe()/Null are deprecated and will be removed in a future release; " \
|
|
17
|
+
"use FunctionalLightService::Option (Some/None) instead"
|
|
18
|
+
)
|
|
19
|
+
obj.nil? ? Null.instance : obj
|
|
20
|
+
end
|
|
21
|
+
# rubocop:enable Naming/MethodName
|