philosophal 1.2.0 → 2.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/CHANGELOG.md +25 -1
- data/README.md +39 -0
- data/lib/philosophal/convertor.rb +9 -12
- data/lib/philosophal/loaders/json_loader.rb +4 -9
- data/lib/philosophal/properties/instance_methods.rb +76 -0
- data/lib/philosophal/properties/schema.rb +48 -0
- data/lib/philosophal/properties.rb +66 -88
- data/lib/philosophal/property.rb +162 -53
- data/lib/philosophal/transform.rb +8 -6
- data/lib/philosophal/types/array_of_type.rb +4 -3
- data/lib/philosophal/types/boolean_type.rb +1 -1
- data/lib/philosophal/types/hash_of_type.rb +8 -6
- data/lib/philosophal.rb +15 -17
- data/sig/manifest.yaml +5 -0
- data/sig/philosophal/convertor.rbs +35 -0
- data/sig/philosophal/errors/argument_error.rbs +4 -0
- data/sig/philosophal/errors/type_error.rbs +4 -0
- data/sig/philosophal/loaders/errors.rbs +6 -0
- data/sig/philosophal/loaders/json_loader.rbs +29 -0
- data/sig/philosophal/loaders.rbs +4 -0
- data/sig/philosophal/properties/instance_methods.rbs +26 -0
- data/sig/philosophal/properties/schema.rbs +47 -0
- data/sig/philosophal/properties.rbs +59 -0
- data/sig/philosophal/property.rbs +98 -0
- data/sig/philosophal/transform.rbs +7 -0
- data/sig/philosophal/types/any_type.rbs +9 -0
- data/sig/philosophal/types/array_of_type.rbs +23 -0
- data/sig/philosophal/types/boolean_type.rbs +11 -0
- data/sig/philosophal/types/hash_of_type.rbs +25 -0
- data/sig/philosophal/types.rbs +11 -0
- data/sig/philosophal.rbs +12 -0
- metadata +43 -14
- data/.rubocop.yml +0 -12
- data/.ruby-version +0 -1
- data/.tool-versions +0 -1
- data/Rakefile +0 -12
- data/VERSION +0 -1
data/lib/philosophal/property.rb
CHANGED
|
@@ -2,7 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
module Philosophal
|
|
4
4
|
class Property
|
|
5
|
-
def initialize(name:, type:, default:, transform:, immutable:, description:, json
|
|
5
|
+
def initialize(name:, type:, default:, transform:, immutable:, description:, json:, override:,
|
|
6
|
+
track_changes: false)
|
|
6
7
|
@name = name
|
|
7
8
|
@type = type
|
|
8
9
|
@default = default
|
|
@@ -10,9 +11,11 @@ module Philosophal
|
|
|
10
11
|
@immutable = immutable
|
|
11
12
|
@description = description
|
|
12
13
|
@json = json
|
|
14
|
+
@override = override
|
|
15
|
+
@track_changes = track_changes
|
|
13
16
|
end
|
|
14
17
|
|
|
15
|
-
attr_reader :name, :type, :default, :transform, :immutable, :description, :json
|
|
18
|
+
attr_reader :name, :type, :default, :transform, :immutable, :description, :json, :override, :track_changes
|
|
16
19
|
|
|
17
20
|
def json_name
|
|
18
21
|
return @json if @json.is_a?(Symbol)
|
|
@@ -35,61 +38,167 @@ module Philosophal
|
|
|
35
38
|
@transform != nil
|
|
36
39
|
end
|
|
37
40
|
|
|
41
|
+
def override?
|
|
42
|
+
@override
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def track_changes?
|
|
46
|
+
@track_changes
|
|
47
|
+
end
|
|
48
|
+
|
|
38
49
|
def check_conversion(value)
|
|
39
50
|
Philosophal.convert(self, value)
|
|
40
51
|
end
|
|
41
52
|
|
|
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
|
-
|
|
53
|
+
# The Convertor method (and subtype) for the type, looked up once since the type never changes.
|
|
54
|
+
def convert_method
|
|
55
|
+
return @convert_method if defined?(@convert_method)
|
|
56
|
+
|
|
57
|
+
@convert_method = Philosophal::Convertor.convert_method_for(@type)
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def method_generators
|
|
61
|
+
generators = {
|
|
62
|
+
writer_method_name => immutable ? :generate_immutable_writer_method : :generate_writer_method,
|
|
63
|
+
reader_method_name => default? ? :generate_reader_method : :generate_plain_reader_method
|
|
64
|
+
}
|
|
65
|
+
generators[boolean_method_name] = :generate_boolean_method if type == Philosophal::Types::BooleanType::Instance
|
|
66
|
+
generators[description_method_name] = :generate_description_method if description
|
|
67
|
+
generators.merge(change_tracking_generators)
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def change_tracking_generators
|
|
71
|
+
return {} unless track_changes?
|
|
72
|
+
|
|
73
|
+
{ was_method_name => :generate_was_method, changed_method_name => :generate_changed_method }
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
# Private constant of the generated methods module holding this property, so the writers
|
|
77
|
+
# reach it without looking it up in the schema.
|
|
78
|
+
def constant_name
|
|
79
|
+
return @constant_name if defined? @constant_name
|
|
80
|
+
|
|
81
|
+
@constant_name = :"PHILOSOPHAL_PROPERTY_#{@name.name}"
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
def writer_method_name
|
|
85
|
+
return @writer_method_name if defined? @writer_method_name
|
|
86
|
+
|
|
87
|
+
@writer_method_name = :"#{@name.name}="
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def generate_writer_method(buffer)
|
|
91
|
+
buffer << <<~RUBY
|
|
92
|
+
def #{writer_method_name.name}(value)
|
|
93
|
+
@#{@name.name} = #{constant_name}.check_conversion(value)
|
|
94
|
+
rescue Philosophal::TypeError => error
|
|
95
|
+
error.set_backtrace(caller(1))
|
|
96
|
+
raise
|
|
97
|
+
end
|
|
98
|
+
RUBY
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
def generate_immutable_writer_method(buffer)
|
|
102
|
+
buffer << <<~RUBY
|
|
103
|
+
def #{writer_method_name.name}(value)
|
|
104
|
+
raise FrozenError, "can't modify frozen variable @#{@name.name}" if defined?(@#{@name.name})
|
|
105
|
+
@#{@name.name} = #{constant_name}.check_conversion(value).freeze
|
|
106
|
+
rescue Philosophal::TypeError => error
|
|
107
|
+
error.set_backtrace(caller(1))
|
|
108
|
+
raise
|
|
109
|
+
end
|
|
110
|
+
RUBY
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
def reader_method_name
|
|
114
|
+
@name
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
def variable_name
|
|
118
|
+
return @variable_name if defined? @variable_name
|
|
119
|
+
|
|
120
|
+
@variable_name = :"@#{@name.name}"
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
# Without a default the reader only returns the variable: attr_reader is the fastest form.
|
|
124
|
+
# The default is not looked up, so a subclass redeclaring the property with a default and
|
|
125
|
+
# override: false keeps this reader and does not get its default (not supported).
|
|
126
|
+
def generate_plain_reader_method(buffer)
|
|
127
|
+
buffer << "attr_reader :#{reader_method_name.name}\n"
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
def generate_reader_method(buffer)
|
|
131
|
+
buffer << <<~RUBY
|
|
132
|
+
def #{reader_method_name.name}
|
|
133
|
+
@#{@name.name}.nil? ? #{constant_name}.default_value : @#{@name.name}
|
|
134
|
+
end
|
|
135
|
+
RUBY
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
def boolean_method_name
|
|
139
|
+
return @boolean_method_name if defined? @boolean_method_name
|
|
140
|
+
|
|
141
|
+
@boolean_method_name = :"#{@name.name}?"
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
def generate_boolean_method(buffer)
|
|
145
|
+
buffer << <<~RUBY
|
|
146
|
+
def #{boolean_method_name.name}
|
|
147
|
+
!!#{reader_method_name.name}
|
|
148
|
+
end
|
|
149
|
+
RUBY
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
def description_method_name
|
|
153
|
+
return @description_method_name if defined? @description_method_name
|
|
154
|
+
|
|
155
|
+
@description_method_name = :"#{@name.name}_description"
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
def was_method_name
|
|
159
|
+
return @was_method_name if defined? @was_method_name
|
|
160
|
+
|
|
161
|
+
@was_method_name = :"#{@name.name}_was"
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
def was_variable_name
|
|
165
|
+
return @was_variable_name if defined? @was_variable_name
|
|
166
|
+
|
|
167
|
+
@was_variable_name = :"@__philosophal_#{@name.name}_was__"
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
# Returns the stored value at the last changes_applied (nil before), without falling back to the default.
|
|
171
|
+
def generate_was_method(buffer)
|
|
172
|
+
buffer << <<~RUBY
|
|
173
|
+
def #{was_method_name.name}
|
|
174
|
+
#{was_variable_name}
|
|
175
|
+
end
|
|
176
|
+
RUBY
|
|
177
|
+
end
|
|
178
|
+
|
|
179
|
+
def changed_method_name
|
|
180
|
+
return @changed_method_name if defined? @changed_method_name
|
|
181
|
+
|
|
182
|
+
@changed_method_name = :"#{@name.name}_changed?"
|
|
183
|
+
end
|
|
184
|
+
|
|
185
|
+
# True when the stored value differs from the one recorded at the last changes_applied.
|
|
186
|
+
def generate_changed_method(buffer)
|
|
187
|
+
buffer << <<~RUBY
|
|
188
|
+
def #{changed_method_name.name}
|
|
189
|
+
@#{@name.name} != #{was_variable_name}
|
|
190
|
+
end
|
|
191
|
+
RUBY
|
|
192
|
+
end
|
|
193
|
+
|
|
194
|
+
# The description is read from the property constant rather than written into the generated code,
|
|
195
|
+
# so it is never evaluated as Ruby.
|
|
196
|
+
def generate_description_method(buffer)
|
|
197
|
+
buffer << <<~RUBY
|
|
198
|
+
def #{description_method_name.name}
|
|
199
|
+
#{constant_name}.description
|
|
200
|
+
end
|
|
201
|
+
RUBY
|
|
93
202
|
end
|
|
94
203
|
end
|
|
95
204
|
end
|
|
@@ -3,12 +3,14 @@
|
|
|
3
3
|
module Philosophal
|
|
4
4
|
class Transform
|
|
5
5
|
def self.make(method, value)
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
6
|
+
return method.call(value) if method.is_a?(Proc)
|
|
7
|
+
|
|
8
|
+
result = value.send(method)
|
|
9
|
+
self_method?(method) ? value : result
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def self.self_method?(method)
|
|
13
|
+
method.end_with?('!')
|
|
12
14
|
end
|
|
13
15
|
end
|
|
14
16
|
end
|
|
@@ -4,7 +4,7 @@ module Philosophal
|
|
|
4
4
|
module Types
|
|
5
5
|
class ArrayOfType
|
|
6
6
|
def self.instance(subtype)
|
|
7
|
-
memorization
|
|
7
|
+
memorization[subtype] ||= new(subtype).freeze
|
|
8
8
|
end
|
|
9
9
|
|
|
10
10
|
def self.memorization
|
|
@@ -13,15 +13,16 @@ module Philosophal
|
|
|
13
13
|
@memorization = {}
|
|
14
14
|
end
|
|
15
15
|
|
|
16
|
+
private_class_method :new
|
|
17
|
+
|
|
16
18
|
attr_reader :subtype
|
|
17
19
|
|
|
18
20
|
def initialize(subtype)
|
|
19
21
|
@subtype = subtype
|
|
20
|
-
self.class.memorization[subtype] = self
|
|
21
22
|
end
|
|
22
23
|
|
|
23
24
|
def ===(array)
|
|
24
|
-
array.is_a?(Array) &&
|
|
25
|
+
array.is_a?(Array) && array.all?(@subtype)
|
|
25
26
|
end
|
|
26
27
|
end
|
|
27
28
|
end
|
|
@@ -4,8 +4,7 @@ module Philosophal
|
|
|
4
4
|
module Types
|
|
5
5
|
class HashOfType
|
|
6
6
|
def self.instance(key_type, value_type)
|
|
7
|
-
|
|
8
|
-
memorization.fetch(Marshal.dump(subtype), new(subtype).freeze)
|
|
7
|
+
memorization[[key_type, value_type]] ||= new({ key_type:, value_type: }).freeze
|
|
9
8
|
end
|
|
10
9
|
|
|
11
10
|
def self.memorization
|
|
@@ -14,17 +13,20 @@ module Philosophal
|
|
|
14
13
|
@memorization = {}
|
|
15
14
|
end
|
|
16
15
|
|
|
16
|
+
private_class_method :new
|
|
17
|
+
|
|
17
18
|
attr_reader :subtype
|
|
18
19
|
|
|
19
20
|
def initialize(subtype)
|
|
20
21
|
@subtype = subtype.freeze
|
|
21
|
-
self.class.memorization[Marshal.dump(subtype)] = self
|
|
22
22
|
end
|
|
23
23
|
|
|
24
24
|
def ===(hash)
|
|
25
|
-
hash.is_a?(Hash)
|
|
26
|
-
|
|
27
|
-
|
|
25
|
+
return false unless hash.is_a?(Hash)
|
|
26
|
+
|
|
27
|
+
key_type = @subtype[:key_type]
|
|
28
|
+
value_type = @subtype[:value_type]
|
|
29
|
+
hash.all? { |key, value| key.is_a?(key_type) && value.is_a?(value_type) }
|
|
28
30
|
end
|
|
29
31
|
end
|
|
30
32
|
end
|
data/lib/philosophal.rb
CHANGED
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
|
|
3
3
|
require 'date'
|
|
4
4
|
require 'pathname'
|
|
5
|
-
require 'set'
|
|
6
5
|
require 'time'
|
|
7
6
|
require 'json'
|
|
8
7
|
|
|
@@ -20,25 +19,24 @@ module Philosophal
|
|
|
20
19
|
autoload :ArgumentError, 'philosophal/errors/argument_error'
|
|
21
20
|
|
|
22
21
|
def self.convert(property, value)
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
end
|
|
29
|
-
else
|
|
30
|
-
convert_method, subtype = Convertor.convert_method_for(property.type)
|
|
31
|
-
raise Philosophal::TypeError unless convert_method
|
|
22
|
+
# nil means "no value": it is neither converted nor transformed, so the reader falls back to the default.
|
|
23
|
+
return if value.nil?
|
|
24
|
+
|
|
25
|
+
converted = property.type === value ? value : convert_to_type(property, value) # rubocop:disable Style/CaseEquality
|
|
26
|
+
return converted unless property.transform?
|
|
32
27
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
else
|
|
36
|
-
Convertor.send(convert_method, value)
|
|
37
|
-
end
|
|
28
|
+
Transform.make(property.transform, converted)
|
|
29
|
+
end
|
|
38
30
|
|
|
39
|
-
|
|
31
|
+
def self.convert_to_type(property, value)
|
|
32
|
+
convert_method, subtype = property.convert_method
|
|
33
|
+
raise Philosophal::TypeError unless convert_method
|
|
40
34
|
|
|
41
|
-
|
|
35
|
+
if subtype
|
|
36
|
+
Convertor.send(convert_method, value, subtype)
|
|
37
|
+
else
|
|
38
|
+
Convertor.send(convert_method, value)
|
|
42
39
|
end
|
|
43
40
|
end
|
|
41
|
+
private_class_method :convert_to_type
|
|
44
42
|
end
|
data/sig/manifest.yaml
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
module Philosophal
|
|
2
|
+
class Convertor
|
|
3
|
+
METHOD_TYPE_MAP: Hash[untyped, Symbol]
|
|
4
|
+
|
|
5
|
+
def self.convert_method_for: (type_spec type) -> (Symbol | [Symbol?, untyped] | nil)
|
|
6
|
+
|
|
7
|
+
def self.convert_to_symbol: (untyped obj) -> Symbol
|
|
8
|
+
|
|
9
|
+
def self.convert_to_string: (untyped obj) -> String
|
|
10
|
+
|
|
11
|
+
def self.convert_to_integer: (untyped obj) -> Integer
|
|
12
|
+
|
|
13
|
+
def self.convert_to_float: (untyped obj) -> Float
|
|
14
|
+
|
|
15
|
+
def self.convert_to_array: (untyped obj) -> Array[untyped]
|
|
16
|
+
|
|
17
|
+
def self.convert_to_hash: (untyped obj) -> Hash[untyped, untyped]
|
|
18
|
+
|
|
19
|
+
def self.convert_to_time: (untyped obj) -> Time
|
|
20
|
+
|
|
21
|
+
def self.convert_to_date: (untyped obj) -> Date
|
|
22
|
+
|
|
23
|
+
def self.convert_to_date_time: (untyped obj) -> DateTime
|
|
24
|
+
|
|
25
|
+
def self.convert_to_any: [T] (T obj) -> T
|
|
26
|
+
|
|
27
|
+
def self.convert_to_boolean: (untyped obj) -> bool
|
|
28
|
+
|
|
29
|
+
def self.convert_to_pathname: (untyped obj) -> Pathname
|
|
30
|
+
|
|
31
|
+
def self.convert_to_array_of: (untyped obj, Module subtype) -> Array[untyped]
|
|
32
|
+
|
|
33
|
+
def self.convert_to_hash_of: (untyped obj, Types::HashOfType::subtype subtype) -> Hash[untyped, untyped]
|
|
34
|
+
end
|
|
35
|
+
end
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
module Philosophal
|
|
2
|
+
module Loaders
|
|
3
|
+
class JsonLoader
|
|
4
|
+
@klass: untyped
|
|
5
|
+
|
|
6
|
+
def initialize: (Properties klass) -> void
|
|
7
|
+
|
|
8
|
+
# A Hash or a JSON object string returns one instance, an Array or a JSON array string returns a list,
|
|
9
|
+
# any other String is read as a path to a JSON file.
|
|
10
|
+
def load: (Hash[Symbol, untyped] json) -> untyped
|
|
11
|
+
| (Array[Hash[Symbol, untyped]] json) -> Array[untyped]
|
|
12
|
+
| (String json) -> untyped
|
|
13
|
+
|
|
14
|
+
private
|
|
15
|
+
|
|
16
|
+
def load_from_array: (Array[Hash[Symbol, untyped]] array) -> Array[untyped]
|
|
17
|
+
|
|
18
|
+
def load_from_hash: (Hash[Symbol, untyped] hash) -> untyped
|
|
19
|
+
|
|
20
|
+
def setter_from_key: (Symbol key) -> Symbol
|
|
21
|
+
|
|
22
|
+
def load_from_json: (String str) -> untyped
|
|
23
|
+
|
|
24
|
+
def load_from_json_collection: (String json) -> Array[untyped]
|
|
25
|
+
|
|
26
|
+
def load_from_path: (String path) -> untyped
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
module Philosophal
|
|
2
|
+
module Properties
|
|
3
|
+
# Included in the instances of the classes that declare properties.
|
|
4
|
+
module InstanceMethods
|
|
5
|
+
def cprop?: (String | Symbol property_name, untyped klass) -> bool
|
|
6
|
+
|
|
7
|
+
def philosophal_inspect: (?boolish light) -> String
|
|
8
|
+
|
|
9
|
+
alias cprop_inspect philosophal_inspect
|
|
10
|
+
|
|
11
|
+
def philosophal_inspect_map: () -> Hash[Symbol, untyped]
|
|
12
|
+
|
|
13
|
+
alias cprop_inspect_map philosophal_inspect_map
|
|
14
|
+
|
|
15
|
+
def philosophal_values: () -> Array[Property]
|
|
16
|
+
|
|
17
|
+
def changed_properties: () -> Hash[Symbol, untyped]
|
|
18
|
+
|
|
19
|
+
def changes_applied: () -> self
|
|
20
|
+
|
|
21
|
+
def to_json_hash: () -> Hash[Symbol, untyped]
|
|
22
|
+
|
|
23
|
+
def to_json: (*untyped _args) -> String
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
module Philosophal
|
|
2
|
+
module Properties
|
|
3
|
+
class Schema
|
|
4
|
+
include Enumerable[Property]
|
|
5
|
+
|
|
6
|
+
@properties_index: Hash[Symbol, Property]
|
|
7
|
+
@mutex: Thread::Mutex
|
|
8
|
+
@immutables: Hash[Symbol, Property]
|
|
9
|
+
@mutables: Hash[Symbol, Property]
|
|
10
|
+
@json_names_h: Hash[Symbol, Symbol]
|
|
11
|
+
@json_setters: Hash[Symbol, Symbol]
|
|
12
|
+
@json_properties: Array[Property]
|
|
13
|
+
@tracked: Array[Property]
|
|
14
|
+
|
|
15
|
+
def initialize: (?properties_index: Hash[Symbol, Property]) -> void
|
|
16
|
+
|
|
17
|
+
def initialize_copy: (Schema source) -> void
|
|
18
|
+
|
|
19
|
+
attr_reader properties_index: Hash[Symbol, Property]
|
|
20
|
+
|
|
21
|
+
def []: (Symbol? key) -> Property?
|
|
22
|
+
|
|
23
|
+
def keys: () -> Array[Symbol]
|
|
24
|
+
|
|
25
|
+
def each: () { (Property) -> void } -> self
|
|
26
|
+
| () -> Enumerator[Property, self]
|
|
27
|
+
|
|
28
|
+
def <<: (Property value) -> self
|
|
29
|
+
|
|
30
|
+
def immutables: () -> Hash[Symbol, Property]
|
|
31
|
+
|
|
32
|
+
def mutables: () -> Hash[Symbol, Property]
|
|
33
|
+
|
|
34
|
+
def json_names_h: () -> Hash[Symbol, Symbol]
|
|
35
|
+
|
|
36
|
+
def json_setters: () -> Hash[Symbol, Symbol]
|
|
37
|
+
|
|
38
|
+
def json_properties: () -> Array[Property]
|
|
39
|
+
|
|
40
|
+
def tracked: () -> Array[Property]
|
|
41
|
+
|
|
42
|
+
private
|
|
43
|
+
|
|
44
|
+
def clear_caches: () -> void
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
module Philosophal
|
|
2
|
+
# Extended by the classes that declare properties.
|
|
3
|
+
module Properties : Module
|
|
4
|
+
include Philosophal::Types
|
|
5
|
+
|
|
6
|
+
@philosophal_properties: Schema
|
|
7
|
+
@philosophal_descriptions: Hash[Symbol, String]
|
|
8
|
+
@json: Loaders::JsonLoader
|
|
9
|
+
@__philosophal_extension__: Module
|
|
10
|
+
|
|
11
|
+
def cprop: (
|
|
12
|
+
Symbol name,
|
|
13
|
+
type_spec `type`,
|
|
14
|
+
?default: untyped,
|
|
15
|
+
?transform: transform?,
|
|
16
|
+
?immutable: bool,
|
|
17
|
+
?description: String?,
|
|
18
|
+
?json: bool | String | Symbol,
|
|
19
|
+
?override: bool,
|
|
20
|
+
?track_changes: bool
|
|
21
|
+
) -> untyped
|
|
22
|
+
|
|
23
|
+
def philosophal_properties: () -> Schema
|
|
24
|
+
|
|
25
|
+
def philosophal_descriptions: () -> Hash[Symbol, String]
|
|
26
|
+
|
|
27
|
+
alias cprop_descriptions philosophal_descriptions
|
|
28
|
+
|
|
29
|
+
def json: () -> Loaders::JsonLoader
|
|
30
|
+
|
|
31
|
+
private
|
|
32
|
+
|
|
33
|
+
def __philosophal_property_class__: () -> singleton(Property)
|
|
34
|
+
|
|
35
|
+
def __define_philosophal_methods__: (Property new_property) -> untyped
|
|
36
|
+
|
|
37
|
+
def __set_philosophal_property_constant__: (Property property) -> void
|
|
38
|
+
|
|
39
|
+
def __philosophal_extension__: () -> Module
|
|
40
|
+
|
|
41
|
+
def __generate_philosophal_methods__: (Property new_property) -> String
|
|
42
|
+
|
|
43
|
+
def __remove_philosophal_own_method__: (Symbol method_name) -> void
|
|
44
|
+
|
|
45
|
+
def __check_philosophal_options__: (
|
|
46
|
+
Symbol name,
|
|
47
|
+
transform: untyped,
|
|
48
|
+
immutable: untyped,
|
|
49
|
+
override: untyped,
|
|
50
|
+
description: untyped,
|
|
51
|
+
json: untyped,
|
|
52
|
+
track_changes: untyped
|
|
53
|
+
) -> void
|
|
54
|
+
|
|
55
|
+
def __check_philosophal_transform_option__: (Symbol name, untyped transform) -> void
|
|
56
|
+
|
|
57
|
+
def __check_philosophal_boolean_option__: (Symbol option_name, untyped value) -> void
|
|
58
|
+
end
|
|
59
|
+
end
|