strokedb 0.0.2.1 → 0.0.2.2
Sign up to get free protection for your applications and to get access to all the features.
- data/README +18 -20
- data/bench.html +4001 -0
- data/bin/strokedb +14 -0
- data/examples/movies.rb +105 -0
- data/examples/movies2.rb +97 -0
- data/examples/strokewiki/README +28 -0
- data/examples/strokewiki/view/edit.xhtml +27 -0
- data/examples/strokewiki/view/new.xhtml +26 -0
- data/examples/strokewiki/view/pages.xhtml +27 -0
- data/examples/strokewiki/view/show.xhtml +40 -0
- data/examples/strokewiki/view/versions.xhtml +25 -0
- data/examples/strokewiki/wiki.rb +106 -0
- data/examples/todo.rb +92 -0
- data/lib/strokedb.rb +85 -0
- data/lib/{config → strokedb}/config.rb +14 -9
- data/lib/strokedb/console.rb +87 -0
- data/lib/strokedb/core_ext.rb +10 -0
- data/lib/{util/ext → strokedb/core_ext}/blank.rb +1 -1
- data/lib/{util/ext → strokedb/core_ext}/enumerable.rb +0 -0
- data/lib/{util/ext → strokedb/core_ext}/fixnum.rb +0 -0
- data/lib/strokedb/core_ext/float.rb +4 -0
- data/lib/{util/ext → strokedb/core_ext}/hash.rb +0 -0
- data/lib/strokedb/core_ext/infinity.rb +33 -0
- data/lib/strokedb/core_ext/kernel.rb +41 -0
- data/lib/strokedb/core_ext/object.rb +16 -0
- data/lib/{util/ext → strokedb/core_ext}/string.rb +28 -1
- data/lib/strokedb/core_ext/symbol.rb +13 -0
- data/lib/strokedb/data_structures.rb +5 -0
- data/lib/strokedb/data_structures/chunked_skiplist.rb +123 -0
- data/lib/{data_structures → strokedb/data_structures}/inverted_list.rb +0 -0
- data/lib/{data_structures → strokedb/data_structures}/point_query.rb +0 -0
- data/lib/strokedb/data_structures/simple_skiplist.rb +350 -0
- data/lib/{data_structures → strokedb/data_structures}/skiplist.rb +1 -1
- data/lib/{document → strokedb}/document.rb +180 -71
- data/lib/{document → strokedb/document}/callback.rb +0 -0
- data/lib/{document → strokedb/document}/delete.rb +2 -2
- data/lib/strokedb/document/dsl.rb +4 -0
- data/lib/{document → strokedb/document/dsl}/associations.rb +0 -0
- data/lib/{document → strokedb/document/dsl}/coercions.rb +0 -0
- data/lib/strokedb/document/dsl/meta_dsl.rb +7 -0
- data/lib/{document → strokedb/document/dsl}/validations.rb +26 -21
- data/lib/{document → strokedb/document/dsl}/virtualize.rb +0 -0
- data/lib/{document → strokedb/document}/meta.rb +92 -29
- data/lib/{document → strokedb/document}/slot.rb +17 -5
- data/lib/{document → strokedb/document}/util.rb +0 -0
- data/lib/{document → strokedb/document}/versions.rb +2 -2
- data/lib/strokedb/index.rb +2 -0
- data/lib/strokedb/nsurl.rb +24 -0
- data/lib/strokedb/store.rb +149 -0
- data/lib/strokedb/stores.rb +6 -0
- data/lib/{stores → strokedb/stores}/chainable_storage.rb +20 -14
- data/lib/strokedb/stores/file_storage.rb +118 -0
- data/lib/{stores/inverted_list_index → strokedb/stores}/inverted_list_file_storage.rb +50 -0
- data/lib/strokedb/stores/memory_storage.rb +80 -0
- data/lib/{stores → strokedb/stores}/remote_store.rb +10 -4
- data/lib/strokedb/sync.rb +4 -0
- data/lib/{sync → strokedb/sync}/chain_sync.rb +0 -0
- data/lib/{sync → strokedb/sync}/diff.rb +12 -1
- data/lib/{sync/stroke_diff → strokedb/sync/diff}/array.rb +1 -1
- data/lib/{sync/stroke_diff → strokedb/sync/diff}/default.rb +0 -0
- data/lib/{sync/stroke_diff → strokedb/sync/diff}/hash.rb +1 -1
- data/lib/{sync/stroke_diff → strokedb/sync/diff}/string.rb +1 -1
- data/lib/{sync → strokedb/sync}/lamport_timestamp.rb +0 -0
- data/lib/{sync → strokedb/sync}/store_sync.rb +15 -7
- data/lib/strokedb/transaction.rb +78 -0
- data/lib/{util → strokedb}/util.rb +14 -7
- data/lib/strokedb/util/attach_dsl.rb +29 -0
- data/lib/{util → strokedb/util}/blankslate.rb +0 -0
- data/lib/strokedb/util/class_optimization.rb +93 -0
- data/lib/{util → strokedb/util}/inflect.rb +0 -0
- data/lib/strokedb/util/java_util.rb +13 -0
- data/lib/{util → strokedb/util}/lazy_array.rb +0 -0
- data/lib/{util → strokedb/util}/lazy_mapping_array.rb +4 -0
- data/lib/{util → strokedb/util}/lazy_mapping_hash.rb +0 -0
- data/lib/{util → strokedb/util}/serialization.rb +21 -0
- data/lib/strokedb/util/uuid.rb +159 -0
- data/lib/{util → strokedb/util}/xml.rb +0 -0
- data/lib/{view → strokedb}/view.rb +2 -2
- data/lib/strokedb/volumes.rb +5 -0
- data/lib/strokedb/volumes/archive_volume.rb +165 -0
- data/lib/strokedb/volumes/block_volume.rb +169 -0
- data/lib/strokedb/volumes/distributed_pointer.rb +43 -0
- data/lib/strokedb/volumes/fixed_length_skiplist_volume.rb +109 -0
- data/lib/strokedb/volumes/map_volume.rb +268 -0
- data/meta/MANIFEST +175 -0
- data/script/console +2 -70
- data/spec/integration/remote_store_spec.rb +70 -0
- data/spec/integration/search_spec.rb +76 -0
- data/spec/integration/spec_helper.rb +1 -0
- data/spec/lib/spec_helper.rb +1 -0
- data/spec/lib/strokedb/config_spec.rb +250 -0
- data/spec/lib/strokedb/core_ext/blank_spec.rb +20 -0
- data/spec/lib/strokedb/core_ext/extract_spec.rb +42 -0
- data/spec/lib/strokedb/core_ext/float_spec.rb +62 -0
- data/spec/lib/strokedb/core_ext/infinity_spec.rb +40 -0
- data/spec/lib/strokedb/core_ext/spec_helper.rb +1 -0
- data/spec/lib/strokedb/core_ext/string_spec.rb +25 -0
- data/spec/lib/strokedb/core_ext/symbol_spec.rb +8 -0
- data/spec/lib/strokedb/data_structures/chunked_skiplist_spec.rb +144 -0
- data/spec/lib/strokedb/data_structures/inverted_list_spec.rb +172 -0
- data/spec/lib/strokedb/data_structures/simple_skiplist_spec.rb +200 -0
- data/spec/lib/strokedb/data_structures/skiplist_spec.rb +253 -0
- data/spec/lib/strokedb/data_structures/spec_helper.rb +1 -0
- data/spec/lib/strokedb/document/associations_spec.rb +319 -0
- data/spec/lib/strokedb/document/callbacks_spec.rb +134 -0
- data/spec/lib/strokedb/document/coercions_spec.rb +110 -0
- data/spec/lib/strokedb/document/document_spec.rb +1063 -0
- data/spec/lib/strokedb/document/meta_meta_spec.rb +30 -0
- data/spec/lib/strokedb/document/meta_spec.rb +435 -0
- data/spec/lib/strokedb/document/metaslot_spec.rb +43 -0
- data/spec/lib/strokedb/document/slot_spec.rb +130 -0
- data/spec/lib/strokedb/document/spec_helper.rb +1 -0
- data/spec/lib/strokedb/document/validations_spec.rb +1081 -0
- data/spec/lib/strokedb/document/virtualize_spec.rb +80 -0
- data/spec/lib/strokedb/nsurl_spec.rb +73 -0
- data/spec/lib/strokedb/spec_helper.rb +1 -0
- data/spec/lib/strokedb/stores/chained_storages_spec.rb +116 -0
- data/spec/lib/strokedb/stores/spec_helper.rb +1 -0
- data/spec/lib/strokedb/stores/store_spec.rb +201 -0
- data/spec/lib/strokedb/stores/transaction_spec.rb +107 -0
- data/spec/lib/strokedb/sync/chain_sync_spec.rb +43 -0
- data/spec/lib/strokedb/sync/diff_spec.rb +111 -0
- data/spec/lib/strokedb/sync/lamport_timestamp_spec.rb +174 -0
- data/spec/lib/strokedb/sync/slot_diff_spec.rb +164 -0
- data/spec/lib/strokedb/sync/spec_helper.rb +1 -0
- data/spec/lib/strokedb/sync/store_sync_spec.rb +181 -0
- data/spec/lib/strokedb/sync/stroke_diff/array_spec.rb +97 -0
- data/spec/lib/strokedb/sync/stroke_diff/complex_spec.rb +58 -0
- data/spec/lib/strokedb/sync/stroke_diff/hash_spec.rb +144 -0
- data/spec/lib/strokedb/sync/stroke_diff/scalar_spec.rb +23 -0
- data/spec/lib/strokedb/sync/stroke_diff/spec_helper.rb +25 -0
- data/spec/lib/strokedb/sync/stroke_diff/string_spec.rb +61 -0
- data/spec/lib/strokedb/util/attach_dsl_spec.rb +45 -0
- data/spec/lib/strokedb/util/inflect_spec.rb +14 -0
- data/spec/lib/strokedb/util/lazy_array_spec.rb +157 -0
- data/spec/lib/strokedb/util/lazy_mapping_array_spec.rb +174 -0
- data/spec/lib/strokedb/util/lazy_mapping_hash_spec.rb +92 -0
- data/spec/lib/strokedb/util/spec_helper.rb +1 -0
- data/spec/lib/strokedb/util/uuid_spec.rb +46 -0
- data/spec/lib/strokedb/view_spec.rb +228 -0
- data/spec/lib/strokedb/volumes/archive_volume_spec.rb +105 -0
- data/spec/lib/strokedb/volumes/block_volume_spec.rb +100 -0
- data/spec/lib/strokedb/volumes/distributed_pointer_spec.rb +14 -0
- data/spec/lib/strokedb/volumes/fixed_length_skiplist_volume_spec.rb +177 -0
- data/spec/lib/strokedb/volumes/map_volume_spec.rb +172 -0
- data/spec/lib/strokedb/volumes/spec_helper.rb +1 -0
- data/spec/regression/docref_spec.rb +94 -0
- data/spec/regression/meta_spec.rb +23 -0
- data/spec/regression/spec_helper.rb +1 -0
- data/spec/regression/sync_spec.rb +36 -0
- data/spec/spec.opts +7 -0
- data/spec/spec_helper.rb +37 -0
- data/spec/temp/storages/TIMESTAMP +1 -0
- data/spec/temp/storages/UUID +1 -0
- data/spec/temp/storages/database-sync/TIMESTAMP +1 -0
- data/spec/temp/storages/database-sync/UUID +1 -0
- data/spec/temp/storages/database-sync/config +1 -0
- data/spec/temp/storages/database-sync/file/LAST +1 -0
- data/spec/temp/storages/database-sync/file/bd/f6/bdf675e5-8a7b-494e-97f2-f74a14ccd95d.av +0 -0
- data/spec/temp/storages/database-sync/file/uindex.wal +0 -0
- data/spec/temp/storages/database-sync/inverted_list_file/INVERTED_INDEX +1 -0
- data/spec/temp/storages/inverted_list_storage/INVERTED_INDEX +0 -0
- data/strokedb.gemspec +120 -0
- data/task/benchmark.task +9 -0
- data/task/ditz.task +30 -0
- data/task/echoe.rb +17 -0
- data/task/rcov.task +50 -0
- data/task/rdoc.task +10 -0
- data/task/rspec.task +0 -0
- data/vendor/java_inline.rb +106 -0
- data/vendor/rbmodexcl/mrimodexcl.rb +82 -0
- data/vendor/rbmodexcl/rbmodexcl.rb +5 -0
- data/vendor/rbmodexcl/rbxmodexcl.rb +48 -0
- data/vendor/rbmodexcl/spec/unextend_spec.rb +50 -0
- data/vendor/rbmodexcl/spec/uninclude_spec.rb +26 -0
- metadata +271 -79
- data/CONTRIBUTORS +0 -7
- data/CREDITS +0 -13
- data/bin/sdbc +0 -2
- data/lib/init.rb +0 -57
- data/lib/stores/inverted_list_index/inverted_list_index.rb +0 -49
- data/lib/stores/skiplist_store/chunk.rb +0 -119
- data/lib/stores/skiplist_store/chunk_storage.rb +0 -21
- data/lib/stores/skiplist_store/file_chunk_storage.rb +0 -44
- data/lib/stores/skiplist_store/memory_chunk_storage.rb +0 -37
- data/lib/stores/skiplist_store/skiplist_store.rb +0 -217
- data/lib/stores/store.rb +0 -5
- data/lib/sync/stroke_diff/stroke_diff.rb +0 -9
- data/lib/util/ext/object.rb +0 -8
- data/lib/util/java_util.rb +0 -9
- data/lib/util/trigger_partition.rb +0 -136
- data/strokedb.rb +0 -75
@@ -1,3 +1,11 @@
|
|
1
|
+
require 'document/dsl'
|
2
|
+
require 'document/util'
|
3
|
+
require 'document/meta'
|
4
|
+
require 'document/callback'
|
5
|
+
require 'document/delete'
|
6
|
+
require 'document/slot'
|
7
|
+
require 'document/versions'
|
8
|
+
|
1
9
|
module StrokeDB
|
2
10
|
# Slots which contain references to another documents are matched
|
3
11
|
# with these regexps.
|
@@ -17,23 +25,23 @@ module StrokeDB
|
|
17
25
|
def initialize(slotname)
|
18
26
|
@slotname = slotname
|
19
27
|
end
|
20
|
-
|
28
|
+
|
21
29
|
def message
|
22
30
|
"Can't find slot #{@slotname}"
|
23
31
|
end
|
24
|
-
|
32
|
+
|
25
33
|
def inspect
|
26
34
|
"#<#{self.class.name}: #{message}>"
|
27
35
|
end
|
28
36
|
end
|
29
|
-
|
37
|
+
|
30
38
|
#
|
31
|
-
# Raised when Document#save! is called on an invalid document
|
39
|
+
# Raised when Document#save! is called on an invalid document
|
32
40
|
# (for which doc.valid? returns false)
|
33
41
|
#
|
34
42
|
class InvalidDocumentError < StandardError #:nodoc:
|
35
43
|
attr_reader :document
|
36
|
-
|
44
|
+
|
37
45
|
def initialize(document)
|
38
46
|
@document = document
|
39
47
|
end
|
@@ -41,7 +49,7 @@ module StrokeDB
|
|
41
49
|
def message
|
42
50
|
"Validation failed: #{@document.errors.messages.join(", ")}"
|
43
51
|
end
|
44
|
-
|
52
|
+
|
45
53
|
def inspect
|
46
54
|
"#<#{self.class.name}: #{message}>"
|
47
55
|
end
|
@@ -62,9 +70,17 @@ module StrokeDB
|
|
62
70
|
# authors: ["Yurii Rashkovskii","Oleg Andreev"]
|
63
71
|
#
|
64
72
|
class Document
|
65
|
-
include Validations::InstanceMethods
|
73
|
+
include StrokeDB::Validations::InstanceMethods
|
66
74
|
|
67
|
-
attr_reader :
|
75
|
+
attr_reader :callbacks #:nodoc:
|
76
|
+
|
77
|
+
def store
|
78
|
+
if (txns = Thread.current[:strokedb_transactions]) && !txns.nil? && !txns.empty?
|
79
|
+
txns.last
|
80
|
+
else
|
81
|
+
@store
|
82
|
+
end
|
83
|
+
end
|
68
84
|
|
69
85
|
def marshal_dump #:nodoc:
|
70
86
|
(@new ? '1' : '0') + (@saved ? '1' : '0') + to_raw.to_json
|
@@ -82,13 +98,34 @@ module StrokeDB
|
|
82
98
|
def initialize(document)
|
83
99
|
@document = document
|
84
100
|
_meta = document[:meta]
|
85
|
-
concat
|
101
|
+
concat _meta.to_a
|
86
102
|
end
|
87
103
|
|
88
104
|
def <<(meta)
|
89
105
|
add_meta(meta, :call_initialization_callbacks => true)
|
90
106
|
end
|
91
107
|
|
108
|
+
alias :_delete :delete
|
109
|
+
def delete(meta)
|
110
|
+
case meta
|
111
|
+
when Document
|
112
|
+
_delete meta
|
113
|
+
_module = StrokeDB::Document.collect_meta_modules(@document.store, meta).first
|
114
|
+
when Meta
|
115
|
+
_delete meta.document(@document.store)
|
116
|
+
_module = meta
|
117
|
+
else
|
118
|
+
raise ArgumentError, "Meta should be either document or meta module"
|
119
|
+
end
|
120
|
+
|
121
|
+
@document[:meta] = self
|
122
|
+
|
123
|
+
if _module
|
124
|
+
@document.unextend(_module)
|
125
|
+
end
|
126
|
+
|
127
|
+
end
|
128
|
+
|
92
129
|
def add_meta(meta, opts = {})
|
93
130
|
opts = opts.stringify_keys
|
94
131
|
_module = nil
|
@@ -110,10 +147,8 @@ module StrokeDB
|
|
110
147
|
|
111
148
|
if _module
|
112
149
|
@document.extend(_module)
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
if opts['call_initialization_callbacks']
|
150
|
+
|
151
|
+
if opts['call_initialization_callbacks']
|
117
152
|
@document.send!(:execute_callbacks_for, _module, :on_initialization)
|
118
153
|
@document.send!(:execute_callbacks_for, _module, :on_new_document) if @document.new?
|
119
154
|
end
|
@@ -168,6 +203,7 @@ module StrokeDB
|
|
168
203
|
# If slot was not found, it will return <tt>nil</tt>
|
169
204
|
#
|
170
205
|
def [](slotname)
|
206
|
+
slotname = slotname.document.uuid if (slotname.is_a?(Meta) && slotname.is_a?(Module)) || (slotname == Meta)
|
171
207
|
@slots[slotname.to_s].value rescue nil
|
172
208
|
end
|
173
209
|
|
@@ -177,11 +213,12 @@ module StrokeDB
|
|
177
213
|
# document[:slot_1] = "some value"
|
178
214
|
#
|
179
215
|
def []=(slotname, value)
|
216
|
+
slotname = slotname.document.uuid if (slotname.is_a?(Meta) && slotname.is_a?(Module)) || (slotname == Meta)
|
180
217
|
slotname = slotname.to_s
|
181
218
|
|
182
219
|
(@slots[slotname] ||= Slot.new(self, slotname)).value = value
|
183
220
|
update_version!(slotname)
|
184
|
-
|
221
|
+
|
185
222
|
value
|
186
223
|
end
|
187
224
|
|
@@ -206,7 +243,7 @@ module StrokeDB
|
|
206
243
|
#
|
207
244
|
def remove_slot!(slotname)
|
208
245
|
slotname = slotname.to_s
|
209
|
-
|
246
|
+
|
210
247
|
@slots.delete slotname
|
211
248
|
update_version! slotname
|
212
249
|
|
@@ -233,9 +270,9 @@ module StrokeDB
|
|
233
270
|
|
234
271
|
def pretty_print #:nodoc:
|
235
272
|
slots = to_raw.except('meta')
|
236
|
-
|
237
|
-
s = is_a?(ImmutableDocument) ? "
|
238
|
-
|
273
|
+
|
274
|
+
s = is_a?(ImmutableDocument) ? "#<^" : "#<"
|
275
|
+
|
239
276
|
Util.catch_circular_reference(self) do
|
240
277
|
if self[:meta] && name = meta[:name]
|
241
278
|
s << "#{name} "
|
@@ -245,9 +282,13 @@ module StrokeDB
|
|
245
282
|
|
246
283
|
slots.keys.sort.each do |k|
|
247
284
|
if %w(version previous_version).member?(k) && v = self[k]
|
248
|
-
s << "#{k}: #{v
|
285
|
+
s << "#{k}: #{v[0,4]}..., "
|
249
286
|
else
|
250
|
-
|
287
|
+
if k.match(/^#{UUID_RE}$/)
|
288
|
+
s << "[#{store.find(k).name}]: #{self[k].inspect}, " rescue s << "#{k}: #{self[k].inspect}, "
|
289
|
+
else
|
290
|
+
s << "#{k}: #{self[k].inspect}, "
|
291
|
+
end
|
251
292
|
end
|
252
293
|
end
|
253
294
|
|
@@ -255,7 +296,7 @@ module StrokeDB
|
|
255
296
|
s.chomp!(' ')
|
256
297
|
s << ">"
|
257
298
|
end
|
258
|
-
|
299
|
+
|
259
300
|
s
|
260
301
|
rescue Util::CircularReferenceCondition
|
261
302
|
"#(#{(self[:meta] ? "#{meta}" : "Doc")} #{('@#'+uuid)[0,5]}...)"
|
@@ -287,8 +328,8 @@ module StrokeDB
|
|
287
328
|
@slots.each_pair do |k,v|
|
288
329
|
raw_slots[k.to_s] = v.to_raw
|
289
330
|
end
|
290
|
-
|
291
|
-
raw_slots
|
331
|
+
|
332
|
+
raw_slots.to_raw
|
292
333
|
end
|
293
334
|
|
294
335
|
def to_optimized_raw #:nodoc:
|
@@ -298,14 +339,12 @@ module StrokeDB
|
|
298
339
|
#
|
299
340
|
# Creates a document from a serialized representation
|
300
341
|
#
|
301
|
-
def self.from_raw(store, raw_slots, opts = {}) #:nodoc:
|
302
|
-
doc = new(store, raw_slots, true)
|
342
|
+
def self.from_raw(store, raw_slots, opts = {}, &block) #:nodoc:
|
343
|
+
doc = new(store, raw_slots, true, &block)
|
303
344
|
|
304
345
|
collect_meta_modules(store, raw_slots['meta']).each do |meta_module|
|
305
346
|
unless doc.is_a? meta_module
|
306
347
|
doc.extend(meta_module)
|
307
|
-
|
308
|
-
meta_module.send!(:setup_callbacks, doc) rescue nil
|
309
348
|
end
|
310
349
|
end
|
311
350
|
|
@@ -330,10 +369,14 @@ module StrokeDB
|
|
330
369
|
# If first argument is Store, that particular store will be used; otherwise default store will be assumed.
|
331
370
|
def self.find(*args)
|
332
371
|
store = nil
|
333
|
-
if
|
334
|
-
store =
|
372
|
+
if (txns = Thread.current[:strokedb_transactions]) && !txns.nil? && !txns.empty?
|
373
|
+
store = txns.last
|
335
374
|
else
|
336
|
-
|
375
|
+
if args.empty? || args.first.is_a?(String) || args.first.is_a?(Hash) || args.first.nil?
|
376
|
+
store = StrokeDB.default_store
|
377
|
+
else
|
378
|
+
store = args.shift
|
379
|
+
end
|
337
380
|
end
|
338
381
|
raise NoDefaultStoreError.new unless store
|
339
382
|
query = args.first
|
@@ -343,7 +386,7 @@ module StrokeDB
|
|
343
386
|
when Hash
|
344
387
|
store.search(query)
|
345
388
|
else
|
346
|
-
raise
|
389
|
+
raise ArgumentError, "use UUID or query to find document(s)"
|
347
390
|
end
|
348
391
|
end
|
349
392
|
|
@@ -386,30 +429,42 @@ module StrokeDB
|
|
386
429
|
store.save!(self)
|
387
430
|
@new = false
|
388
431
|
@saved = true
|
389
|
-
|
432
|
+
|
390
433
|
execute_callbacks :after_save
|
391
|
-
|
434
|
+
|
392
435
|
self
|
393
436
|
end
|
394
437
|
|
395
|
-
#
|
396
|
-
# Updates slots with specified <tt>hash</tt> and returns itself.
|
397
|
-
#
|
438
|
+
# Updates slots with a specified <tt>hash</tt> and returns itself.
|
398
439
|
def update_slots(hash)
|
399
440
|
hash.each do |k, v|
|
400
|
-
self[k]
|
441
|
+
send("#{k}=", v) unless self[k] == v
|
401
442
|
end
|
402
|
-
|
403
443
|
self
|
404
444
|
end
|
405
445
|
|
406
|
-
#
|
407
446
|
# Same as update_slots, but also saves the document.
|
408
|
-
#
|
409
447
|
def update_slots!(hash)
|
410
448
|
update_slots(hash).save!
|
411
449
|
end
|
412
450
|
|
451
|
+
|
452
|
+
# Updates nil/false slots with a specified <tt>hash</tt> and returns itself.
|
453
|
+
# Already set slots are not modified (<tt>||=</tt> is used).
|
454
|
+
# Acts like <tt>hash1.reverse_merge(hash2)</tt> (<tt>hash2.merge(hash1)</tt>).
|
455
|
+
#
|
456
|
+
def reverse_update_slots(hash)
|
457
|
+
hash.each do |k, v|
|
458
|
+
self[k] ||= v
|
459
|
+
end
|
460
|
+
self
|
461
|
+
end
|
462
|
+
|
463
|
+
# Same as reverse_update_slots, but also saves the document.
|
464
|
+
def reverse_update_slots!(hash)
|
465
|
+
reverse_update_slots(hash).save!
|
466
|
+
end
|
467
|
+
|
413
468
|
#
|
414
469
|
# Returns document's metadocument (if any). In case if document has more than one metadocument,
|
415
470
|
# it will combine all metadocuments into one 'virtual' metadocument
|
@@ -419,14 +474,14 @@ module StrokeDB
|
|
419
474
|
# simple case
|
420
475
|
return m || Document.new(@store)
|
421
476
|
end
|
422
|
-
|
477
|
+
|
423
478
|
return m.first if m.size == 1
|
424
479
|
|
425
480
|
mm = m.clone
|
426
481
|
collected_meta = mm.shift.clone
|
427
482
|
|
428
483
|
names = collected_meta[:name].split(',') rescue []
|
429
|
-
|
484
|
+
|
430
485
|
mm.each do |next_meta|
|
431
486
|
next_meta = next_meta.clone
|
432
487
|
collected_meta += next_meta
|
@@ -455,7 +510,7 @@ module StrokeDB
|
|
455
510
|
# Please not that it accept both meta modules and their documents, there is no difference
|
456
511
|
#
|
457
512
|
def metas
|
458
|
-
Metas.new(self)
|
513
|
+
@metas ||= Metas.new(self)
|
459
514
|
end
|
460
515
|
|
461
516
|
#
|
@@ -472,6 +527,10 @@ module StrokeDB
|
|
472
527
|
@uuid ||= self[:uuid]
|
473
528
|
end
|
474
529
|
|
530
|
+
def raw_uuid #:nodoc:
|
531
|
+
@raw_uuid ||= uuid.to_raw_uuid
|
532
|
+
end
|
533
|
+
|
475
534
|
#
|
476
535
|
# Returns document's previous version (which is stored in <tt>previous_version</tt> slot)
|
477
536
|
#
|
@@ -498,7 +557,7 @@ module StrokeDB
|
|
498
557
|
case doc
|
499
558
|
when Document, DocumentReferenceValue
|
500
559
|
doc = doc.load if doc.kind_of? DocumentReferenceValue
|
501
|
-
|
560
|
+
|
502
561
|
# we make a quick UUID check here to skip two heavy to_raw calls
|
503
562
|
doc.uuid == uuid && doc.to_raw == to_raw
|
504
563
|
else
|
@@ -526,16 +585,16 @@ module StrokeDB
|
|
526
585
|
|
527
586
|
def method_missing(sym, *args) #:nodoc:
|
528
587
|
sym = sym.to_s
|
529
|
-
|
588
|
+
|
530
589
|
return send(:[]=, sym.chomp('='), *args) if sym.ends_with? '='
|
531
590
|
return self[sym] if slotnames.include? sym
|
532
591
|
return !!send(sym.chomp('?'), *args) if sym.ends_with? '?'
|
533
|
-
|
592
|
+
|
534
593
|
raise SlotNotFoundError.new(sym) if (callbacks['when_slot_not_found'] || []).empty?
|
535
594
|
|
536
595
|
r = execute_callbacks(:when_slot_not_found, sym)
|
537
596
|
raise r if r.is_a? SlotNotFoundError # TODO: spec this behavior
|
538
|
-
|
597
|
+
|
539
598
|
r
|
540
599
|
end
|
541
600
|
|
@@ -568,21 +627,21 @@ module StrokeDB
|
|
568
627
|
end
|
569
628
|
end
|
570
629
|
|
571
|
-
# initialize the document. initialize_raw is true when
|
630
|
+
# initialize the document. initialize_raw is true when
|
572
631
|
# document is initialized from a raw serialized form
|
573
632
|
def do_initialize(store, slots={}, initialize_raw = false) #:nodoc:
|
574
633
|
@callbacks = {}
|
575
634
|
@store = store
|
576
635
|
|
577
636
|
if initialize_raw
|
578
|
-
initialize_raw_slots slots
|
637
|
+
initialize_raw_slots slots
|
579
638
|
@saved = true
|
580
639
|
else
|
581
640
|
@new = true
|
582
641
|
initialize_slots slots
|
583
642
|
|
584
643
|
self[:uuid] = Util.random_uuid unless self[:uuid]
|
585
|
-
|
644
|
+
self[:version] ||= NIL_UUID
|
586
645
|
end
|
587
646
|
end
|
588
647
|
|
@@ -591,24 +650,23 @@ module StrokeDB
|
|
591
650
|
@slots = {}
|
592
651
|
slots = slots.stringify_keys
|
593
652
|
|
594
|
-
# there is a reason for meta slot is initialized separately —
|
653
|
+
# there is a reason for meta slot is initialized separately —
|
595
654
|
# we need to setup coercions before initializing actual slots
|
596
655
|
if meta = slots['meta']
|
597
656
|
meta = [meta] unless meta.is_a?(Array)
|
598
657
|
meta.each {|m| metas.add_meta(m) }
|
599
658
|
end
|
600
|
-
|
601
|
-
slots.except('meta').each {|name,value|
|
659
|
+
|
660
|
+
slots.except('meta').each {|name,value| send("#{name}=", value) }
|
602
661
|
|
603
662
|
# now, when we have all slots initialized, we can run initialization callbacks
|
604
663
|
execute_callbacks :on_initialization
|
605
664
|
execute_callbacks :on_new_document
|
606
665
|
end
|
607
|
-
|
666
|
+
|
608
667
|
# initialize slots from a raw representation
|
609
668
|
def initialize_raw_slots(slots) #:nodoc:
|
610
669
|
@slots = {}
|
611
|
-
|
612
670
|
slots.each do |name,value|
|
613
671
|
s = Slot.new(self, name)
|
614
672
|
s.raw_value = value
|
@@ -617,26 +675,73 @@ module StrokeDB
|
|
617
675
|
end
|
618
676
|
end
|
619
677
|
|
620
|
-
# returns an array of meta modules (as constants) for a given something
|
621
|
-
# (a document reference, a document itself, or an array of the former)
|
622
|
-
def self.collect_meta_modules(store, meta) #:nodoc:
|
623
|
-
meta_names = []
|
624
678
|
|
625
|
-
|
626
|
-
|
627
|
-
|
628
|
-
|
679
|
+
class MetaModulesCollector
|
680
|
+
def initialize(store, subject)
|
681
|
+
@store = store
|
682
|
+
@subject = subject
|
683
|
+
end
|
684
|
+
|
685
|
+
def resolve_module_name(uuid)
|
686
|
+
if metadoc = @store.find(uuid, self.lookup_version_for_meta(@subject))
|
687
|
+
mod = Module.find_by_nsurl(metadoc[:nsurl])
|
688
|
+
|
689
|
+
if self.has_defined_constant_for_meta?(mod, metadoc)
|
690
|
+
at_top_level?(mod) ? "::#{metadoc[:name]}" : "#{mod.name}::#{metadoc[:name]}"
|
691
|
+
else
|
692
|
+
Meta.resolve_uuid_name(metadoc[:nsurl], metadoc[:name])
|
693
|
+
end
|
629
694
|
end
|
630
|
-
|
631
|
-
|
632
|
-
|
695
|
+
end
|
696
|
+
|
697
|
+
def at_top_level?(mod)
|
698
|
+
mod == Module || mod.nil?
|
699
|
+
end
|
700
|
+
|
701
|
+
def collect!
|
702
|
+
meta_names = []
|
703
|
+
|
704
|
+
case @subject
|
705
|
+
when VERSIONREF, DOCREF
|
706
|
+
meta_names << resolve_module_name($1)
|
707
|
+
when Array
|
708
|
+
meta_names = @subject.map { |subj| subj = MetaModulesCollector.new(@store, subj).collect! }.flatten
|
709
|
+
when Document
|
710
|
+
meta_names << @subject[:name]
|
633
711
|
end
|
634
|
-
|
635
|
-
meta_names
|
636
|
-
|
637
|
-
|
712
|
+
|
713
|
+
meta_names
|
714
|
+
end
|
715
|
+
|
716
|
+
def lookup_version_for_meta(meta)
|
717
|
+
version = case meta
|
718
|
+
when VERSIONREF then $2
|
719
|
+
else nil
|
720
|
+
end
|
721
|
+
version
|
722
|
+
end
|
723
|
+
|
724
|
+
def has_defined_constant_for_meta?(mod, metadoc)
|
725
|
+
top_level_meta?(mod, metadoc) || has_meta_definition?(mod, metadoc)
|
638
726
|
end
|
639
727
|
|
728
|
+
def top_level_meta?(mod, doc)
|
729
|
+
(mod == Module && Object.constants.include?(doc[:name]))
|
730
|
+
end
|
731
|
+
|
732
|
+
def has_meta_definition?(mod, metadoc)
|
733
|
+
(mod && mod.constants.include?(metadoc[:name]))
|
734
|
+
end
|
735
|
+
end
|
736
|
+
|
737
|
+
|
738
|
+
|
739
|
+
# returns an array of meta modules (as constants) for a given something
|
740
|
+
# (a document reference, a document itself, or an array of the former)
|
741
|
+
def self.collect_meta_modules(store, meta) #:nodoc:
|
742
|
+
@collector = MetaModulesCollector.new(store, meta)
|
743
|
+
meta_names = @collector.collect!
|
744
|
+
|
640
745
|
meta_names.map { |m| m.is_a?(String) ? (m.constantize rescue nil) : m }.compact
|
641
746
|
end
|
642
747
|
|
@@ -649,7 +754,7 @@ module StrokeDB
|
|
649
754
|
self[:previous_version] = version unless version.nil?
|
650
755
|
|
651
756
|
generate_new_version!
|
652
|
-
|
757
|
+
|
653
758
|
@saved = nil
|
654
759
|
end
|
655
760
|
end
|
@@ -680,5 +785,9 @@ module StrokeDB
|
|
680
785
|
def save!
|
681
786
|
self
|
682
787
|
end
|
788
|
+
|
789
|
+
def make_mutable!
|
790
|
+
unextend(ImmutableDocument)
|
791
|
+
end
|
683
792
|
end
|
684
793
|
end
|