nrser 0.2.2 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/nrser/char/alpha_numeric_sub.rb +1 -2
- data/lib/nrser/char.rb +0 -6
- data/lib/nrser/core_ext/array.rb +120 -0
- data/lib/nrser/core_ext/binding.rb +44 -0
- data/lib/nrser/{functions → core_ext}/enumerable/find_map.rb +18 -15
- data/lib/nrser/{ext → core_ext}/enumerable.rb +10 -24
- data/lib/nrser/core_ext/exception.rb +30 -0
- data/lib/nrser/core_ext/hash/extract_values_at.rb +49 -0
- data/lib/nrser/core_ext/hash/transform_values_with_keys.rb +24 -0
- data/lib/nrser/core_ext/hash.rb +50 -0
- data/lib/nrser/core_ext/module/method_objects.rb +96 -0
- data/lib/nrser/core_ext/module/names.rb +69 -0
- data/lib/nrser/core_ext/module/source_locations.rb +214 -0
- data/lib/nrser/core_ext/module.rb +2 -0
- data/lib/nrser/core_ext/object/lazy_var.rb +31 -0
- data/lib/nrser/core_ext/object.rb +46 -0
- data/lib/nrser/core_ext/open_struct.rb +6 -0
- data/lib/nrser/{ext → core_ext}/pathname.rb +8 -5
- data/lib/nrser/{ext → core_ext}/string.rb +6 -12
- data/lib/nrser/core_ext/symbol.rb +13 -0
- data/lib/nrser/core_ext/time.rb +46 -0
- data/lib/nrser/core_ext.rb +13 -0
- data/lib/nrser/errors/abstract_method_error.rb +150 -0
- data/lib/nrser/errors/argument_error.rb +42 -0
- data/lib/nrser/errors/nicer_error.rb +298 -72
- data/lib/nrser/errors/type_error.rb +46 -0
- data/lib/nrser/errors.rb +4 -53
- data/lib/nrser/ext/tree.rb +3 -0
- data/lib/nrser/functions/enumerable/associate.rb +6 -9
- data/lib/nrser/functions/enumerable/include_slice.rb +2 -3
- data/lib/nrser/functions/enumerable.rb +1 -3
- data/lib/nrser/functions/exception.rb +1 -1
- data/lib/nrser/functions/hash.rb +0 -6
- data/lib/nrser/functions/merge_by.rb +2 -2
- data/lib/nrser/functions/module/method_objects.rb +77 -0
- data/lib/nrser/functions/module.rb +1 -2
- data/lib/nrser/functions/open_struct.rb +25 -35
- data/lib/nrser/functions/proc.rb +1 -6
- data/lib/nrser/functions/string/looks_like.rb +32 -1
- data/lib/nrser/functions/string.rb +1 -40
- data/lib/nrser/functions/text/lines.rb +2 -1
- data/lib/nrser/functions.rb +0 -1
- data/lib/nrser/graph/tsorter.rb +41 -0
- data/lib/nrser/labs/core_ext/binding.rb +37 -0
- data/lib/nrser/labs/stash.rb +372 -0
- data/lib/nrser/{logging → log}/appender/sync.rb +3 -3
- data/lib/nrser/log/appender.rb +3 -0
- data/lib/nrser/{logging → log}/formatters/color.rb +47 -20
- data/lib/nrser/log/formatters/mixin.rb +270 -0
- data/lib/nrser/{logging → log}/formatters.rb +0 -0
- data/lib/nrser/log/logger.rb +229 -0
- data/lib/nrser/log/mixin.rb +56 -0
- data/lib/nrser/log.rb +723 -0
- data/lib/nrser/message.rb +24 -3
- data/lib/nrser/meta/source/location.rb +158 -0
- data/lib/nrser/meta.rb +1 -1
- data/lib/nrser/props/class_methods.rb +118 -0
- data/lib/nrser/props/immutable/hash.rb +111 -0
- data/lib/nrser/props/immutable/hash_variable.rb +82 -0
- data/lib/nrser/props/immutable/instance_variables.rb +48 -0
- data/lib/nrser/props/immutable/vector.rb +107 -0
- data/lib/nrser/props/instance_methods.rb +184 -0
- data/lib/nrser/props/metadata.rb +359 -0
- data/lib/nrser/props/mutable/instance_variables.rb +60 -0
- data/lib/nrser/props/mutable/stash.rb +199 -0
- data/lib/nrser/{meta/props → props}/prop.rb +217 -112
- data/lib/nrser/props/storage/instance_variable.rb +85 -0
- data/lib/nrser/props/storage/instance_variables.rb +67 -0
- data/lib/nrser/props/storage/key.rb +88 -0
- data/lib/nrser/props.rb +9 -0
- data/lib/nrser/refinements/sugar.rb +41 -0
- data/lib/nrser/refinements/types.rb +2 -2
- data/lib/nrser/refinements.rb +14 -16
- data/lib/nrser/rspex/example_group/describe_attribute.rb +24 -0
- data/lib/nrser/rspex/example_group/describe_called_with.rb +1 -6
- data/lib/nrser/rspex/example_group/{describe_use_case.rb → describe_case.rb} +6 -3
- data/lib/nrser/rspex/example_group/describe_class.rb +1 -0
- data/lib/nrser/rspex/example_group/describe_group.rb +29 -0
- data/lib/nrser/rspex/example_group/describe_instance_method.rb +2 -2
- data/lib/nrser/rspex/example_group/describe_message.rb +35 -0
- data/lib/nrser/rspex/example_group/describe_method.rb +23 -2
- data/lib/nrser/rspex/example_group/describe_module.rb +19 -0
- data/lib/nrser/rspex/example_group/describe_response_to.rb +32 -0
- data/lib/nrser/rspex/example_group/describe_section.rb +38 -0
- data/lib/nrser/rspex/example_group/describe_sent_to.rb +52 -0
- data/lib/nrser/rspex/example_group/describe_source_file.rb +49 -0
- data/lib/nrser/rspex/example_group/describe_spec_file.rb +41 -108
- data/lib/nrser/rspex/example_group/describe_when.rb +14 -7
- data/lib/nrser/rspex/example_group/describe_x.rb +39 -12
- data/lib/nrser/rspex/example_group/overrides.rb +66 -0
- data/lib/nrser/rspex/example_group.rb +20 -252
- data/lib/nrser/rspex/format.rb +83 -17
- data/lib/nrser/rspex.rb +4 -34
- data/lib/nrser/sugar/method_missing_forwarder.rb +50 -0
- data/lib/nrser/{env → sys/env}/path.rb +1 -2
- data/lib/nrser/{env.rb → sys/env.rb} +2 -1
- data/lib/nrser/sys.rb +5 -0
- data/lib/nrser/types/any.rb +36 -7
- data/lib/nrser/types/{array.rb → arrays.rb} +32 -81
- data/lib/nrser/types/attrs.rb +68 -15
- data/lib/nrser/types/booleans.rb +95 -34
- data/lib/nrser/types/bounded.rb +12 -10
- data/lib/nrser/types/combinators.rb +74 -37
- data/lib/nrser/types/errors/check_error.rb +86 -0
- data/lib/nrser/types/errors/from_string_error.rb +82 -0
- data/lib/nrser/types/factory.rb +91 -0
- data/lib/nrser/types/hashes.rb +171 -26
- data/lib/nrser/types/in.rb +25 -12
- data/lib/nrser/types/is.rb +50 -18
- data/lib/nrser/types/is_a.rb +52 -33
- data/lib/nrser/types/labels.rb +6 -33
- data/lib/nrser/types/maybe.rb +12 -4
- data/lib/nrser/types/nil.rb +24 -4
- data/lib/nrser/types/not.rb +6 -16
- data/lib/nrser/types/numbers.rb +94 -57
- data/lib/nrser/types/pairs.rb +57 -57
- data/lib/nrser/types/paths.rb +112 -133
- data/lib/nrser/types/responds.rb +64 -74
- data/lib/nrser/types/shape.rb +29 -24
- data/lib/nrser/types/strings.rb +25 -17
- data/lib/nrser/types/symbols.rb +19 -17
- data/lib/nrser/types/trees.rb +18 -70
- data/lib/nrser/types/tuples.rb +36 -40
- data/lib/nrser/types/type.rb +342 -91
- data/lib/nrser/types/when.rb +40 -18
- data/lib/nrser/types/where.rb +94 -9
- data/lib/nrser/types.rb +72 -63
- data/lib/nrser/version.rb +1 -1
- data/lib/nrser.rb +18 -18
- data/spec/lib/nrser/{functions/binding/template_spec.rb → core_ext/binding/erb_spec.rb} +5 -5
- data/spec/lib/nrser/{functions → core_ext}/enumerable/find_map_spec.rb +8 -6
- data/spec/lib/nrser/{refinements → core_ext}/hash_spec.rb +9 -22
- data/spec/lib/nrser/errors/abstract_method_error_spec.rb +12 -5
- data/spec/lib/nrser/functions/enumerable/{to_h_by_spec.rb → associate_spec.rb} +1 -1
- data/spec/lib/nrser/functions/merge_by_spec.rb +1 -1
- data/spec/lib/nrser/functions/tree/each_branch_spec.rb +3 -3
- data/spec/lib/nrser/functions/tree/transform_spec.rb +14 -15
- data/spec/lib/nrser/gem_ext/hamster/json_spec.rb +4 -0
- data/spec/lib/nrser/meta/source/location_spec.rb +86 -0
- data/spec/lib/nrser/props/immutable/hash_spec.rb +297 -0
- data/spec/lib/nrser/props/immutable/vector_spec.rb +296 -0
- data/spec/lib/nrser/{meta/props_spec.rb → props/original_props_spec.rb} +11 -16
- data/spec/lib/nrser/{meta/props → props}/to_and_from_data_spec.rb +10 -8
- data/spec/lib/nrser/refinements/array_spec.rb +2 -15
- data/spec/lib/nrser/refinements/erb_spec.rb +5 -7
- data/spec/lib/nrser/refinements/set_spec.rb +2 -15
- data/spec/lib/nrser/{env → sys/env}/path/insert_spec.rb +4 -2
- data/spec/lib/nrser/{env → sys/env}/path_spec.rb +4 -2
- data/spec/lib/nrser/types/array_spec.rb +8 -8
- data/spec/lib/nrser/types/paths_spec.rb +15 -18
- data/spec/spec_helper.rb +4 -0
- metadata +109 -69
- data/lib/nrser/ext/binding.rb +0 -36
- data/lib/nrser/ext/module.rb +0 -62
- data/lib/nrser/ext.rb +0 -8
- data/lib/nrser/functions/binding.rb +0 -76
- data/lib/nrser/functions/enumerable/map_keys.rb +0 -0
- data/lib/nrser/functions/enumerable/map_values.rb +0 -94
- data/lib/nrser/functions/hash/deep_merge.rb +0 -57
- data/lib/nrser/functions/hash/except_keys.rb +0 -44
- data/lib/nrser/functions/hash/slice_keys.rb +0 -43
- data/lib/nrser/functions/hash/stringify_keys.rb +0 -55
- data/lib/nrser/functions/hash/symbolize_keys.rb +0 -57
- data/lib/nrser/functions/hash/transform_keys.rb +0 -140
- data/lib/nrser/functions/module/methods.rb +0 -206
- data/lib/nrser/functions/module/source_locations.rb +0 -213
- data/lib/nrser/logging/appender.rb +0 -3
- data/lib/nrser/logging.rb +0 -353
- data/lib/nrser/meta/props/base.rb +0 -31
- data/lib/nrser/meta/props.rb +0 -357
- data/lib/nrser/refinements/array.rb +0 -133
- data/lib/nrser/refinements/binding.rb +0 -6
- data/lib/nrser/refinements/enumerator.rb +0 -5
- data/lib/nrser/refinements/exception.rb +0 -35
- data/lib/nrser/refinements/hash.rb +0 -150
- data/lib/nrser/refinements/module.rb +0 -5
- data/lib/nrser/refinements/object.rb +0 -42
- data/lib/nrser/refinements/open_struct.rb +0 -28
- data/lib/nrser/refinements/pathname.rb +0 -5
- data/lib/nrser/refinements/set.rb +0 -5
- data/lib/nrser/refinements/string.rb +0 -5
- data/lib/nrser/refinements/symbol.rb +0 -20
- data/lib/nrser/rspex/described.rb +0 -99
- data/spec/design/mapping_spec.rb +0 -42
- data/spec/lib/nrser/functions/hash_spec.rb +0 -41
- data/spec/lib/nrser/functions/string/truncate_spec.rb +0 -11
- data/spec/lib/nrser/refinements/truncate_spec.rb +0 -10
@@ -0,0 +1,199 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
# Requirements
|
5
|
+
# =======================================================================
|
6
|
+
|
7
|
+
# Project / Package
|
8
|
+
# -----------------------------------------------------------------------
|
9
|
+
|
10
|
+
# Need {NRSER::Props} to include
|
11
|
+
require_relative '../../props'
|
12
|
+
|
13
|
+
# Need {NRSER::Stash} itself
|
14
|
+
require 'nrser/labs/stash'
|
15
|
+
|
16
|
+
# Gonna use {NRSER::Props::Storage::Key} for storage
|
17
|
+
require_relative '../storage/key'
|
18
|
+
|
19
|
+
|
20
|
+
# Declarations
|
21
|
+
# =======================================================================
|
22
|
+
|
23
|
+
module NRSER::Props::Mutable; end
|
24
|
+
|
25
|
+
|
26
|
+
# Definitions
|
27
|
+
# =======================================================================
|
28
|
+
|
29
|
+
module NRSER::Props::Mutable::Stash
|
30
|
+
|
31
|
+
# Constants
|
32
|
+
# ==========================================================================
|
33
|
+
|
34
|
+
STORAGE = NRSER::Props::Storage::Key.new \
|
35
|
+
immutable: false,
|
36
|
+
key_type: :name,
|
37
|
+
get: :_raw_get,
|
38
|
+
put: :_raw_put
|
39
|
+
|
40
|
+
|
41
|
+
# Module Methods
|
42
|
+
# ======================================================================
|
43
|
+
|
44
|
+
def self.included base
|
45
|
+
unless base < NRSER::Stash
|
46
|
+
raise binding.erb <<~END
|
47
|
+
This class is only for including in {Hash} subclasses!
|
48
|
+
END
|
49
|
+
end
|
50
|
+
|
51
|
+
base.include NRSER::Props
|
52
|
+
base.include InstanceMethods
|
53
|
+
base.metadata.storage STORAGE
|
54
|
+
base.metadata.freeze
|
55
|
+
end
|
56
|
+
|
57
|
+
# Methods to be mixed in at the class-level with
|
58
|
+
# {NRSER::Props::Mutable::Hash}.
|
59
|
+
module ClassMethods
|
60
|
+
|
61
|
+
def [] *args
|
62
|
+
new ::Hash[*args]
|
63
|
+
end
|
64
|
+
|
65
|
+
end # module ClassMethods
|
66
|
+
|
67
|
+
|
68
|
+
# Instance methods to mix in with {NRSER::Props::Mutable::Hash}.
|
69
|
+
#
|
70
|
+
# We want these to *override* {NRSER::Props::InstanceMethods}, so they
|
71
|
+
# need to be separate so we can include them after {NRSER::Props} in
|
72
|
+
# {NRSER::Props::Mutable::Hash.included}.
|
73
|
+
#
|
74
|
+
module InstanceMethods
|
75
|
+
|
76
|
+
def initialize_props values = {}
|
77
|
+
# Handles things like `[[:x, 1], [:y, 2]]`, since we know that's what is
|
78
|
+
# meant in that case
|
79
|
+
values = values.to_h unless values.respond_to?( :each_pair )
|
80
|
+
|
81
|
+
self.class.metadata.
|
82
|
+
each_primary_prop_value_from( values ) { |prop, value|
|
83
|
+
_raw_put prop.name, value
|
84
|
+
}
|
85
|
+
|
86
|
+
# Check additional type invariants
|
87
|
+
self.class.invariants.each do |type|
|
88
|
+
type.check self
|
89
|
+
end
|
90
|
+
|
91
|
+
# Load in additional non-prop values, if any
|
92
|
+
#
|
93
|
+
# TODO Optimize
|
94
|
+
#
|
95
|
+
|
96
|
+
prop_names = self.class.metadata.prop_names
|
97
|
+
|
98
|
+
values.each do |key, value|
|
99
|
+
unless prop_names.include? convert_key( key )
|
100
|
+
self[key] = value
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end # #initialize_props
|
104
|
+
|
105
|
+
|
106
|
+
# Override {NRSER::Props::InstanceMethods#to_data} to handle non-prop
|
107
|
+
# values in the {NRSER::Stash}.
|
108
|
+
#
|
109
|
+
# @param [Boolean] only_props:
|
110
|
+
# When `true` only prop values will be added to the data hash.
|
111
|
+
#
|
112
|
+
# Otherwise, any non-prop keys and vales will be added as well
|
113
|
+
# (default behavior).
|
114
|
+
#
|
115
|
+
# @param **kwds
|
116
|
+
# See {NRSER::Props::InstanceMethods#to_data}.
|
117
|
+
#
|
118
|
+
# @return (see NRSER::Props::InstanceMethods#to_data)
|
119
|
+
#
|
120
|
+
def to_data only_props: false, **kwds
|
121
|
+
hash = super **kwds
|
122
|
+
|
123
|
+
unless only_props
|
124
|
+
each do |key, value|
|
125
|
+
# Data uses **string** keys
|
126
|
+
key = key.to_s
|
127
|
+
|
128
|
+
# See if the key is missing
|
129
|
+
unless hash.key?( key.to_s )
|
130
|
+
# It is, so let's fill it in
|
131
|
+
|
132
|
+
# If value knows how to be data, do that
|
133
|
+
value = value.to_data if value.respond_to?( :to_data )
|
134
|
+
|
135
|
+
# Set the key/value pair
|
136
|
+
hash[key] = value
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
hash
|
142
|
+
end # #to_data
|
143
|
+
|
144
|
+
|
145
|
+
def convert_key key
|
146
|
+
case key
|
147
|
+
when Symbol
|
148
|
+
key
|
149
|
+
when String
|
150
|
+
sym = key.to_sym
|
151
|
+
if self.metadata[ sym ]
|
152
|
+
sym
|
153
|
+
else
|
154
|
+
key
|
155
|
+
end
|
156
|
+
else
|
157
|
+
key
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
|
162
|
+
# Store a value at a key. If the key is a prop name, store it through the
|
163
|
+
# prop, which will check it's type.
|
164
|
+
#
|
165
|
+
# @param [Symbol | String] key
|
166
|
+
# @param [VALUE] value
|
167
|
+
#
|
168
|
+
# @return [VALUE]
|
169
|
+
# The stored value.
|
170
|
+
#
|
171
|
+
def put key, value
|
172
|
+
key = convert_key key
|
173
|
+
|
174
|
+
if (prop = self.class.metadata[ key ])
|
175
|
+
prop.set self, value
|
176
|
+
else
|
177
|
+
# We know {#convert_value} is a no-op so can skip it
|
178
|
+
_raw_put key, value
|
179
|
+
end
|
180
|
+
end # #put
|
181
|
+
|
182
|
+
|
183
|
+
def dup
|
184
|
+
self.class.new( self ).tap do |new_stash|
|
185
|
+
set_defaults new_stash
|
186
|
+
end
|
187
|
+
end
|
188
|
+
|
189
|
+
|
190
|
+
# Need to patch `#merge` since {NRSER::Props::InstanceMethods} defines
|
191
|
+
# it, which overrides {NRSER::Stash#merge}, so we just put it back.
|
192
|
+
#
|
193
|
+
def merge other_hash = {}, &block
|
194
|
+
dup.update other_hash, &block
|
195
|
+
end
|
196
|
+
|
197
|
+
end # module InstanceMethods
|
198
|
+
|
199
|
+
end # module NRSER::Props::Mutable::Stash
|
@@ -1,7 +1,20 @@
|
|
1
|
+
# Requirements
|
2
|
+
# =======================================================================
|
3
|
+
|
4
|
+
# Stdlib
|
5
|
+
# -----------------------------------------------------------------------
|
6
|
+
|
7
|
+
# Deps
|
8
|
+
# -----------------------------------------------------------------------
|
9
|
+
|
10
|
+
# Project / Package
|
11
|
+
# -----------------------------------------------------------------------
|
12
|
+
require 'nrser/refinements/types'
|
13
|
+
|
14
|
+
|
1
15
|
# Refinements
|
2
16
|
# =======================================================================
|
3
17
|
|
4
|
-
using NRSER
|
5
18
|
using NRSER::Types
|
6
19
|
|
7
20
|
|
@@ -9,8 +22,7 @@ using NRSER::Types
|
|
9
22
|
# =======================================================================
|
10
23
|
|
11
24
|
module NRSER; end
|
12
|
-
module NRSER::
|
13
|
-
module NRSER::Meta::Props; end
|
25
|
+
module NRSER::Props; end
|
14
26
|
|
15
27
|
|
16
28
|
# Definitions
|
@@ -21,7 +33,9 @@ module NRSER::Meta::Props; end
|
|
21
33
|
#
|
22
34
|
# Props are immutable by design.
|
23
35
|
#
|
24
|
-
class NRSER::
|
36
|
+
class NRSER::Props::Prop
|
37
|
+
|
38
|
+
include NRSER::Log::Mixin
|
25
39
|
|
26
40
|
# The class the prop was defined in.
|
27
41
|
#
|
@@ -38,13 +52,27 @@ class NRSER::Meta::Props::Prop
|
|
38
52
|
attr_reader :name
|
39
53
|
|
40
54
|
|
55
|
+
# The key under which the value will be stored in the storage.
|
56
|
+
#
|
57
|
+
# @return [nil | Integer]
|
58
|
+
#
|
59
|
+
attr_reader :index
|
60
|
+
|
61
|
+
|
41
62
|
# The type of the valid values for the property.
|
42
63
|
#
|
43
64
|
# @return [NRSER::Types::Type]
|
44
65
|
#
|
45
66
|
attr_reader :type
|
46
67
|
|
47
|
-
|
68
|
+
|
69
|
+
# Names of any props this one depends on (to create a default).
|
70
|
+
#
|
71
|
+
# @return [Array<Symbol>]
|
72
|
+
#
|
73
|
+
attr_reader :deps
|
74
|
+
|
75
|
+
|
48
76
|
# Optional name of instance variable (including the `@` prefix) or getter
|
49
77
|
# method (method that takes no arguments) that provides the property's
|
50
78
|
# value.
|
@@ -68,6 +96,13 @@ class NRSER::Meta::Props::Prop
|
|
68
96
|
attr_reader :source
|
69
97
|
|
70
98
|
|
99
|
+
# TODO document `aliases` attribute.
|
100
|
+
#
|
101
|
+
# @return [Array<Symbol>]
|
102
|
+
#
|
103
|
+
attr_reader :aliases
|
104
|
+
|
105
|
+
|
71
106
|
# Constructor
|
72
107
|
# =====================================================================
|
73
108
|
|
@@ -75,8 +110,8 @@ class NRSER::Meta::Props::Prop
|
|
75
110
|
#
|
76
111
|
# You should not need to construct a `Prop` directly unless you are doing
|
77
112
|
# custom meta-programming - they should be constructed for you via the
|
78
|
-
# `.prop` "macro" defined at {NRSER::
|
79
|
-
# that is extended in to classes including {NRSER::
|
113
|
+
# `.prop` "macro" defined at {NRSER::Props::Props::ClassMethods#prop}
|
114
|
+
# that is extended in to classes including {NRSER::Props::Props}.
|
80
115
|
#
|
81
116
|
# @param [nil | Proc | Object] default:
|
82
117
|
# A default value or a {Proc} used to get default values for *primary*
|
@@ -101,16 +136,29 @@ class NRSER::Meta::Props::Prop
|
|
101
136
|
default: nil,
|
102
137
|
source: nil,
|
103
138
|
to_data: nil,
|
104
|
-
from_data: nil
|
139
|
+
from_data: nil,
|
140
|
+
index: nil,
|
141
|
+
reader: nil,
|
142
|
+
writer: nil,
|
143
|
+
aliases: []
|
105
144
|
|
106
145
|
# Set these up first so {#to_s} works in case we need to raise errors.
|
107
146
|
@defined_in = defined_in
|
108
147
|
@name = t.sym.check name
|
148
|
+
@index = t.non_neg_int?.check! index
|
109
149
|
@type = t.make type
|
110
150
|
|
151
|
+
# Will be overridden in {#init_default!} if needed
|
152
|
+
@deps = []
|
153
|
+
|
111
154
|
@to_data = to_data
|
112
155
|
@from_data = from_data
|
113
156
|
|
157
|
+
@reader = t.bool?.check! reader
|
158
|
+
@writer = t.bool?.check! writer
|
159
|
+
|
160
|
+
@aliases = t.array( t.sym ).check! aliases
|
161
|
+
|
114
162
|
# Source
|
115
163
|
|
116
164
|
# normalize source to {nil}, {Symbol} or {Proc}
|
@@ -147,7 +195,7 @@ class NRSER::Meta::Props::Prop
|
|
147
195
|
# for sourced props
|
148
196
|
if source?
|
149
197
|
raise ArgumentError.new binding.erb <<-END
|
150
|
-
Can not construct {<%= self.class.
|
198
|
+
Can not construct {<%= self.class.safe_name %>} with `default` and `source`
|
151
199
|
|
152
200
|
Props with {#source} always get their value from that source, so
|
153
201
|
defaults don't make any sense.
|
@@ -166,8 +214,47 @@ class NRSER::Meta::Props::Prop
|
|
166
214
|
END
|
167
215
|
end
|
168
216
|
|
169
|
-
|
170
|
-
|
217
|
+
if Proc === default
|
218
|
+
case default.arity
|
219
|
+
when 0
|
220
|
+
# pass, no deps
|
221
|
+
when 1
|
222
|
+
# Check that it's valid and set deps
|
223
|
+
@deps = default.parameters.map do |param|
|
224
|
+
unless Array === param &&
|
225
|
+
:keyreq == param[0]
|
226
|
+
raise ArgumentError.new binding.erb <<~END
|
227
|
+
Prop default Proc that take args must take only required
|
228
|
+
keywords (`:keyreq` type)
|
229
|
+
|
230
|
+
This is because this is how the props system figures out
|
231
|
+
any dependency orders.
|
232
|
+
|
233
|
+
Found:
|
234
|
+
|
235
|
+
<%= default.parameters %>
|
236
|
+
|
237
|
+
For `default` for prop <%= full_name %>:
|
238
|
+
|
239
|
+
<%= self.pretty_inspect %>
|
240
|
+
|
241
|
+
END
|
242
|
+
end
|
243
|
+
|
244
|
+
# The keyword name
|
245
|
+
param[1]
|
246
|
+
end
|
247
|
+
else
|
248
|
+
raise ArgumentError.new binding.erb <<~END
|
249
|
+
Prop default Proc must take no params or only required keywords
|
250
|
+
({Proc#arity} of 0 or 1).
|
251
|
+
|
252
|
+
Default to prop <%= full_name %> has arity <%= default.arity %>.
|
253
|
+
|
254
|
+
END
|
255
|
+
end
|
256
|
+
|
257
|
+
elsif !default.frozen?
|
171
258
|
raise ArgumentError.new binding.erb <<-END
|
172
259
|
Non-proc default values must be frozen
|
173
260
|
|
@@ -195,13 +282,21 @@ class NRSER::Meta::Props::Prop
|
|
195
282
|
# Instance Methods
|
196
283
|
# ============================================================================
|
197
284
|
|
198
|
-
|
285
|
+
def names
|
286
|
+
[name, *aliases]
|
287
|
+
end
|
288
|
+
|
289
|
+
|
290
|
+
# Used by the {NRSER::Props::Props::ClassMethods.prop} "macro" method to
|
199
291
|
# determine if it should create a reader method on the propertied class.
|
200
292
|
#
|
201
293
|
# @return [Boolean]
|
202
294
|
# `true` if a reader method should be created for the prop value.
|
203
295
|
#
|
204
|
-
def create_reader?
|
296
|
+
def create_reader? name
|
297
|
+
# If the options was explicitly provided then return that
|
298
|
+
return @reader unless @reader.nil?
|
299
|
+
|
205
300
|
# Always create readers for primary props
|
206
301
|
return true if primary?
|
207
302
|
|
@@ -216,7 +311,7 @@ class NRSER::Meta::Props::Prop
|
|
216
311
|
end # #create_reader?
|
217
312
|
|
218
313
|
|
219
|
-
# Used by the {NRSER::
|
314
|
+
# Used by the {NRSER::Props::Props::ClassMethods.prop} "macro" method to
|
220
315
|
# determine if it should create a writer method on the propertied class.
|
221
316
|
#
|
222
317
|
# Right now, we don't create writers, but we will probably make them an
|
@@ -225,7 +320,13 @@ class NRSER::Meta::Props::Prop
|
|
225
320
|
# @return [Boolean]
|
226
321
|
# Always `false` for the moment.
|
227
322
|
#
|
228
|
-
def create_writer?
|
323
|
+
def create_writer? name
|
324
|
+
return @writer unless @writer.nil?
|
325
|
+
|
326
|
+
storage_immutable = defined_in.metadata.storage.try( :immutable? )
|
327
|
+
|
328
|
+
return !storage_immutable unless storage_immutable.nil?
|
329
|
+
|
229
330
|
false
|
230
331
|
end # #create_writer?
|
231
332
|
|
@@ -259,16 +360,37 @@ class NRSER::Meta::Props::Prop
|
|
259
360
|
alias_method :default?, :has_default?
|
260
361
|
|
261
362
|
|
262
|
-
|
363
|
+
# Get the default value for the property given the instance and values.
|
364
|
+
#
|
365
|
+
# @todo
|
366
|
+
# This is a shitty hack stop-gap until I really figure our how this should
|
367
|
+
# work.
|
368
|
+
#
|
369
|
+
# @param [Hash<Symbol, Object>] values
|
370
|
+
# Other prop values known at this point, keyed by name.
|
371
|
+
#
|
372
|
+
# @return [Object]
|
373
|
+
# Default value.
|
374
|
+
#
|
375
|
+
# @raise [NameError]
|
376
|
+
# If the prop doesn't have a default.
|
377
|
+
#
|
378
|
+
def default **values
|
263
379
|
if has_default?
|
264
380
|
if Proc === @default
|
265
|
-
@default.
|
381
|
+
case @default.arity
|
382
|
+
when 0
|
383
|
+
@default.call
|
384
|
+
else
|
385
|
+
kwds = values.slice *deps
|
386
|
+
@default.call **kwds
|
387
|
+
end
|
266
388
|
else
|
267
389
|
@default
|
268
390
|
end
|
269
391
|
else
|
270
|
-
raise NameError.new
|
271
|
-
Prop
|
392
|
+
raise NameError.new binding.erb <<-END
|
393
|
+
Prop <%= full_name %> has no default value (and none provided).
|
272
394
|
END
|
273
395
|
end
|
274
396
|
end
|
@@ -309,100 +431,107 @@ class NRSER::Meta::Props::Prop
|
|
309
431
|
end # #primary?
|
310
432
|
|
311
433
|
|
312
|
-
#
|
434
|
+
# Get the value of the prop from an instance.
|
313
435
|
#
|
314
|
-
# @
|
315
|
-
#
|
436
|
+
# @note
|
437
|
+
# At the moment, values are **not** type-checked when reading. Primary
|
438
|
+
# values are checked when setting, so they should be ok, but this does
|
439
|
+
# leave the possibility that props with a {#source} may return values
|
440
|
+
# that do not satisfy their types... :/
|
316
441
|
#
|
317
|
-
# @
|
318
|
-
#
|
442
|
+
# @param [NRSER::Props] instance
|
443
|
+
# An instance of {#defined_in}.
|
444
|
+
#
|
445
|
+
# @return
|
446
|
+
# Value from the instance's prop value storage (for {#primary?} props)
|
447
|
+
# or it's {#source}.
|
319
448
|
#
|
320
449
|
def get instance
|
321
450
|
if source?
|
322
451
|
if instance_variable_source?
|
323
452
|
instance.instance_variable_get source
|
324
453
|
else
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
else
|
331
|
-
raise TypeError.squished <<-END
|
332
|
-
Expected `Prop#source` to be a String, Symbol or Proc;
|
333
|
-
found #{ source.inspect }
|
334
|
-
END
|
335
|
-
end
|
454
|
+
t.match source,
|
455
|
+
t.or( String, Symbol ),
|
456
|
+
->( name ) { instance.send name },
|
457
|
+
Proc,
|
458
|
+
->( block ) { instance.instance_exec &block }
|
336
459
|
end
|
337
460
|
else
|
338
|
-
|
461
|
+
# Go through the storage engine
|
462
|
+
instance.class.metadata.storage.get instance, self
|
339
463
|
end
|
340
464
|
end # #get
|
341
465
|
|
342
466
|
|
343
|
-
#
|
467
|
+
# Set a value for a the prop on an instance.
|
344
468
|
#
|
345
|
-
# @param [
|
346
|
-
#
|
469
|
+
# @param [NRSER::Props] instance
|
470
|
+
# An instance of {#defined_in}.
|
347
471
|
#
|
348
|
-
# @
|
349
|
-
#
|
472
|
+
# @param [*] value
|
473
|
+
# A value that must satisfy {#type}.
|
474
|
+
#
|
475
|
+
# @return [nil]
|
476
|
+
#
|
477
|
+
# @raise [RuntimeError]
|
478
|
+
# If you try to set a value for a prop that isn't {#primary?}.
|
479
|
+
#
|
480
|
+
# @raise (see #check!)
|
350
481
|
#
|
351
482
|
def set instance, value
|
352
|
-
|
353
|
-
binding.erb
|
354
|
-
|
355
|
-
failed type check.
|
483
|
+
unless primary?
|
484
|
+
raise RuntimeError.new binding.erb <<~END
|
485
|
+
Only {#primary?} props can be set!
|
356
486
|
|
357
|
-
|
487
|
+
Tried to set prop #{ prop.name } to value
|
358
488
|
|
359
|
-
<%=
|
489
|
+
<%= value.pretty_inspect %>
|
360
490
|
|
361
|
-
|
491
|
+
in instance
|
362
492
|
|
363
|
-
<%=
|
493
|
+
<%= instance.pretty_inspect %>
|
364
494
|
|
365
495
|
END
|
366
496
|
end
|
367
497
|
|
368
|
-
|
498
|
+
instance.class.metadata.storage.put \
|
499
|
+
instance,
|
500
|
+
self,
|
501
|
+
check!( value )
|
502
|
+
|
503
|
+
nil
|
369
504
|
end # #set
|
370
505
|
|
371
506
|
|
372
|
-
#
|
507
|
+
# Check that a value satisfies the {#type}, raising if it doesn't.
|
373
508
|
#
|
374
|
-
# @param [
|
375
|
-
#
|
509
|
+
# @param [VALUE] value
|
510
|
+
# Value to check.
|
376
511
|
#
|
377
|
-
# @return [
|
378
|
-
#
|
512
|
+
# @return [VALUE]
|
513
|
+
# `value` arg that was passed in.
|
379
514
|
#
|
380
|
-
|
381
|
-
|
382
|
-
|
383
|
-
|
384
|
-
|
385
|
-
|
386
|
-
|
387
|
-
|
388
|
-
|
389
|
-
|
390
|
-
|
391
|
-
|
392
|
-
|
393
|
-
|
394
|
-
|
395
|
-
|
396
|
-
|
397
|
-
|
398
|
-
Prop:
|
399
|
-
|
400
|
-
<%= self.pretty_inspect %>
|
401
|
-
|
402
|
-
ERB
|
403
|
-
end
|
515
|
+
# @raise [NRSER::Types::CheckError]
|
516
|
+
# If `value` does not satisfy {#type}.
|
517
|
+
#
|
518
|
+
def check! value
|
519
|
+
type.check!( value ) do
|
520
|
+
binding.erb <<-END
|
521
|
+
Value of type <%= value.class.safe_name %> for prop <%= self.full_name %>
|
522
|
+
failed type check.
|
523
|
+
|
524
|
+
Must satisfy type:
|
525
|
+
|
526
|
+
<%= type %>
|
527
|
+
|
528
|
+
Given value:
|
529
|
+
|
530
|
+
<%= value.pretty_inspect %>
|
531
|
+
|
532
|
+
END
|
404
533
|
end
|
405
|
-
end # #
|
534
|
+
end # #check!
|
406
535
|
|
407
536
|
|
408
537
|
# Get the "data" value - a basic scalar or structure of hashes, arrays and
|
@@ -438,7 +567,7 @@ class NRSER::Meta::Props::Prop
|
|
438
567
|
# - The `to_data:` proc is called with the property value as the sole
|
439
568
|
# argument and the result is returned as the data.
|
440
569
|
#
|
441
|
-
# @param [NRSER::
|
570
|
+
# @param [NRSER::Props::Props] instance
|
442
571
|
# Instance to get the property value form.
|
443
572
|
#
|
444
573
|
# @return [Object]
|
@@ -474,13 +603,12 @@ class NRSER::Meta::Props::Prop
|
|
474
603
|
end # #to_data
|
475
604
|
|
476
605
|
|
477
|
-
#
|
606
|
+
# Load a value for the prop from "data".
|
478
607
|
#
|
479
|
-
# @param [
|
480
|
-
# @todo Add name param description.
|
608
|
+
# @param [*] data
|
481
609
|
#
|
482
|
-
# @return [
|
483
|
-
#
|
610
|
+
# @return [VALUE]
|
611
|
+
# The prop value to use.
|
484
612
|
#
|
485
613
|
def value_from_data data
|
486
614
|
value = case @from_data
|
@@ -498,7 +626,7 @@ class NRSER::Meta::Props::Prop
|
|
498
626
|
# The custom `from_data` configuration specifies a string or symbol name,
|
499
627
|
# which we interpret as a class method on the defining class and call
|
500
628
|
# with the data to produce a value.
|
501
|
-
@defined_in.send @
|
629
|
+
@defined_in.send @from_data, data
|
502
630
|
|
503
631
|
when Proc
|
504
632
|
# The custom `from_data` configuration provides a procedure, which we
|
@@ -536,30 +664,7 @@ class NRSER::Meta::Props::Prop
|
|
536
664
|
# a short string describing the instance.
|
537
665
|
#
|
538
666
|
def to_s
|
539
|
-
"#<#{ self.class.
|
667
|
+
"#<#{ self.class.safe_name } #{ full_name }:#{ type }>"
|
540
668
|
end # #to_s
|
541
669
|
|
542
|
-
|
543
|
-
private
|
544
|
-
|
545
|
-
# @todo Document values method.
|
546
|
-
#
|
547
|
-
# @param [type] arg_name
|
548
|
-
# @todo Add name param description.
|
549
|
-
#
|
550
|
-
# @return [return_type]
|
551
|
-
# @todo Document return value.
|
552
|
-
#
|
553
|
-
def values instance
|
554
|
-
unless instance.instance_variable_defined?(
|
555
|
-
NRSER::Meta::Props::PROP_VALUES_VARIABLE_NAME
|
556
|
-
)
|
557
|
-
instance.instance_variable_set \
|
558
|
-
NRSER::Meta::Props::PROP_VALUES_VARIABLE_NAME, {}
|
559
|
-
end
|
560
|
-
|
561
|
-
instance.instance_variable_get \
|
562
|
-
NRSER::Meta::Props::PROP_VALUES_VARIABLE_NAME
|
563
|
-
end # #value
|
564
|
-
|
565
|
-
end # class NRSER::Meta::Props::Prop
|
670
|
+
end # class NRSER::Props::Prop
|