Class: Literal::Enum
- Inherits:
-
Object
show all
- Extended by:
- Enumerable, Properties
- Defined in:
- lib/literal/enum.rb
Constant Summary
Constants included
from Types
Types::CallableType, Types::LambdaType, Types::NilableBooleanType, Types::NilableCallableType, Types::NilableJSONDataType, Types::NilableLambdaType, Types::NilableProcableType, Types::ProcableType
Class Attribute Summary collapse
Instance Attribute Summary collapse
Class Method Summary
collapse
-
.[](value) ⇒ Object
(also: cast)
-
.__after_defined__ ⇒ Object
-
._load(data) ⇒ Object
-
.at_position(n) ⇒ Object
-
.coerce(value) ⇒ Object
-
.const_added(name) ⇒ Object
-
.each ⇒ Object
-
.each_value ⇒ Object
-
.fetch ⇒ Object
-
.find_by(**kwargs) ⇒ Object
-
.index(name, type, unique: true, &block) ⇒ Object
-
.inherited(subclass) ⇒ Object
-
.names ⇒ Object
-
.new(*args, **kwargs, &block) ⇒ Object
-
.position_of(member) ⇒ Object
-
.prop(name, type, kind = :keyword, reader: :public, predicate: false, default: nil) ⇒ Object
-
.to_h ⇒ Object
-
.to_proc ⇒ Object
-
.values ⇒ Object
-
.where(**kwargs) ⇒ Object
Instance Method Summary
collapse
Methods included from Properties
extended, initialize, literal_properties, prop
Methods included from Types
#_Any, #_Any?, #_Array, #_Array?, #_Boolean, #_Boolean?, #_Callable, #_Callable?, #_Class, #_Class?, #_Constraint, #_Constraint?, #_Date, #_Date?, #_Deferred, #_Deferred?, #_Descendant, #_Descendant?, #_Enumerable, #_Enumerable?, #_Falsy, #_Float, #_Float?, #_Frozen, #_Frozen?, #_Hash, #_Hash?, #_Integer, #_Integer?, #_Interface, #_Interface?, #_Intersection, #_Intersection?, #_JSONData, #_JSONData?, #_Lambda, #_Lambda?, #_Map, #_Map?, #_Never, #_Nilable, #_Not, #_Pattern, #_Predicate, #_Procable, #_Procable?, #_Range, #_Range?, #_Set, #_Set?, #_String, #_String?, #_Symbol, #_Symbol?, #_Time, #_Time?, #_Truthy, #_Tuple, #_Tuple?, #_Union, #_Union?, #_Unit, #_Unit?, #_Void
Class Attribute Details
Returns the value of attribute members.
9
10
11
|
# File 'lib/literal/enum.rb', line 9
def members
@members
end
|
Instance Attribute Details
#__position__ ⇒ Object
Returns the value of attribute __position__.
238
239
240
|
# File 'lib/literal/enum.rb', line 238
def __position__
@__position__
end
|
Class Method Details
.[](value) ⇒ Object
Also known as:
cast
152
153
154
|
# File 'lib/literal/enum.rb', line 152
def [](value)
@values[value]
end
|
.__after_defined__ ⇒ Object
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
|
# File 'lib/literal/enum.rb', line 116
def __after_defined__
raise ArgumentError if frozen?
if RUBY_VERSION < "3.2"
constants(false).each { |name| const_added(name) }
end
@indexes_definitions.each do |name, (type, unique, block)|
index = @members.group_by(&block).freeze
index.each do |key, values|
unless type === key
raise Literal::TypeError.expected(key, to_be_a: type)
end
if unique && values.size > 1
raise ArgumentError.new("The index #{name} is not unique.")
end
end
@indexes[name] = index
end
@values.freeze
@members.freeze
freeze
end
|
._load(data) ⇒ Object
80
81
82
|
# File 'lib/literal/enum.rb', line 80
def _load(data)
self[Marshal.load(data)]
end
|
.at_position(n) ⇒ Object
41
42
43
|
# File 'lib/literal/enum.rb', line 41
def at_position(n)
@members[n]
end
|
.coerce(value) ⇒ Object
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
|
# File 'lib/literal/enum.rb', line 162
def coerce(value)
case value
when self
value
when Symbol
self[value] || begin
const_get(value)
rescue NameError
raise ArgumentError.new(
"Can't coerce #{value.inspect} into a #{inspect}."
)
end
else
self[value] || raise(
ArgumentError.new(
"Can't coerce #{value.inspect} into a #{inspect}."
)
)
end
end
|
.const_added(name) ⇒ Object
84
85
86
87
88
89
90
91
92
93
94
|
# File 'lib/literal/enum.rb', line 84
def const_added(name)
raise ArgumentError if frozen?
object = const_get(name)
if self === object
@names[object] = name
predicate_name = name.to_s.gsub(/(?<=[A-Z])(?=[A-Z][a-z])|(?<=[a-z\d])(?=[A-Z])/, "_").downcase
define_method("#{predicate_name}?") { self == object }
object.freeze
end
end
|
144
145
146
|
# File 'lib/literal/enum.rb', line 144
def each
@members.each { |member| yield(member) }
end
|
.each_value ⇒ Object
148
149
150
|
# File 'lib/literal/enum.rb', line 148
def each_value(&)
@values.each_key(&)
end
|
158
159
160
|
# File 'lib/literal/enum.rb', line 158
def fetch(...)
@values.fetch(...)
end
|
.find_by(**kwargs) ⇒ Object
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
|
# File 'lib/literal/enum.rb', line 63
def find_by(**kwargs)
unless kwargs.length == 1
raise ArgumentError.new("You can only specify one index when using `where`.")
end
key, value = kwargs.first
unless @indexes_definitions.fetch(key)[1]
raise ArgumentError.new("You can only use `find_by` on unique indexes.")
end
type = @indexes_definitions.fetch(key)[0]
Literal.check(value, type)
@indexes.fetch(key)[value]&.first
end
|
.index(name, type, unique: true, &block) ⇒ Object
45
46
47
|
# File 'lib/literal/enum.rb', line 45
def index(name, type, unique: true, &block)
@indexes_definitions[name] = [type, unique, block || name.to_proc]
end
|
.inherited(subclass) ⇒ Object
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
|
# File 'lib/literal/enum.rb', line 18
def inherited(subclass)
subclass.instance_exec do
@values = {}
@members = []
@indexes_definitions = {}
@indexes = {}
@names = {}
end
if subclass.name && RUBY_ENGINE != "truffleruby"
TracePoint.trace(:end) do |tp|
if tp.self == subclass
tp.self.__after_defined__
tp.disable
end
end
end
end
|
12
|
# File 'lib/literal/enum.rb', line 12
def names = @names
|
.new(*args, **kwargs, &block) ⇒ Object
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
|
# File 'lib/literal/enum.rb', line 96
def new(*args, **kwargs, &block)
raise ArgumentError if frozen?
new_object = super(*args, **kwargs, &nil)
if @values.key?(new_object.value)
raise ArgumentError.new("The value #{new_object.value} is already used by #{@values[new_object.value].name}.")
end
@values[new_object.value] = new_object
new_object.instance_variable_set(:@__position__, @members.length)
@members << new_object
new_object.instance_exec(&block) if block
new_object
end
|
.position_of(member) ⇒ Object
37
38
39
|
# File 'lib/literal/enum.rb', line 37
def position_of(member)
coerce(member).__position__
end
|
.prop(name, type, kind = :keyword, reader: :public, predicate: false, default: nil) ⇒ Object
14
15
16
|
# File 'lib/literal/enum.rb', line 14
def prop(name, type, kind = :keyword, reader: :public, predicate: false, default: nil)
super(name, type, kind, reader:, writer: false, predicate:, default:)
end
|
187
188
189
190
191
192
193
|
# File 'lib/literal/enum.rb', line 187
def to_h(&)
if block_given?
@members.to_h(&)
else
@members.to_h { |it| [it, it.value] }
end
end
|
183
184
185
|
# File 'lib/literal/enum.rb', line 183
def to_proc
method(:coerce).to_proc
end
|
11
|
# File 'lib/literal/enum.rb', line 11
def values = @values.keys
|
.where(**kwargs) ⇒ Object
49
50
51
52
53
54
55
56
57
58
59
60
61
|
# File 'lib/literal/enum.rb', line 49
def where(**kwargs)
unless kwargs.length == 1
raise ArgumentError.new("You can only specify one index when using `where`.")
end
key, value = kwargs.first
types = @indexes_definitions.fetch(key)
type = types.first
Literal.check(value, type) { |c| raise NotImplementedError }
@indexes.fetch(key)[value]
end
|
Instance Method Details
#<=>(other) ⇒ Object
217
218
219
220
221
222
223
224
|
# File 'lib/literal/enum.rb', line 217
def <=>(other)
case other
when self.class
@__position__ <=> other.__position__
else
raise ArgumentError.new("Can't compare instances of #{other.class} to instances of #{self.class}")
end
end
|
#_dump(level) ⇒ Object
213
214
215
|
# File 'lib/literal/enum.rb', line 213
def _dump(level)
Marshal.dump(@value)
end
|
#deconstruct ⇒ Object
204
205
206
|
# File 'lib/literal/enum.rb', line 204
def deconstruct
[@value]
end
|
#deconstruct_keys(keys) ⇒ Object
208
209
210
211
|
# File 'lib/literal/enum.rb', line 208
def deconstruct_keys(keys)
h = to_h
keys ? h.slice(*keys) : h
end
|
#name ⇒ Object
Also known as:
inspect, to_s
196
197
198
199
|
# File 'lib/literal/enum.rb', line 196
def name
klass = self.class
"#{klass.name}::#{klass.names[self]}"
end
|
230
231
232
233
234
235
236
|
# File 'lib/literal/enum.rb', line 230
def pred
if @__position__ <= 0
nil
else
self.class.members[@__position__ - 1]
end
end
|
226
227
228
|
# File 'lib/literal/enum.rb', line 226
def succ
self.class.members[@__position__ + 1]
end
|