nrser 0.1.3 → 0.1.4
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/lib/nrser.rb +10 -12
- data/lib/nrser/ext.rb +1 -0
- data/lib/nrser/ext/enumerable.rb +6 -0
- data/lib/nrser/ext/string.rb +62 -0
- data/lib/nrser/functions/enumerable.rb +1 -0
- data/lib/nrser/functions/enumerable/include_slice.rb +84 -0
- data/lib/nrser/functions/enumerable/include_slice/array_include_slice.rb +80 -0
- data/lib/nrser/functions/text.rb +1 -0
- data/lib/nrser/functions/text/words.rb +23 -0
- data/lib/nrser/labs.rb +13 -0
- data/lib/nrser/labs/globlin.rb +106 -0
- data/lib/nrser/labs/index.rb +89 -0
- data/lib/nrser/{temp → labs}/unicode_math.rb +2 -2
- data/lib/nrser/{temp → labs}/where.rb +2 -4
- data/lib/nrser/meta/props.rb +13 -7
- data/lib/nrser/meta/props/prop.rb +144 -86
- data/lib/nrser/refinements/exception.rb +2 -2
- data/lib/nrser/refinements/string.rb +1 -51
- data/lib/nrser/rspex/example_group/describe_spec_file.rb +20 -0
- data/lib/nrser/version.rb +21 -1
- data/spec/nrser/functions/enumerable/include_slice_spec.rb +28 -0
- data/spec/nrser/functions/text/words_spec.rb +17 -0
- data/spec/nrser/labs/globlin_spec.rb +61 -0
- data/spec/nrser/labs/index_spec.rb +87 -0
- data/spec/spec_helper.rb +16 -0
- metadata +19 -4
@@ -0,0 +1,89 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Requirements
|
4
|
+
# =======================================================================
|
5
|
+
|
6
|
+
# Stdlib
|
7
|
+
# -----------------------------------------------------------------------
|
8
|
+
|
9
|
+
# Deps
|
10
|
+
# -----------------------------------------------------------------------
|
11
|
+
|
12
|
+
# Project / Package
|
13
|
+
# -----------------------------------------------------------------------
|
14
|
+
|
15
|
+
|
16
|
+
# Refinements
|
17
|
+
# =======================================================================
|
18
|
+
|
19
|
+
|
20
|
+
# Declarations
|
21
|
+
# =======================================================================
|
22
|
+
|
23
|
+
module NRSER::Labs; end
|
24
|
+
|
25
|
+
|
26
|
+
|
27
|
+
# Definitions
|
28
|
+
# =======================================================================
|
29
|
+
|
30
|
+
# A very basic index data structure that
|
31
|
+
class NRSER::Labs::Index
|
32
|
+
|
33
|
+
# Attributes
|
34
|
+
# ======================================================================
|
35
|
+
|
36
|
+
|
37
|
+
# Constructor
|
38
|
+
# ======================================================================
|
39
|
+
|
40
|
+
# Instantiate a new `NRSER::Index`.
|
41
|
+
def initialize entries = nil, sort: false, &indexer
|
42
|
+
@indexer = indexer
|
43
|
+
@hash = Hash.new { |hash, key| hash[key] = Set.new }
|
44
|
+
|
45
|
+
add( *entries ) if entries
|
46
|
+
end # #initialize
|
47
|
+
|
48
|
+
|
49
|
+
# Instance Methods
|
50
|
+
# ======================================================================
|
51
|
+
|
52
|
+
def key_for entry
|
53
|
+
@indexer.call entry
|
54
|
+
end
|
55
|
+
|
56
|
+
|
57
|
+
def keys
|
58
|
+
Set.new @hash.keys
|
59
|
+
end
|
60
|
+
|
61
|
+
|
62
|
+
def values
|
63
|
+
@hash.values.reduce :+
|
64
|
+
end
|
65
|
+
|
66
|
+
|
67
|
+
def [] key
|
68
|
+
@hash[key]
|
69
|
+
end
|
70
|
+
|
71
|
+
|
72
|
+
def add *entries
|
73
|
+
entries.each do |entry|
|
74
|
+
@hash[key_for( entry )].add entry
|
75
|
+
end
|
76
|
+
|
77
|
+
self
|
78
|
+
end
|
79
|
+
|
80
|
+
|
81
|
+
def remove *entries
|
82
|
+
entries.each do |entry|
|
83
|
+
@hash[key_for( entry )].remove entry
|
84
|
+
end
|
85
|
+
|
86
|
+
self
|
87
|
+
end
|
88
|
+
|
89
|
+
end # class NRSER::Index
|
@@ -1,9 +1,7 @@
|
|
1
|
-
|
2
|
-
|
3
1
|
# Definitions
|
4
2
|
# =======================================================================
|
5
3
|
|
6
|
-
module NRSER
|
4
|
+
module NRSER::Labs
|
7
5
|
|
8
6
|
# A class to hold info about how to find a record (besides by primary key).
|
9
7
|
#
|
@@ -16,7 +14,7 @@ module NRSER
|
|
16
14
|
# {NRSER::Types::Where}...
|
17
15
|
#
|
18
16
|
# Maybe this functionality has something to do with the types system?
|
19
|
-
# It seems like the placeholder stuff would be hard to integrate with
|
17
|
+
# It seems like the placeholder stuff would be hard to integrate with
|
20
18
|
# that, but having a whole other very similar system sucks too.
|
21
19
|
#
|
22
20
|
class Where
|
data/lib/nrser/meta/props.rb
CHANGED
@@ -188,16 +188,19 @@ module NRSER::Meta::Props
|
|
188
188
|
prop = Prop.new self, name, **opts
|
189
189
|
ref[name] = prop
|
190
190
|
|
191
|
-
|
191
|
+
if prop.create_reader?
|
192
192
|
class_eval do
|
193
|
-
define_method
|
193
|
+
define_method prop.name do
|
194
194
|
prop.get self
|
195
195
|
end
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
196
|
+
end
|
197
|
+
end
|
198
|
+
|
199
|
+
if prop.create_writer?
|
200
|
+
class_eval do
|
201
|
+
define_method "#{ prop.name }=" do |value|
|
202
|
+
prop.set self, value
|
203
|
+
end
|
201
204
|
end
|
202
205
|
end
|
203
206
|
|
@@ -255,6 +258,9 @@ module NRSER::Meta::Props
|
|
255
258
|
self.class.props(only_primary: true).each { |name, prop|
|
256
259
|
prop.set_from_values_hash self, values
|
257
260
|
}
|
261
|
+
|
262
|
+
# TODO Now trigger all eager defaults (check prop getting trigger
|
263
|
+
# correctly)
|
258
264
|
end # #initialize_props
|
259
265
|
|
260
266
|
|
@@ -52,7 +52,18 @@ class NRSER::Meta::Props::Prop
|
|
52
52
|
# Props that have a source are considered *derived*, those that don't are
|
53
53
|
# called *primary*.
|
54
54
|
#
|
55
|
-
# @return [
|
55
|
+
# @return [nil]
|
56
|
+
# When this prop is a *primary* property and receives it's value at
|
57
|
+
# initialization or from a {#default}.
|
58
|
+
#
|
59
|
+
# @return [Symbol]
|
60
|
+
# This prop is *derived* by returning an instance variable if the symbol
|
61
|
+
# starts with `@` or otherwise by sending the symbol to the prop'd instance
|
62
|
+
# (calling that method with no arguments).
|
63
|
+
#
|
64
|
+
# @return [Proc]
|
65
|
+
# This prop is *derived* by evaluating this {Proc} in the prop'd
|
66
|
+
# instance.
|
56
67
|
#
|
57
68
|
attr_reader :source
|
58
69
|
|
@@ -67,18 +78,34 @@ class NRSER::Meta::Props::Prop
|
|
67
78
|
# `.prop` "macro" defined at {NRSER::Meta::Props::ClassMethods#prop}
|
68
79
|
# that is extended in to classes including {NRSER::Meta::Props}.
|
69
80
|
#
|
81
|
+
# @param [nil | Proc | Object] default:
|
82
|
+
# A default value or a {Proc} used to get default values for *primary*
|
83
|
+
# props. *Dervied* props (those that have a {#source}) may not
|
84
|
+
#
|
85
|
+
# At least one of `default:` and `source:` must be `nil`.
|
86
|
+
#
|
87
|
+
# @param [nil | Symbol | String | Proc] source:
|
88
|
+
# Source that provides the prop's value. See details for how each type is
|
89
|
+
# handled in {#source}. Strings are converted to symbols.
|
90
|
+
#
|
91
|
+
# At least one of `default:` and `source:` must be `nil`.
|
92
|
+
#
|
93
|
+
# @raise [ArgumentError]
|
94
|
+
# If `default:` is not `nil` *and* `source:` is not `nil`.
|
95
|
+
#
|
96
|
+
# @raise
|
97
|
+
#
|
70
98
|
def initialize defined_in,
|
71
99
|
name,
|
72
100
|
type: t.any,
|
73
101
|
default: nil,
|
74
|
-
default_from: nil,
|
75
102
|
source: nil,
|
76
103
|
to_data: nil,
|
77
104
|
from_data: nil
|
78
105
|
|
79
106
|
# Set these up first so {#to_s} works in case we need to raise errors.
|
80
107
|
@defined_in = defined_in
|
81
|
-
@name = name
|
108
|
+
@name = t.sym.check name
|
82
109
|
@type = t.make type
|
83
110
|
|
84
111
|
@to_data = to_data
|
@@ -86,90 +113,121 @@ class NRSER::Meta::Props::Prop
|
|
86
113
|
|
87
114
|
# Source
|
88
115
|
|
89
|
-
|
116
|
+
# normalize source to {nil}, {Symbol} or {Proc}
|
117
|
+
@source = t.match source,
|
118
|
+
nil, nil,
|
119
|
+
String, ->( string ) { string.to_sym },
|
120
|
+
Symbol, source,
|
121
|
+
Proc, ->(){ source }
|
90
122
|
|
91
|
-
# Detect if the source
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
# TODO Check that default and default_from are `nil`, make no sense here
|
96
|
-
|
97
|
-
source_str = source.to_s
|
98
|
-
@instance_variable_source = source_str[0] == '@'
|
99
|
-
end
|
123
|
+
# Detect if the source points to an instance variable (`:'@name'`-formatted
|
124
|
+
# symbol).
|
125
|
+
@instance_variable_source = \
|
126
|
+
@source.is_a?( Symbol ) && @source.to_s[0] == '@'
|
100
127
|
|
101
|
-
|
128
|
+
init_default! default
|
102
129
|
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
default:
|
110
|
-
<%= default.pretty_inspect %>
|
111
|
-
|
112
|
-
default_from:
|
113
|
-
<%= default_from.pretty_inspect %>
|
114
|
-
|
115
|
-
ERB
|
116
|
-
end
|
130
|
+
end # #initialize
|
131
|
+
|
132
|
+
|
133
|
+
protected
|
134
|
+
# ========================================================================
|
117
135
|
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
# Validate `default` value
|
136
|
+
|
137
|
+
def init_default! default
|
122
138
|
if default.nil?
|
123
|
-
# If it's `nil
|
124
|
-
#
|
125
|
-
|
126
|
-
|
127
|
-
#
|
128
|
-
@has_default = if source.nil?
|
129
|
-
@type.test default
|
130
|
-
else
|
131
|
-
# NOTE This is up for debate... does a derived property have a
|
132
|
-
# default? What does that even mean?
|
133
|
-
true # false ?
|
134
|
-
end
|
135
|
-
|
136
|
-
else
|
137
|
-
# Check that the default value is valid for the type, raising TypeError
|
138
|
-
# if it isn't.
|
139
|
-
@type.check( default ) { |type:, value:|
|
140
|
-
binding.erb <<-ERB
|
141
|
-
Default value is not valid for <%= self %>:
|
142
|
-
|
143
|
-
<%= value.pretty_inspect %>
|
144
|
-
|
145
|
-
ERB
|
146
|
-
}
|
147
|
-
|
148
|
-
# If we passed the check we know the value is valid
|
149
|
-
@has_default = true
|
150
|
-
|
151
|
-
# Set the default value to `default`, freezing it since it will be
|
152
|
-
# set on instances without any attempt at duplication, which seems like
|
153
|
-
# it *might be ok* since a lot of prop'd classes are being used
|
154
|
-
# immutably.
|
155
|
-
@default_value = default.freeze
|
139
|
+
# If it's `nil`, we will use it as the default value *if* this
|
140
|
+
# is a primary prop *and* the type is satisfied by `nil`
|
141
|
+
@has_default = source? && @type.test( default )
|
142
|
+
return
|
156
143
|
end
|
157
144
|
|
158
|
-
|
159
|
-
#
|
145
|
+
# Now the we know that the default isn't `nil`, we want to check that
|
146
|
+
# the prop doesn't have a source, because defaults don't make any sense
|
147
|
+
# for sourced props
|
148
|
+
if source?
|
149
|
+
raise ArgumentError.new binding.erb <<-END
|
150
|
+
Can not construct {<%= self.class.name %>} with `default` and `source`
|
151
|
+
|
152
|
+
Props with {#source} always get their value from that source, so
|
153
|
+
defaults don't make any sense.
|
154
|
+
|
155
|
+
Attempted to construct prop <%= name.inspect %> for class
|
156
|
+
{<%= defined_in.name %>} with:
|
157
|
+
|
158
|
+
default:
|
159
|
+
|
160
|
+
<%= default.pretty_inspect %>
|
161
|
+
|
162
|
+
source:
|
163
|
+
|
164
|
+
<%= source.pretty_inspect %>
|
165
|
+
|
166
|
+
END
|
167
|
+
end
|
160
168
|
|
161
|
-
#
|
162
|
-
|
169
|
+
# It must be a {Proc} or be frozen
|
170
|
+
unless Proc === default || default.frozen?
|
171
|
+
raise ArgumentError.new binding.erb <<-END
|
172
|
+
Non-proc default values must be frozen
|
173
|
+
|
174
|
+
Default values that are *not* a {Proc} are shared between *all*
|
175
|
+
instances of the prop'd class, and as such *must* be immutable
|
176
|
+
(`#frozen? == true`).
|
177
|
+
|
178
|
+
Found `default`:
|
179
|
+
|
180
|
+
<%= default.pretty_inspect %>
|
181
|
+
|
182
|
+
when constructing prop <%= name.inspect %>
|
183
|
+
for class <%= defined_in.name %>
|
184
|
+
END
|
185
|
+
end
|
186
|
+
|
163
187
|
@has_default = true
|
164
|
-
|
165
|
-
|
166
|
-
#
|
167
|
-
# TODO validate it's something reasonable here?
|
168
|
-
#
|
169
|
-
@default_from = default_from
|
170
|
-
end
|
188
|
+
@default = default
|
189
|
+
end # #init_default!
|
171
190
|
|
172
|
-
end
|
191
|
+
# end protected
|
192
|
+
public
|
193
|
+
|
194
|
+
|
195
|
+
# Instance Methods
|
196
|
+
# ============================================================================
|
197
|
+
|
198
|
+
# Used by the {NRSER::Meta::Props::ClassMethods.prop} "macro" method to
|
199
|
+
# determine if it should create a reader method on the propertied class.
|
200
|
+
#
|
201
|
+
# @return [Boolean]
|
202
|
+
# `true` if a reader method should be created for the prop value.
|
203
|
+
#
|
204
|
+
def create_reader?
|
205
|
+
# Always create readers for primary props
|
206
|
+
return true if primary?
|
207
|
+
|
208
|
+
# Don't override methods
|
209
|
+
return false if defined_in.instance_methods.include?( name )
|
210
|
+
|
211
|
+
# Create if {#source} is a {Proc} so it's accessible
|
212
|
+
return true if Proc === source
|
213
|
+
|
214
|
+
# Source is a symbol; only create if it's not the same as the name
|
215
|
+
return source != name
|
216
|
+
end # #create_reader?
|
217
|
+
|
218
|
+
|
219
|
+
# Used by the {NRSER::Meta::Props::ClassMethods.prop} "macro" method to
|
220
|
+
# determine if it should create a writer method on the propertied class.
|
221
|
+
#
|
222
|
+
# Right now, we don't create writers, but we will probably make them an
|
223
|
+
# option in the future, which is why this stub is here.
|
224
|
+
#
|
225
|
+
# @return [Boolean]
|
226
|
+
# Always `false` for the moment.
|
227
|
+
#
|
228
|
+
def create_writer?
|
229
|
+
false
|
230
|
+
end # #create_writer?
|
173
231
|
|
174
232
|
|
175
233
|
# Full name with class prop was defined in.
|
@@ -202,8 +260,12 @@ class NRSER::Meta::Props::Prop
|
|
202
260
|
|
203
261
|
|
204
262
|
def default
|
205
|
-
if
|
206
|
-
@default
|
263
|
+
if has_default?
|
264
|
+
if Proc === @default
|
265
|
+
@default.call
|
266
|
+
else
|
267
|
+
@default
|
268
|
+
end
|
207
269
|
else
|
208
270
|
raise NameError.new NRSER.squish <<-END
|
209
271
|
Prop #{ self } has no default value.
|
@@ -212,13 +274,9 @@ class NRSER::Meta::Props::Prop
|
|
212
274
|
end
|
213
275
|
|
214
276
|
|
215
|
-
#
|
216
|
-
#
|
217
|
-
# @param [type] arg_name
|
218
|
-
# @todo Add name param description.
|
277
|
+
# Does this property have a source method that it gets it's value from?
|
219
278
|
#
|
220
|
-
# @return [
|
221
|
-
# @todo Document return value.
|
279
|
+
# @return [Boolean]
|
222
280
|
#
|
223
281
|
def source?
|
224
282
|
!@source.nil?
|
@@ -466,7 +524,7 @@ class NRSER::Meta::Props::Prop
|
|
466
524
|
|
467
525
|
ERB
|
468
526
|
end
|
469
|
-
|
527
|
+
|
470
528
|
end # #value_from_data
|
471
529
|
|
472
530
|
|
@@ -16,7 +16,7 @@ module NRSER
|
|
16
16
|
# @return [Exception]
|
17
17
|
#
|
18
18
|
def squished message
|
19
|
-
new
|
19
|
+
new NRSER.squish( message )
|
20
20
|
end
|
21
21
|
|
22
22
|
# Create a new instance from the dedented message.
|
@@ -28,7 +28,7 @@ module NRSER
|
|
28
28
|
# @return [Exception]
|
29
29
|
#
|
30
30
|
def dedented message
|
31
|
-
new
|
31
|
+
new NRSER.dedent( message )
|
32
32
|
end
|
33
33
|
|
34
34
|
end # refine Exception.singleton_class
|