ardm 0.0.1
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 +15 -0
- data/.gitignore +35 -0
- data/Gemfile +13 -0
- data/LICENSE +21 -0
- data/README.md +70 -0
- data/Rakefile +4 -0
- data/ardm.gemspec +29 -0
- data/db/.gitignore +1 -0
- data/lib/ardm/active_record/associations.rb +80 -0
- data/lib/ardm/active_record/base.rb +49 -0
- data/lib/ardm/active_record/dirty.rb +25 -0
- data/lib/ardm/active_record/hooks.rb +31 -0
- data/lib/ardm/active_record/inheritance.rb +37 -0
- data/lib/ardm/active_record/is/state_machine.rb +21 -0
- data/lib/ardm/active_record/is.rb +22 -0
- data/lib/ardm/active_record/not_found.rb +7 -0
- data/lib/ardm/active_record/predicate_builder/array_handler.rb +31 -0
- data/lib/ardm/active_record/predicate_builder/rails3.rb +147 -0
- data/lib/ardm/active_record/predicate_builder/rails4.rb +139 -0
- data/lib/ardm/active_record/predicate_builder/relation_handler.rb +15 -0
- data/lib/ardm/active_record/predicate_builder.rb +19 -0
- data/lib/ardm/active_record/property.rb +357 -0
- data/lib/ardm/active_record/query.rb +108 -0
- data/lib/ardm/active_record/record.rb +70 -0
- data/lib/ardm/active_record/relation.rb +83 -0
- data/lib/ardm/active_record/repository.rb +38 -0
- data/lib/ardm/active_record/serialization.rb +164 -0
- data/lib/ardm/active_record/storage_names.rb +28 -0
- data/lib/ardm/active_record/validations.rb +111 -0
- data/lib/ardm/active_record.rb +43 -0
- data/lib/ardm/data_mapper/not_found.rb +5 -0
- data/lib/ardm/data_mapper/record.rb +41 -0
- data/lib/ardm/data_mapper.rb +5 -0
- data/lib/ardm/env.rb +5 -0
- data/lib/ardm/property/api_key.rb +30 -0
- data/lib/ardm/property/bcrypt_hash.rb +31 -0
- data/lib/ardm/property/binary.rb +23 -0
- data/lib/ardm/property/boolean.rb +29 -0
- data/lib/ardm/property/class.rb +19 -0
- data/lib/ardm/property/comma_separated_list.rb +28 -0
- data/lib/ardm/property/csv.rb +35 -0
- data/lib/ardm/property/date.rb +12 -0
- data/lib/ardm/property/datetime.rb +12 -0
- data/lib/ardm/property/decimal.rb +38 -0
- data/lib/ardm/property/discriminator.rb +65 -0
- data/lib/ardm/property/enum.rb +51 -0
- data/lib/ardm/property/epoch_time.rb +38 -0
- data/lib/ardm/property/file_path.rb +25 -0
- data/lib/ardm/property/flag.rb +65 -0
- data/lib/ardm/property/float.rb +18 -0
- data/lib/ardm/property/integer.rb +24 -0
- data/lib/ardm/property/invalid_value_error.rb +22 -0
- data/lib/ardm/property/ip_address.rb +35 -0
- data/lib/ardm/property/json.rb +49 -0
- data/lib/ardm/property/lookup.rb +29 -0
- data/lib/ardm/property/numeric.rb +40 -0
- data/lib/ardm/property/object.rb +36 -0
- data/lib/ardm/property/paranoid_boolean.rb +18 -0
- data/lib/ardm/property/paranoid_datetime.rb +17 -0
- data/lib/ardm/property/regexp.rb +22 -0
- data/lib/ardm/property/serial.rb +16 -0
- data/lib/ardm/property/slug.rb +29 -0
- data/lib/ardm/property/string.rb +40 -0
- data/lib/ardm/property/support/dirty_minder.rb +169 -0
- data/lib/ardm/property/support/flags.rb +41 -0
- data/lib/ardm/property/support/paranoid_base.rb +78 -0
- data/lib/ardm/property/text.rb +11 -0
- data/lib/ardm/property/time.rb +12 -0
- data/lib/ardm/property/uri.rb +27 -0
- data/lib/ardm/property/uuid.rb +65 -0
- data/lib/ardm/property/validation.rb +208 -0
- data/lib/ardm/property/yaml.rb +38 -0
- data/lib/ardm/property.rb +891 -0
- data/lib/ardm/property_set.rb +152 -0
- data/lib/ardm/query/expression.rb +85 -0
- data/lib/ardm/query/ext/symbol.rb +37 -0
- data/lib/ardm/query/operator.rb +64 -0
- data/lib/ardm/record.rb +1 -0
- data/lib/ardm/support/assertions.rb +8 -0
- data/lib/ardm/support/deprecate.rb +12 -0
- data/lib/ardm/support/descendant_set.rb +89 -0
- data/lib/ardm/support/equalizer.rb +48 -0
- data/lib/ardm/support/ext/array.rb +22 -0
- data/lib/ardm/support/ext/blank.rb +25 -0
- data/lib/ardm/support/ext/hash.rb +67 -0
- data/lib/ardm/support/ext/module.rb +47 -0
- data/lib/ardm/support/ext/object.rb +57 -0
- data/lib/ardm/support/ext/string.rb +24 -0
- data/lib/ardm/support/ext/try_dup.rb +12 -0
- data/lib/ardm/support/hook.rb +405 -0
- data/lib/ardm/support/lazy_array.rb +451 -0
- data/lib/ardm/support/local_object_space.rb +13 -0
- data/lib/ardm/support/logger.rb +201 -0
- data/lib/ardm/support/mash.rb +176 -0
- data/lib/ardm/support/naming_conventions.rb +90 -0
- data/lib/ardm/support/ordered_set.rb +380 -0
- data/lib/ardm/support/subject.rb +33 -0
- data/lib/ardm/support/subject_set.rb +250 -0
- data/lib/ardm/version.rb +3 -0
- data/lib/ardm.rb +56 -0
- data/spec/fixtures/api_user.rb +11 -0
- data/spec/fixtures/article.rb +22 -0
- data/spec/fixtures/bookmark.rb +14 -0
- data/spec/fixtures/invention.rb +5 -0
- data/spec/fixtures/network_node.rb +23 -0
- data/spec/fixtures/person.rb +17 -0
- data/spec/fixtures/software_package.rb +22 -0
- data/spec/fixtures/ticket.rb +12 -0
- data/spec/fixtures/tshirt.rb +15 -0
- data/spec/integration/api_key_spec.rb +25 -0
- data/spec/integration/bcrypt_hash_spec.rb +45 -0
- data/spec/integration/comma_separated_list_spec.rb +85 -0
- data/spec/integration/dirty_minder_spec.rb +197 -0
- data/spec/integration/enum_spec.rb +79 -0
- data/spec/integration/epoch_time_spec.rb +59 -0
- data/spec/integration/file_path_spec.rb +158 -0
- data/spec/integration/flag_spec.rb +72 -0
- data/spec/integration/ip_address_spec.rb +151 -0
- data/spec/integration/json_spec.rb +70 -0
- data/spec/integration/slug_spec.rb +65 -0
- data/spec/integration/uri_spec.rb +136 -0
- data/spec/integration/uuid_spec.rb +102 -0
- data/spec/integration/yaml_spec.rb +85 -0
- data/spec/public/property/binary_spec.rb +41 -0
- data/spec/public/property/boolean_spec.rb +30 -0
- data/spec/public/property/class_spec.rb +28 -0
- data/spec/public/property/date_spec.rb +22 -0
- data/spec/public/property/date_time_spec.rb +22 -0
- data/spec/public/property/decimal_spec.rb +23 -0
- data/spec/public/property/discriminator_spec.rb +133 -0
- data/spec/public/property/float_spec.rb +22 -0
- data/spec/public/property/integer_spec.rb +22 -0
- data/spec/public/property/object_spec.rb +103 -0
- data/spec/public/property/serial_spec.rb +22 -0
- data/spec/public/property/string_spec.rb +22 -0
- data/spec/public/property/text_spec.rb +23 -0
- data/spec/public/property/time_spec.rb +22 -0
- data/spec/public/property_spec.rb +316 -0
- data/spec/rcov.opts +6 -0
- data/spec/schema.rb +86 -0
- data/spec/semipublic/property/binary_spec.rb +14 -0
- data/spec/semipublic/property/boolean_spec.rb +48 -0
- data/spec/semipublic/property/class_spec.rb +36 -0
- data/spec/semipublic/property/date_spec.rb +44 -0
- data/spec/semipublic/property/date_time_spec.rb +47 -0
- data/spec/semipublic/property/decimal_spec.rb +83 -0
- data/spec/semipublic/property/discriminator_spec.rb +22 -0
- data/spec/semipublic/property/float_spec.rb +83 -0
- data/spec/semipublic/property/integer_spec.rb +83 -0
- data/spec/semipublic/property/lookup_spec.rb +27 -0
- data/spec/semipublic/property/serial_spec.rb +14 -0
- data/spec/semipublic/property/string_spec.rb +14 -0
- data/spec/semipublic/property/text_spec.rb +30 -0
- data/spec/semipublic/property/time_spec.rb +49 -0
- data/spec/semipublic/property_spec.rb +51 -0
- data/spec/shared/flags_shared_spec.rb +36 -0
- data/spec/shared/identity_function_group.rb +5 -0
- data/spec/shared/public_property_spec.rb +229 -0
- data/spec/shared/semipublic_property_spec.rb +159 -0
- data/spec/spec.opts +4 -0
- data/spec/spec_helper.rb +58 -0
- data/spec/unit/bcrypt_hash_spec.rb +154 -0
- data/spec/unit/csv_spec.rb +139 -0
- data/spec/unit/dirty_minder_spec.rb +64 -0
- data/spec/unit/enum_spec.rb +125 -0
- data/spec/unit/epoch_time_spec.rb +72 -0
- data/spec/unit/file_path_spec.rb +75 -0
- data/spec/unit/flag_spec.rb +114 -0
- data/spec/unit/ip_address_spec.rb +109 -0
- data/spec/unit/json_spec.rb +127 -0
- data/spec/unit/paranoid_boolean_spec.rb +142 -0
- data/spec/unit/paranoid_datetime_spec.rb +149 -0
- data/spec/unit/regexp_spec.rb +62 -0
- data/spec/unit/uri_spec.rb +64 -0
- data/spec/unit/yaml_spec.rb +111 -0
- data/tasks/spec.rake +40 -0
- data/tasks/yard.rake +9 -0
- data/tasks/yardstick.rake +19 -0
- metadata +350 -0
|
@@ -0,0 +1,451 @@
|
|
|
1
|
+
class LazyArray # borrowed partially from StrokeDB
|
|
2
|
+
include Enumerable
|
|
3
|
+
|
|
4
|
+
attr_reader :head, :tail
|
|
5
|
+
|
|
6
|
+
def first(*args)
|
|
7
|
+
if lazy_possible?(@head, *args)
|
|
8
|
+
@head.first(*args)
|
|
9
|
+
else
|
|
10
|
+
lazy_load
|
|
11
|
+
@array.first(*args)
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def last(*args)
|
|
16
|
+
if lazy_possible?(@tail, *args)
|
|
17
|
+
@tail.last(*args)
|
|
18
|
+
else
|
|
19
|
+
lazy_load
|
|
20
|
+
@array.last(*args)
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def at(index)
|
|
25
|
+
if index >= 0 && lazy_possible?(@head, index + 1)
|
|
26
|
+
@head.at(index)
|
|
27
|
+
elsif index < 0 && lazy_possible?(@tail, index.abs)
|
|
28
|
+
@tail.at(index)
|
|
29
|
+
else
|
|
30
|
+
lazy_load
|
|
31
|
+
@array.at(index)
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def fetch(*args, &block)
|
|
36
|
+
index = args.first
|
|
37
|
+
|
|
38
|
+
if index >= 0 && lazy_possible?(@head, index + 1)
|
|
39
|
+
@head.fetch(*args, &block)
|
|
40
|
+
elsif index < 0 && lazy_possible?(@tail, index.abs)
|
|
41
|
+
@tail.fetch(*args, &block)
|
|
42
|
+
else
|
|
43
|
+
lazy_load
|
|
44
|
+
@array.fetch(*args, &block)
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def values_at(*args)
|
|
49
|
+
accumulator = []
|
|
50
|
+
|
|
51
|
+
lazy_possible = args.all? do |arg|
|
|
52
|
+
index, length = extract_slice_arguments(arg)
|
|
53
|
+
|
|
54
|
+
if index >= 0 && lazy_possible?(@head, index + length)
|
|
55
|
+
accumulator.concat(head.values_at(*arg))
|
|
56
|
+
elsif index < 0 && lazy_possible?(@tail, index.abs)
|
|
57
|
+
accumulator.concat(tail.values_at(*arg))
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
if lazy_possible
|
|
62
|
+
accumulator
|
|
63
|
+
else
|
|
64
|
+
lazy_load
|
|
65
|
+
@array.values_at(*args)
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def index(entry)
|
|
70
|
+
(lazy_possible?(@head) && @head.index(entry)) || begin
|
|
71
|
+
lazy_load
|
|
72
|
+
@array.index(entry)
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def include?(entry)
|
|
77
|
+
(lazy_possible?(@tail) && @tail.include?(entry)) ||
|
|
78
|
+
(lazy_possible?(@head) && @head.include?(entry)) || begin
|
|
79
|
+
lazy_load
|
|
80
|
+
@array.include?(entry)
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
def empty?
|
|
85
|
+
(@tail.nil? || @tail.empty?) &&
|
|
86
|
+
(@head.nil? || @head.empty?) && begin
|
|
87
|
+
lazy_load
|
|
88
|
+
@array.empty?
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
def any?(&block)
|
|
93
|
+
(lazy_possible?(@tail) && @tail.any?(&block)) ||
|
|
94
|
+
(lazy_possible?(@head) && @head.any?(&block)) || begin
|
|
95
|
+
lazy_load
|
|
96
|
+
@array.any?(&block)
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
def [](*args)
|
|
101
|
+
index, length = extract_slice_arguments(*args)
|
|
102
|
+
|
|
103
|
+
if length == 1 && args.size == 1 && args.first.kind_of?(Integer)
|
|
104
|
+
return at(index)
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
if index >= 0 && lazy_possible?(@head, index + length)
|
|
108
|
+
@head[*args]
|
|
109
|
+
elsif index < 0 && lazy_possible?(@tail, index.abs - 1 + length)
|
|
110
|
+
@tail[*args]
|
|
111
|
+
else
|
|
112
|
+
lazy_load
|
|
113
|
+
@array[*args]
|
|
114
|
+
end
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
alias_method :slice, :[]
|
|
118
|
+
|
|
119
|
+
def slice!(*args)
|
|
120
|
+
index, length = extract_slice_arguments(*args)
|
|
121
|
+
|
|
122
|
+
if index >= 0 && lazy_possible?(@head, index + length)
|
|
123
|
+
@head.slice!(*args)
|
|
124
|
+
elsif index < 0 && lazy_possible?(@tail, index.abs - 1 + length)
|
|
125
|
+
@tail.slice!(*args)
|
|
126
|
+
else
|
|
127
|
+
lazy_load
|
|
128
|
+
@array.slice!(*args)
|
|
129
|
+
end
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
def []=(*args)
|
|
133
|
+
index, length = extract_slice_arguments(*args[0..-2])
|
|
134
|
+
|
|
135
|
+
if index >= 0 && lazy_possible?(@head, index + length)
|
|
136
|
+
@head.[]=(*args)
|
|
137
|
+
elsif index < 0 && lazy_possible?(@tail, index.abs - 1 + length)
|
|
138
|
+
@tail.[]=(*args)
|
|
139
|
+
else
|
|
140
|
+
lazy_load
|
|
141
|
+
@array.[]=(*args)
|
|
142
|
+
end
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
alias_method :splice, :[]=
|
|
146
|
+
|
|
147
|
+
def reverse
|
|
148
|
+
dup.reverse!
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
def reverse!
|
|
152
|
+
# reverse without kicking if possible
|
|
153
|
+
if loaded?
|
|
154
|
+
@array = @array.reverse
|
|
155
|
+
else
|
|
156
|
+
@head, @tail = @tail.reverse, @head.reverse
|
|
157
|
+
|
|
158
|
+
proc = @load_with_proc
|
|
159
|
+
|
|
160
|
+
@load_with_proc = lambda do |v|
|
|
161
|
+
proc.call(v)
|
|
162
|
+
v.instance_variable_get(:@array).reverse!
|
|
163
|
+
end
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
self
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
def <<(entry)
|
|
170
|
+
if loaded?
|
|
171
|
+
lazy_load
|
|
172
|
+
@array << entry
|
|
173
|
+
else
|
|
174
|
+
@tail << entry
|
|
175
|
+
end
|
|
176
|
+
self
|
|
177
|
+
end
|
|
178
|
+
|
|
179
|
+
def concat(other)
|
|
180
|
+
if loaded?
|
|
181
|
+
lazy_load
|
|
182
|
+
@array.concat(other)
|
|
183
|
+
else
|
|
184
|
+
@tail.concat(other)
|
|
185
|
+
end
|
|
186
|
+
self
|
|
187
|
+
end
|
|
188
|
+
|
|
189
|
+
def push(*entries)
|
|
190
|
+
if loaded?
|
|
191
|
+
lazy_load
|
|
192
|
+
@array.push(*entries)
|
|
193
|
+
else
|
|
194
|
+
@tail.push(*entries)
|
|
195
|
+
end
|
|
196
|
+
self
|
|
197
|
+
end
|
|
198
|
+
|
|
199
|
+
def unshift(*entries)
|
|
200
|
+
if loaded?
|
|
201
|
+
lazy_load
|
|
202
|
+
@array.unshift(*entries)
|
|
203
|
+
else
|
|
204
|
+
@head.unshift(*entries)
|
|
205
|
+
end
|
|
206
|
+
self
|
|
207
|
+
end
|
|
208
|
+
|
|
209
|
+
def insert(index, *entries)
|
|
210
|
+
if index >= 0 && lazy_possible?(@head, index)
|
|
211
|
+
@head.insert(index, *entries)
|
|
212
|
+
elsif index < 0 && lazy_possible?(@tail, index.abs - 1)
|
|
213
|
+
@tail.insert(index, *entries)
|
|
214
|
+
else
|
|
215
|
+
lazy_load
|
|
216
|
+
@array.insert(index, *entries)
|
|
217
|
+
end
|
|
218
|
+
self
|
|
219
|
+
end
|
|
220
|
+
|
|
221
|
+
def pop(*args)
|
|
222
|
+
if lazy_possible?(@tail, *args)
|
|
223
|
+
@tail.pop(*args)
|
|
224
|
+
else
|
|
225
|
+
lazy_load
|
|
226
|
+
@array.pop(*args)
|
|
227
|
+
end
|
|
228
|
+
end
|
|
229
|
+
|
|
230
|
+
def shift(*args)
|
|
231
|
+
if lazy_possible?(@head, *args)
|
|
232
|
+
@head.shift(*args)
|
|
233
|
+
else
|
|
234
|
+
lazy_load
|
|
235
|
+
@array.shift(*args)
|
|
236
|
+
end
|
|
237
|
+
end
|
|
238
|
+
|
|
239
|
+
def delete_at(index)
|
|
240
|
+
if index >= 0 && lazy_possible?(@head, index + 1)
|
|
241
|
+
@head.delete_at(index)
|
|
242
|
+
elsif index < 0 && lazy_possible?(@tail, index.abs)
|
|
243
|
+
@tail.delete_at(index)
|
|
244
|
+
else
|
|
245
|
+
lazy_load
|
|
246
|
+
@array.delete_at(index)
|
|
247
|
+
end
|
|
248
|
+
end
|
|
249
|
+
|
|
250
|
+
def delete_if(&block)
|
|
251
|
+
if loaded?
|
|
252
|
+
lazy_load
|
|
253
|
+
@array.delete_if(&block)
|
|
254
|
+
else
|
|
255
|
+
@reapers << block
|
|
256
|
+
@head.delete_if(&block)
|
|
257
|
+
@tail.delete_if(&block)
|
|
258
|
+
end
|
|
259
|
+
self
|
|
260
|
+
end
|
|
261
|
+
|
|
262
|
+
def replace(other)
|
|
263
|
+
mark_loaded
|
|
264
|
+
@array.replace(other)
|
|
265
|
+
self
|
|
266
|
+
end
|
|
267
|
+
|
|
268
|
+
def clear
|
|
269
|
+
mark_loaded
|
|
270
|
+
@array.clear
|
|
271
|
+
self
|
|
272
|
+
end
|
|
273
|
+
|
|
274
|
+
def to_a
|
|
275
|
+
lazy_load
|
|
276
|
+
@array.to_a
|
|
277
|
+
end
|
|
278
|
+
|
|
279
|
+
alias_method :to_ary, :to_a
|
|
280
|
+
|
|
281
|
+
def load_with(&block)
|
|
282
|
+
@load_with_proc = block
|
|
283
|
+
self
|
|
284
|
+
end
|
|
285
|
+
|
|
286
|
+
def loaded?
|
|
287
|
+
@loaded == true
|
|
288
|
+
end
|
|
289
|
+
|
|
290
|
+
def kind_of?(klass)
|
|
291
|
+
super || @array.kind_of?(klass)
|
|
292
|
+
end
|
|
293
|
+
|
|
294
|
+
alias_method :is_a?, :kind_of?
|
|
295
|
+
|
|
296
|
+
def respond_to?(method, include_private = false)
|
|
297
|
+
super || @array.respond_to?(method)
|
|
298
|
+
end
|
|
299
|
+
|
|
300
|
+
def freeze
|
|
301
|
+
if loaded?
|
|
302
|
+
@array.freeze
|
|
303
|
+
else
|
|
304
|
+
@head.freeze
|
|
305
|
+
@tail.freeze
|
|
306
|
+
end
|
|
307
|
+
@frozen = true
|
|
308
|
+
self
|
|
309
|
+
end
|
|
310
|
+
|
|
311
|
+
def frozen?
|
|
312
|
+
@frozen == true
|
|
313
|
+
end
|
|
314
|
+
|
|
315
|
+
def ==(other)
|
|
316
|
+
if equal?(other)
|
|
317
|
+
return true
|
|
318
|
+
end
|
|
319
|
+
|
|
320
|
+
unless other.respond_to?(:to_ary)
|
|
321
|
+
return false
|
|
322
|
+
end
|
|
323
|
+
|
|
324
|
+
# if necessary, convert to something that can be compared
|
|
325
|
+
other = other.to_ary unless other.respond_to?(:[])
|
|
326
|
+
|
|
327
|
+
cmp?(other, :==)
|
|
328
|
+
end
|
|
329
|
+
|
|
330
|
+
def eql?(other)
|
|
331
|
+
if equal?(other)
|
|
332
|
+
return true
|
|
333
|
+
end
|
|
334
|
+
|
|
335
|
+
unless other.class.equal?(self.class)
|
|
336
|
+
return false
|
|
337
|
+
end
|
|
338
|
+
|
|
339
|
+
cmp?(other, :eql?)
|
|
340
|
+
end
|
|
341
|
+
|
|
342
|
+
def lazy_possible?(list, need_length = 1)
|
|
343
|
+
!loaded? && need_length <= list.size
|
|
344
|
+
end
|
|
345
|
+
|
|
346
|
+
private
|
|
347
|
+
|
|
348
|
+
def initialize
|
|
349
|
+
@frozen = false
|
|
350
|
+
@loaded = false
|
|
351
|
+
@load_with_proc = lambda { |v| v }
|
|
352
|
+
@head = []
|
|
353
|
+
@tail = []
|
|
354
|
+
@array = []
|
|
355
|
+
@reapers = []
|
|
356
|
+
end
|
|
357
|
+
|
|
358
|
+
def initialize_copy(original)
|
|
359
|
+
@head = Ardm::Ext.try_dup(@head)
|
|
360
|
+
@tail = Ardm::Ext.try_dup(@tail)
|
|
361
|
+
@array = Ardm::Ext.try_dup(@array)
|
|
362
|
+
end
|
|
363
|
+
|
|
364
|
+
def lazy_load
|
|
365
|
+
return if loaded?
|
|
366
|
+
mark_loaded
|
|
367
|
+
@load_with_proc[self]
|
|
368
|
+
@array.unshift(*@head)
|
|
369
|
+
@array.concat(@tail)
|
|
370
|
+
@head = @tail = nil
|
|
371
|
+
@reapers.each { |r| @array.delete_if(&r) } if @reapers
|
|
372
|
+
@array.freeze if frozen?
|
|
373
|
+
end
|
|
374
|
+
|
|
375
|
+
def mark_loaded
|
|
376
|
+
@loaded = true
|
|
377
|
+
end
|
|
378
|
+
|
|
379
|
+
##
|
|
380
|
+
# Extract arguments for #slice an #slice! and return index and length
|
|
381
|
+
#
|
|
382
|
+
# @param [Integer, Array(Integer), Range] *args the index,
|
|
383
|
+
# index and length, or range indicating first and last position
|
|
384
|
+
#
|
|
385
|
+
# @return [Integer] the index
|
|
386
|
+
# @return [Integer,NilClass] the length, if any
|
|
387
|
+
#
|
|
388
|
+
# @api private
|
|
389
|
+
def extract_slice_arguments(*args)
|
|
390
|
+
first_arg, second_arg = args
|
|
391
|
+
|
|
392
|
+
if args.size == 2 && first_arg.kind_of?(Integer) && second_arg.kind_of?(Integer)
|
|
393
|
+
return first_arg, second_arg
|
|
394
|
+
elsif args.size == 1
|
|
395
|
+
if first_arg.kind_of?(Integer)
|
|
396
|
+
return first_arg, 1
|
|
397
|
+
elsif first_arg.kind_of?(Range)
|
|
398
|
+
index = first_arg.first
|
|
399
|
+
length = first_arg.last - index
|
|
400
|
+
length += 1 unless first_arg.exclude_end?
|
|
401
|
+
return index, length
|
|
402
|
+
end
|
|
403
|
+
end
|
|
404
|
+
|
|
405
|
+
raise ArgumentError, "arguments may be 1 or 2 Integers, or 1 Range object, was: #{args.inspect}", caller(1)
|
|
406
|
+
end
|
|
407
|
+
|
|
408
|
+
def each
|
|
409
|
+
lazy_load
|
|
410
|
+
if block_given?
|
|
411
|
+
@array.each { |entry| yield entry }
|
|
412
|
+
self
|
|
413
|
+
else
|
|
414
|
+
@array.each
|
|
415
|
+
end
|
|
416
|
+
end
|
|
417
|
+
|
|
418
|
+
# delegate any not-explicitly-handled methods to @array, if possible.
|
|
419
|
+
# this is handy for handling methods mixed-into Array like group_by
|
|
420
|
+
def method_missing(method, *args, &block)
|
|
421
|
+
if @array.respond_to?(method)
|
|
422
|
+
lazy_load
|
|
423
|
+
results = @array.send(method, *args, &block)
|
|
424
|
+
results.equal?(@array) ? self : results
|
|
425
|
+
else
|
|
426
|
+
super
|
|
427
|
+
end
|
|
428
|
+
end
|
|
429
|
+
|
|
430
|
+
def cmp?(other, operator)
|
|
431
|
+
unless loaded?
|
|
432
|
+
# compare the head against the beginning of other. start at index
|
|
433
|
+
# 0 and incrementally compare each entry. if other is a LazyArray
|
|
434
|
+
# this has a lesser likelyhood of triggering a lazy load
|
|
435
|
+
0.upto(@head.size - 1) do |i|
|
|
436
|
+
return false unless @head[i].__send__(operator, other[i])
|
|
437
|
+
end
|
|
438
|
+
|
|
439
|
+
# compare the tail against the end of other. start at index
|
|
440
|
+
# -1 and decrementally compare each entry. if other is a LazyArray
|
|
441
|
+
# this has a lesser likelyhood of triggering a lazy load
|
|
442
|
+
-1.downto(@tail.size * -1) do |i|
|
|
443
|
+
return false unless @tail[i].__send__(operator, other[i])
|
|
444
|
+
end
|
|
445
|
+
|
|
446
|
+
lazy_load
|
|
447
|
+
end
|
|
448
|
+
|
|
449
|
+
@array.send(operator, other.to_ary)
|
|
450
|
+
end
|
|
451
|
+
end
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
module Ardm
|
|
2
|
+
module LocalObjectSpace
|
|
3
|
+
def self.extended(klass)
|
|
4
|
+
(class << klass; self; end).send :attr_accessor, :hook_scopes
|
|
5
|
+
klass.hook_scopes = []
|
|
6
|
+
super
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def object_by_id(object_id)
|
|
10
|
+
self.hook_scopes.detect { |object| object.object_id == object_id }
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
end
|
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
# ==== Public Ardm Logger API
|
|
2
|
+
#
|
|
3
|
+
# To replace an existing logger with a new one:
|
|
4
|
+
# Ardm::Logger.set_log(log{String, IO},level{Symbol, String})
|
|
5
|
+
#
|
|
6
|
+
# Available logging levels are
|
|
7
|
+
# Ardm::Logger::{ Fatal, Error, Warn, Info, Debug }
|
|
8
|
+
#
|
|
9
|
+
# Logging via:
|
|
10
|
+
# Ardm.logger.fatal(message<String>,&block)
|
|
11
|
+
# Ardm.logger.error(message<String>,&block)
|
|
12
|
+
# Ardm.logger.warn(message<String>,&block)
|
|
13
|
+
# Ardm.logger.info(message<String>,&block)
|
|
14
|
+
# Ardm.logger.debug(message<String>,&block)
|
|
15
|
+
#
|
|
16
|
+
# Logging with autoflush:
|
|
17
|
+
# Ardm.logger.fatal!(message<String>,&block)
|
|
18
|
+
# Ardm.logger.error!(message<String>,&block)
|
|
19
|
+
# Ardm.logger.warn!(message<String>,&block)
|
|
20
|
+
# Ardm.logger.info!(message<String>,&block)
|
|
21
|
+
# Ardm.logger.debug!(message<String>,&block)
|
|
22
|
+
#
|
|
23
|
+
# Flush the buffer to
|
|
24
|
+
# Ardm.logger.flush
|
|
25
|
+
#
|
|
26
|
+
# Remove the current log object
|
|
27
|
+
# Ardm.logger.close
|
|
28
|
+
#
|
|
29
|
+
# ==== Private Ardm Logger API
|
|
30
|
+
#
|
|
31
|
+
# To initialize the logger you create a new object, proxies to set_log.
|
|
32
|
+
# Ardm::Logger.new(log{String, IO},level{Symbol, String})
|
|
33
|
+
module Ardm
|
|
34
|
+
|
|
35
|
+
class << self
|
|
36
|
+
attr_accessor :logger
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
class Logger
|
|
40
|
+
|
|
41
|
+
attr_accessor :level
|
|
42
|
+
attr_accessor :delimiter
|
|
43
|
+
attr_accessor :auto_flush
|
|
44
|
+
attr_reader :buffer
|
|
45
|
+
attr_reader :log
|
|
46
|
+
attr_reader :init_args
|
|
47
|
+
|
|
48
|
+
# ==== Notes
|
|
49
|
+
# Ruby (standard) logger levels:
|
|
50
|
+
# :fatal:: An unhandleable error that results in a program crash
|
|
51
|
+
# :error:: A handleable error condition
|
|
52
|
+
# :warn:: A warning
|
|
53
|
+
# :info:: generic (useful) information about system operation
|
|
54
|
+
# :debug:: low-level information for developers
|
|
55
|
+
Levels =
|
|
56
|
+
{
|
|
57
|
+
:fatal => 7,
|
|
58
|
+
:error => 6,
|
|
59
|
+
:warn => 4,
|
|
60
|
+
:info => 3,
|
|
61
|
+
:debug => 0
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
private
|
|
65
|
+
|
|
66
|
+
# Readies a log for writing.
|
|
67
|
+
#
|
|
68
|
+
# ==== Parameters
|
|
69
|
+
# log<IO, String>:: Either an IO object or a name of a logfile.
|
|
70
|
+
def initialize_log(log)
|
|
71
|
+
close if @log # be sure that we don't leave open files laying around.
|
|
72
|
+
|
|
73
|
+
if log.respond_to?(:write)
|
|
74
|
+
@log = log
|
|
75
|
+
elsif File.exist?(log)
|
|
76
|
+
@log = open(log, (File::WRONLY | File::APPEND))
|
|
77
|
+
@log.sync = true
|
|
78
|
+
else
|
|
79
|
+
FileUtils.mkdir_p(File.dirname(log)) unless File.directory?(File.dirname(log))
|
|
80
|
+
@log = open(log, (File::WRONLY | File::APPEND | File::CREAT))
|
|
81
|
+
@log.sync = true
|
|
82
|
+
@log.write("#{Time.now.httpdate} #{delimiter} info #{delimiter} Logfile created\n")
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
public
|
|
87
|
+
|
|
88
|
+
# To initialize the logger you create a new object, proxies to set_log.
|
|
89
|
+
#
|
|
90
|
+
# ==== Parameters
|
|
91
|
+
# *args:: Arguments to create the log from. See set_logs for specifics.
|
|
92
|
+
def initialize(*args)
|
|
93
|
+
@init_args = args
|
|
94
|
+
set_log(*args)
|
|
95
|
+
self.auto_flush = true
|
|
96
|
+
Ardm.logger = self
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
# Replaces an existing logger with a new one.
|
|
100
|
+
#
|
|
101
|
+
# ==== Parameters
|
|
102
|
+
# log<IO, String>:: Either an IO object or a name of a logfile.
|
|
103
|
+
# log_level<~to_sym>::
|
|
104
|
+
# The log level from, e.g. :fatal or :info. Defaults to :error in the
|
|
105
|
+
# production environment and :debug otherwise.
|
|
106
|
+
# delimiter<String>::
|
|
107
|
+
# Delimiter to use between message sections. Defaults to " ~ ".
|
|
108
|
+
# auto_flush<Boolean>::
|
|
109
|
+
# Whether the log should automatically flush after new messages are
|
|
110
|
+
# added. Defaults to false.
|
|
111
|
+
def set_log(log, log_level = nil, delimiter = " ~ ", auto_flush = false)
|
|
112
|
+
if log_level && Levels[log_level.to_sym]
|
|
113
|
+
@level = Levels[log_level.to_sym]
|
|
114
|
+
else
|
|
115
|
+
@level = Levels[:debug]
|
|
116
|
+
end
|
|
117
|
+
@buffer = []
|
|
118
|
+
@delimiter = delimiter
|
|
119
|
+
@auto_flush = auto_flush
|
|
120
|
+
|
|
121
|
+
initialize_log(log)
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
# Flush the entire buffer to the log object.
|
|
125
|
+
def flush
|
|
126
|
+
return unless @buffer.size > 0
|
|
127
|
+
to_flush = @buffer
|
|
128
|
+
@buffer = []
|
|
129
|
+
@log.write(to_flush.join)
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
# Close and remove the current log object.
|
|
133
|
+
def close
|
|
134
|
+
flush
|
|
135
|
+
@log.close if @log.respond_to?(:close) && !@log.tty?
|
|
136
|
+
@log = nil
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
# Appends a message to the log. The methods yield to an optional block and
|
|
140
|
+
# the output of this block will be appended to the message.
|
|
141
|
+
#
|
|
142
|
+
# ==== Parameters
|
|
143
|
+
# string<String>:: The message to be logged. Defaults to nil.
|
|
144
|
+
#
|
|
145
|
+
# ==== Returns
|
|
146
|
+
# String:: The resulting message added to the log file.
|
|
147
|
+
def <<(string = nil)
|
|
148
|
+
message = ""
|
|
149
|
+
message << delimiter
|
|
150
|
+
message << string if string
|
|
151
|
+
message << "\n" unless message[-1] == ?\n
|
|
152
|
+
@buffer << message
|
|
153
|
+
flush if @auto_flush
|
|
154
|
+
|
|
155
|
+
message
|
|
156
|
+
end
|
|
157
|
+
alias_method :push, :<<
|
|
158
|
+
|
|
159
|
+
# Generate the logging methods for Ardm.logger for each log level.
|
|
160
|
+
Levels.each_pair do |name, number|
|
|
161
|
+
class_eval <<-LEVELMETHODS, __FILE__, __LINE__
|
|
162
|
+
|
|
163
|
+
# Appends a message to the log if the log level is at least as high as
|
|
164
|
+
# the log level of the logger.
|
|
165
|
+
#
|
|
166
|
+
# ==== Parameters
|
|
167
|
+
# string<String>:: The message to be logged. Defaults to nil.
|
|
168
|
+
#
|
|
169
|
+
# ==== Returns
|
|
170
|
+
# self:: The logger object for chaining.
|
|
171
|
+
def #{name}(message = nil)
|
|
172
|
+
self << message if #{number} >= level
|
|
173
|
+
self
|
|
174
|
+
end
|
|
175
|
+
|
|
176
|
+
# Appends a message to the log if the log level is at least as high as
|
|
177
|
+
# the log level of the logger. The bang! version of the method also auto
|
|
178
|
+
# flushes the log buffer to disk.
|
|
179
|
+
#
|
|
180
|
+
# ==== Parameters
|
|
181
|
+
# string<String>:: The message to be logged. Defaults to nil.
|
|
182
|
+
#
|
|
183
|
+
# ==== Returns
|
|
184
|
+
# self:: The logger object for chaining.
|
|
185
|
+
def #{name}!(message = nil)
|
|
186
|
+
self << message if #{number} >= level
|
|
187
|
+
flush if #{number} >= level
|
|
188
|
+
self
|
|
189
|
+
end
|
|
190
|
+
|
|
191
|
+
# ==== Returns
|
|
192
|
+
# Boolean:: True if this level will be logged by this logger.
|
|
193
|
+
def #{name}?
|
|
194
|
+
#{number} >= level
|
|
195
|
+
end
|
|
196
|
+
LEVELMETHODS
|
|
197
|
+
end
|
|
198
|
+
|
|
199
|
+
end
|
|
200
|
+
|
|
201
|
+
end
|