odba 1.1.8 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,27 +1,36 @@
1
1
  #!/usr/bin/env ruby
2
- # encoding: utf-8
2
+
3
3
  # ODBA::Persistable -- odba -- 23.12.2011 -- mhatakeyama@ywesee.com
4
4
  # ODBA::Persistable -- odba -- 29.04.2004 -- hwyss@ywesee.com rwaltert@ywesee.com mwalder@ywesee.com
5
5
 
6
6
  class Object # :nodoc: all
7
- def odba_id
8
- end
9
- def odba_instance
10
- self
11
- end
12
- def odba_isolated_stub
13
- self
14
- end
15
- def metaclass; class << self; self; end; end
16
- def meta_eval &blk; metaclass.instance_eval &blk; end
7
+ def odba_id
8
+ end
9
+
10
+ def odba_instance
11
+ self
12
+ end
13
+
14
+ def odba_isolated_stub
15
+ self
16
+ end
17
+
18
+ def metaclass
19
+ class << self; self; end
20
+ end
21
+
22
+ def meta_eval &blk
23
+ metaclass.instance_eval(&blk)
24
+ end
17
25
  end
18
26
 
19
- require 'odba/stub'
20
- require 'observer'
27
+ require "odba/stub"
28
+ require "observer"
21
29
 
22
30
  module ODBA
23
- class Stub; end
24
- module Persistable
31
+ class Stub; end
32
+
33
+ module Persistable
25
34
  meta = Struct.new(:exact, :limit)
26
35
  Exact = meta.new
27
36
  Exact.exact = true
@@ -29,28 +38,28 @@ module ODBA
29
38
  Find.limit = 1
30
39
  # Classes which include Persistable have a class-method 'odba_index'
31
40
  attr_accessor :odba_persistent
32
- def Persistable.append_features(mod)
41
+ def self.append_features(mod)
33
42
  super
34
43
  mod.module_eval {
35
44
  class << self
36
45
  def odba_index(*keys)
37
- require 'odba/index_definition'
46
+ require "odba/index_definition"
38
47
  origin_klass = self
39
48
  resolve_origin = nil
40
49
  resolve_target = :none
41
50
  resolve = {}
42
51
  opts = {}
43
- if(keys.size > 1)
44
- if(keys.last.is_a?(Hash))
52
+ if keys.size > 1
53
+ if keys.last.is_a?(Hash)
45
54
  opts = keys.pop
46
55
  end
47
- if(keys.last.is_a?(Class))
56
+ if keys.last.is_a?(Class)
48
57
  origin_klass = keys.pop
49
58
  resolve = keys.pop
50
59
  resolve_origin = keys.pop
51
- elsif(keys.last.is_a?(Symbol))
60
+ elsif keys.last.is_a?(Symbol)
52
61
  keys.each { |key|
53
- resolve.store(key, {'resolve' => key})
62
+ resolve.store(key, {"resolve" => key})
54
63
  }
55
64
  else
56
65
  resolve = keys.pop
@@ -59,17 +68,13 @@ module ODBA
59
68
  resolve = keys.first
60
69
  end
61
70
  keys.each { |key|
62
- if RUBY_VERSION >= '1.9'
63
- key = key.to_sym
64
- else
65
- key = key.to_s
66
- end
67
- unless(instance_methods.include?(key))
71
+ key.to_sym
72
+ unless instance_methods.include?(key)
68
73
  attr_accessor key
69
74
  end
70
75
  }
71
- index_prefix = self.name.downcase.gsub(/::/, '_')
72
- index_suffix = Persistable.sanitize(keys.join('_and_'))
76
+ index_prefix = name.downcase.gsub("::", "_")
77
+ index_suffix = Persistable.sanitize(keys.join("_and_"))
73
78
  index_name = sprintf("%s_%s", index_prefix, index_suffix)
74
79
  search_name = sprintf("search_by_%s", index_suffix)
75
80
  exact_name = sprintf("search_by_exact_%s", index_suffix)
@@ -82,58 +87,58 @@ module ODBA
82
87
  index_definition.resolve_search_term = resolve
83
88
  index_definition.resolve_origin = resolve_origin.to_s
84
89
  index_definition.resolve_target = resolve_target
85
- opts.each { |key, val| index_definition.send "#{key}=", val }
90
+ opts.each { |key, val| index_definition.send :"#{key}=", val }
86
91
  ODBA.cache.ensure_index_deferred(index_definition)
87
92
  meta_eval {
88
93
  define_method(search_name) { |*vals|
89
- if(vals.size > 1)
94
+ if vals.size > 1
90
95
  args = {}
91
96
  vals.each_with_index { |val, idx|
92
97
  cond = case val
93
- when Numeric, Date
94
- '='
95
- else
96
- 'like'
97
- end
98
+ when Numeric, Date
99
+ "="
100
+ else
101
+ "like"
102
+ end
98
103
  args.store(keys.at(idx),
99
- { 'value' => val, 'condition' => cond })
104
+ {"value" => val, "condition" => cond})
100
105
  }
101
106
  ODBA.cache.retrieve_from_index(index_name, args)
102
107
  else
103
108
  ODBA.cache.retrieve_from_index(index_name, vals.first)
104
109
  end
105
110
  }
106
- define_method(exact_name) { |*vals|
107
- if(vals.size > 1)
111
+ define_method(exact_name) { |*vals|
112
+ if vals.size > 1
108
113
  args = {}
109
114
  vals.each_with_index { |val, idx|
110
115
  args.store(keys.at(idx), val)
111
116
  }
112
117
  ODBA.cache.retrieve_from_index(index_name, args,
113
- ODBA::Persistable::Exact)
118
+ ODBA::Persistable::Exact)
114
119
  else
115
120
  ODBA.cache.retrieve_from_index(index_name, vals.first,
116
- ODBA::Persistable::Exact)
121
+ ODBA::Persistable::Exact)
117
122
  end
118
123
  }
119
- define_method(find_name) { |*vals|
120
- if(vals.size > 1)
124
+ define_method(find_name) { |*vals|
125
+ if vals.size > 1
121
126
  args = {}
122
127
  vals.each_with_index { |val, idx|
123
128
  cond = case val
124
- when Numeric, Date
125
- '='
126
- else
127
- 'like'
128
- end
129
+ when Numeric, Date
130
+ "="
131
+ else
132
+ "like"
133
+ end
129
134
  args.store(keys.at(idx),
130
- { 'value' => val, 'condition' => cond })
135
+ {"value" => val, "condition" => cond})
131
136
  }
132
137
  ODBA.cache.retrieve_from_index(index_name, args,
133
- ODBA::Persistable::Find)
138
+ ODBA::Persistable::Find)
134
139
  else
135
140
  ODBA.cache.retrieve_from_index(index_name, vals.first,
136
- ODBA::Persistable::Find)
141
+ ODBA::Persistable::Find)
137
142
  end.first
138
143
  }
139
144
  define_method(keys_name) { |*vals|
@@ -144,15 +149,17 @@ module ODBA
144
149
  }
145
150
  index_definition
146
151
  end
152
+
147
153
  def odba_extent
148
154
  all = ODBA.cache.extent(self)
149
- if(block_given?)
155
+ if block_given?
150
156
  all.each { |instance| yield instance }
151
157
  nil
152
158
  else
153
159
  all
154
160
  end
155
161
  end
162
+
156
163
  def odba_count
157
164
  ODBA.cache.count(self)
158
165
  end
@@ -160,32 +167,27 @@ module ODBA
160
167
  }
161
168
  end
162
169
  @@sanitize_ptrn = /[^a-z0-9_]/i
163
- def Persistable.sanitize(name)
164
- name.gsub(@@sanitize_ptrn, '_')
165
- end
166
- attr_accessor :odba_name, :odba_prefetch
167
- # Classes which include Persistable may override ODBA_EXCLUDE_VARS to
168
- # prevent data from being stored in the database (e.g. passwords, file
169
- # descriptors). Simply redefine: ODBA_EXCLUDE_VARS = ['@foo']
170
- ODBA_EXCLUDE_VARS = []
171
- ODBA_INDEXABLE = true # :nodoc:
172
- # see odba_prefetch?
173
- ODBA_PREFETCH = false
174
- if RUBY_VERSION >= '1.9'
175
- ODBA_PREDEFINE_EXCLUDE_VARS = [:@odba_observers] # :nodoc:
176
- ODBA_PREDEFINE_SERIALIZABLE = [:@odba_target_ids] # :nodoc:, legacy
177
- else
178
- ODBA_PREDEFINE_EXCLUDE_VARS = ['@odba_observers'] # :nodoc:
179
- ODBA_PREDEFINE_SERIALIZABLE = ['@odba_target_ids'] # :nodoc:, legacy
180
- end
181
- # If you want to prevent Persistables from being disconnected and stored
182
- # separately (Array and Hash are Persistable by default), redefine:
183
- # ODBA_SERIALIZABLE = ['@bar']
184
- ODBA_SERIALIZABLE = []
185
- def ==(other) # :nodoc:
186
- super(other.odba_instance)
187
- end
188
- @@odba_id_name = RUBY_VERSION >= '1.9' ? :@odba_id : '@odba_id'
170
+ def self.sanitize(name)
171
+ name.gsub(@@sanitize_ptrn, "_")
172
+ end
173
+ attr_accessor :odba_name, :odba_prefetch
174
+ # Classes which include Persistable may override ODBA_EXCLUDE_VARS to
175
+ # prevent data from being stored in the database (e.g. passwords, file
176
+ # descriptors). Simply redefine: ODBA_EXCLUDE_VARS = ['@foo']
177
+ ODBA_EXCLUDE_VARS = []
178
+ ODBA_INDEXABLE = true # :nodoc:
179
+ # see odba_prefetch?
180
+ ODBA_PREFETCH = false
181
+ ODBA_PREDEFINE_EXCLUDE_VARS = [:@odba_observers] # :nodoc:
182
+ ODBA_PREDEFINE_SERIALIZABLE = [:@odba_target_ids] # :nodoc:, legacy
183
+ # If you want to prevent Persistables from being disconnected and stored
184
+ # separately (Array and Hash are Persistable by default), redefine:
185
+ # ODBA_SERIALIZABLE = ['@bar']
186
+ ODBA_SERIALIZABLE = []
187
+ def ==(other) # :nodoc:
188
+ super(other.odba_instance)
189
+ end
190
+ @@odba_id_name = :@odba_id
189
191
  def dup # :nodoc:
190
192
  twin = super
191
193
  ## since twin may not be a Persistable, we need to do some magic here to
@@ -193,343 +195,376 @@ module ODBA
193
195
  twin.instance_variable_set(@@odba_id_name, nil)
194
196
  twin
195
197
  end
198
+
196
199
  def eql?(other) # :nodoc:
197
200
  (other.is_a?(Stub) && other.odba_id == @odba_id) \
198
201
  || super(other.odba_instance)
199
202
  end
203
+
200
204
  # Add an observer for Cache#store(self), Cache#delete(self) and
201
205
  # Cache#clean removing the object from the Cache
202
206
  def odba_add_observer(obj)
203
207
  odba_observers.push(obj)
204
208
  obj
205
209
  end
206
- def odba_collection # :nodoc:
207
- []
208
- end
209
- # Removes all connections to another persistable. This method is called
210
- # by the Cache server when _remove_object_ is deleted from the database
211
- def odba_cut_connection(remove_object)
212
- odba_potentials.each { |name|
213
- var = instance_variable_get(name)
214
- if(var.eql?(remove_object))
215
- instance_variable_set(name, nil)
216
- end
217
- }
218
- end
210
+
211
+ def odba_collection # :nodoc:
212
+ []
213
+ end
214
+
215
+ # Removes all connections to another persistable. This method is called
216
+ # by the Cache server when _remove_object_ is deleted from the database
217
+ def odba_cut_connection(remove_object)
218
+ odba_potentials.each { |name|
219
+ var = instance_variable_get(name)
220
+ if var.eql?(remove_object)
221
+ instance_variable_set(name, nil)
222
+ end
223
+ }
224
+ end
225
+
219
226
  # Permanently deletes this Persistable from the database and remove
220
227
  # all connections to it
221
- def odba_delete
222
- ODBA.cache.delete(self)
223
- end
228
+ def odba_delete
229
+ ODBA.cache.delete(self)
230
+ end
231
+
224
232
  # Delete _observer_ as an observer on this object.
225
233
  # It will no longer receive notifications.
226
234
  def odba_delete_observer(observer)
227
- @odba_observers.delete(observer) if(@odba_observers)
235
+ @odba_observers.delete(observer) if @odba_observers
228
236
  end
237
+
229
238
  # Delete all observers associated with this object.
230
239
  def odba_delete_observers
231
240
  @odba_observers = nil
232
241
  end
233
- def odba_dup #:nodoc:
234
- twin = dup
242
+
243
+ def odba_dup # :nodoc:
244
+ twin = dup
235
245
  twin.extend(Persistable)
236
246
  twin.odba_id = @odba_id
237
- odba_potentials.each { |name|
238
- var = twin.instance_variable_get(name)
239
- if(var.is_a?(ODBA::Stub))
240
- stub = var.odba_dup
241
- stub.odba_container = twin
242
- twin.instance_variable_set(name, stub)
243
- end
244
- }
245
- twin
246
- end
247
+ odba_potentials.each { |name|
248
+ var = twin.instance_variable_get(name)
249
+ if var.is_a?(ODBA::Stub)
250
+ stub = var.odba_dup
251
+ stub.odba_container = twin
252
+ twin.instance_variable_set(name, stub)
253
+ end
254
+ }
255
+ twin
256
+ end
257
+
247
258
  def odba_exclude_vars # :nodoc:
248
- exc = if(defined?(self::class::ODBA_PREDEFINE_EXCLUDE_VARS))
249
- self::class::ODBA_PREDEFINE_EXCLUDE_VARS
250
- else
251
- ODBA_PREDEFINE_EXCLUDE_VARS
252
- end
253
- if(defined?(self::class::ODBA_EXCLUDE_VARS))
254
- exc += self::class::ODBA_EXCLUDE_VARS
255
- end
256
- if RUBY_VERSION >= '1.9'
257
- exc.map{|v| v.to_sym}
259
+ exc = if defined?(self.class::ODBA_PREDEFINE_EXCLUDE_VARS)
260
+ self.class::ODBA_PREDEFINE_EXCLUDE_VARS
258
261
  else
259
- exc
262
+ ODBA_PREDEFINE_EXCLUDE_VARS
263
+ end
264
+ if defined?(self.class::ODBA_EXCLUDE_VARS)
265
+ exc += self.class::ODBA_EXCLUDE_VARS
260
266
  end
267
+ exc.map { |v| v.to_sym }
261
268
  end
262
- # Returns the odba unique id of this Persistable.
269
+
270
+ # Returns the odba unique id of this Persistable.
263
271
  # If no id had been assigned, this is now done.
264
272
  # No attempt is made to store the Persistable in the db.
265
- def odba_id
266
- @odba_id ||= ODBA.cache.next_id
267
- end
268
- def odba_isolated_dump # :nodoc:
269
- ODBA.marshaller.dump(odba_isolated_twin)
270
- end
271
- # Convenience method equivalent to ODBA.cache.store(self)
272
- def odba_isolated_store
273
- @odba_persistent = true
274
- ODBA.cache.store(self)
275
- end
276
- # Returns a new instance of Stub, which can be used as a stand-in replacement
277
- # for this Persistable.
278
- def odba_isolated_stub
279
- Stub.new(self.odba_id, nil, self)
280
- end
281
- # Returns a duplicate of this Persistable, for which all connected
282
- # Persistables have been replaced by a Stub
283
- def odba_isolated_twin
284
- # ensure a valid odba_id
285
- self.odba_id
286
- twin = self.odba_dup
287
- twin.odba_replace_persistables
288
- twin.odba_replace_excluded!
289
- twin
290
- end
291
- # A Persistable instance can be _prefetchable_. This means that the object
292
- # can be loaded at startup by calling ODBA.cache.prefetch, and that it will
293
- # never expire from the Cache. The prefetch status can be controlled per
294
- # instance by setting the instance variable @odba_prefetch, and per class by
295
- # overriding the module constant ODBA_PREFETCH
296
- def odba_prefetch?
273
+ def odba_id
274
+ @odba_id ||= ODBA.cache.next_id
275
+ end
276
+
277
+ def odba_isolated_dump # :nodoc:
278
+ ODBA.marshaller.dump(odba_isolated_twin)
279
+ end
280
+
281
+ # Convenience method equivalent to ODBA.cache.store(self)
282
+ def odba_isolated_store
283
+ @odba_persistent = true
284
+ ODBA.cache.store(self)
285
+ end
286
+
287
+ # Returns a new instance of Stub, which can be used as a stand-in replacement
288
+ # for this Persistable.
289
+ def odba_isolated_stub
290
+ Stub.new(odba_id, nil, self)
291
+ end
292
+
293
+ # Returns a duplicate of this Persistable, for which all connected
294
+ # Persistables have been replaced by a Stub
295
+ def odba_isolated_twin
296
+ # ensure a valid odba_id
297
+ odba_id
298
+ twin = odba_dup
299
+ twin.odba_replace_persistables
300
+ twin.odba_replace_excluded!
301
+ twin
302
+ end
303
+
304
+ # A Persistable instance can be _prefetchable_. This means that the object
305
+ # can be loaded at startup by calling ODBA.cache.prefetch, and that it will
306
+ # never expire from the Cache. The prefetch status can be controlled per
307
+ # instance by setting the instance variable @odba_prefetch, and per class by
308
+ # overriding the module constant ODBA_PREFETCH
309
+ def odba_prefetch?
297
310
  @odba_prefetch ||= nil
298
- @odba_prefetch \
299
- || (defined?(self::class::ODBA_PREFETCH) && self::class::ODBA_PREFETCH)
300
- end
301
- def odba_indexable? # :nodoc:
302
- @odba_indexable \
303
- || (defined?(self::class::ODBA_INDEXABLE) && self::class::ODBA_INDEXABLE)
304
- end
311
+ @odba_prefetch \
312
+ || (defined?(self.class::ODBA_PREFETCH) && self.class::ODBA_PREFETCH)
313
+ end
314
+
315
+ def odba_indexable? # :nodoc:
316
+ @odba_indexable \
317
+ || (defined?(self.class::ODBA_INDEXABLE) && self.class::ODBA_INDEXABLE)
318
+ end
319
+
305
320
  # Invoke the update method in each currently associated observer
306
321
  # in turn, passing it the given arguments
307
322
  def odba_notify_observers(*args)
308
323
  odba_observers.each { |obs| obs.odba_update(*args) }
309
324
  end
325
+
310
326
  def odba_observers
311
327
  @odba_observers ||= []
312
328
  end
313
- def odba_potentials # :nodoc:
314
- instance_variables - odba_serializables - odba_exclude_vars
315
- end
329
+
330
+ def odba_potentials # :nodoc:
331
+ instance_variables - odba_serializables - odba_exclude_vars
332
+ end
333
+
316
334
  def odba_replace!(obj) # :nodoc:
317
335
  @odba_observers ||= []
318
336
  instance_variables.each { |name|
319
337
  instance_variable_set(name, obj.instance_variable_get(name))
320
338
  }
321
339
  end
322
- def odba_replace_persistables # :nodoc:
323
- odba_potentials.each { |name|
324
- var = instance_variable_get(name)
325
- if(var.is_a?(ODBA::Stub))
340
+
341
+ def odba_replace_persistables # :nodoc:
342
+ odba_potentials.each { |name|
343
+ var = instance_variable_get(name)
344
+ if var.is_a?(ODBA::Stub)
326
345
  var.odba_clear_receiver # ensure we don't leak into the db
327
346
  var.odba_container = self # ensure we don't leak into memory
328
- elsif(var.is_a?(ODBA::Persistable))
329
- odba_id = var.odba_id
330
- stub = ODBA::Stub.new(odba_id, self, var)
331
- instance_variable_set(name, stub)
332
- end
333
- }
334
- odba_serializables.each { |name|
335
- var = instance_variable_get(name)
336
- if(var.is_a?(ODBA::Stub))
337
- instance_variable_set(name, var.odba_instance)
338
- end
339
- }
340
- end
341
- def odba_replace_stubs(odba_id, substitution) # :nodoc:
347
+ elsif var.is_a?(ODBA::Persistable)
348
+ odba_id = var.odba_id
349
+ stub = ODBA::Stub.new(odba_id, self, var)
350
+ instance_variable_set(name, stub)
351
+ end
352
+ }
353
+ odba_serializables.each { |name|
354
+ var = instance_variable_get(name)
355
+ if var.is_a?(ODBA::Stub)
356
+ instance_variable_set(name, var.odba_instance)
357
+ end
358
+ }
359
+ end
360
+
361
+ def odba_replace_stubs(odba_id, substitution) # :nodoc:
342
362
  odba_potentials.each { |name|
343
363
  var = instance_variable_get(name)
344
- if(var.is_a?(Stub) && odba_id == var.odba_id)
364
+ if var.is_a?(Stub) && odba_id == var.odba_id
345
365
  instance_variable_set(name, substitution)
346
366
  end
347
367
  }
348
- end
349
- def odba_restore(collection=[]) # :nodoc:
350
- end
351
- def odba_serializables # :nodoc:
352
- srs = if(defined?(self::class::ODBA_PREDEFINE_SERIALIZABLE))
353
- self::class::ODBA_PREDEFINE_SERIALIZABLE
354
- else
355
- ODBA_PREDEFINE_SERIALIZABLE
356
- end
357
- if(defined?(self::class::ODBA_SERIALIZABLE))
358
- srs += self::class::ODBA_SERIALIZABLE
359
- end
360
- if RUBY_VERSION >= '1.9'
361
- srs.map{|s| s.to_sym}
368
+ end
369
+
370
+ def odba_restore(collection = []) # :nodoc:
371
+ end
372
+
373
+ def odba_serializables # :nodoc:
374
+ srs = if defined?(self.class::ODBA_PREDEFINE_SERIALIZABLE)
375
+ self.class::ODBA_PREDEFINE_SERIALIZABLE
362
376
  else
363
- srs
377
+ ODBA_PREDEFINE_SERIALIZABLE
364
378
  end
365
- end
366
- def odba_snapshot(snapshot_level) # :nodoc:
367
- if(snapshot_level > @odba_snapshot_level.to_i)
368
- @odba_snapshot_level = snapshot_level
369
- odba_isolated_store
370
- end
371
- end
372
- # Stores this Persistable and recursively all connected unsaved persistables,
373
- # until no more direcly connected unsaved persistables can be found.
374
- # The optional parameter _name_ can be used later to retrieve this
375
- # Persistable using Cache#fetch_named
376
- def odba_store(name = nil)
377
- begin
378
- unless (name.nil?)
379
- old_name = @odba_name
380
- @odba_name = name
381
- end
382
- odba_store_unsaved
383
- self
384
- rescue
385
- @odba_name = old_name
386
- raise
387
- end
388
- end
389
- def odba_store_unsaved # :nodoc:
390
- @odba_persistent = false
391
- current_level = [self]
392
- while(!current_level.empty?)
393
- next_level = []
394
- current_level.each { |item|
395
- if(item.odba_unsaved?)
396
- next_level += item.odba_unsaved_neighbors
397
- item.odba_isolated_store
398
- end
399
- }
400
- current_level = next_level
401
- end
402
- end
403
- def odba_stubize(obj, opts={}) # :nodoc:
404
- return false if(frozen?)
405
- id = obj.odba_id
406
- odba_potentials.each { |name|
407
- var = instance_variable_get(name)
408
- # must not be synchronized because of the following if
409
- # statement (if an object has already been replaced by
410
- # a stub, it will have the correct id and it
411
- # will be ignored)
379
+ if defined?(self.class::ODBA_SERIALIZABLE)
380
+ srs += self.class::ODBA_SERIALIZABLE
381
+ end
382
+ srs.map { |s| s.to_sym }
383
+ end
384
+
385
+ def odba_snapshot(snapshot_level) # :nodoc:
386
+ if snapshot_level > @odba_snapshot_level.to_i
387
+ @odba_snapshot_level = snapshot_level
388
+ odba_isolated_store
389
+ end
390
+ end
391
+
392
+ # Stores this Persistable and recursively all connected unsaved persistables,
393
+ # until no more direcly connected unsaved persistables can be found.
394
+ # The optional parameter _name_ can be used later to retrieve this
395
+ # Persistable using Cache#fetch_named
396
+ def odba_store(name = nil)
397
+ unless name.nil?
398
+ old_name = @odba_name
399
+ @odba_name = name
400
+ end
401
+ odba_store_unsaved
402
+ self
403
+ rescue
404
+ @odba_name = old_name
405
+ raise
406
+ end
407
+
408
+ def odba_store_unsaved # :nodoc:
409
+ @odba_persistent = false
410
+ current_level = [self]
411
+ until current_level.empty?
412
+ next_level = []
413
+ current_level.each { |item|
414
+ if item.odba_unsaved?
415
+ next_level += item.odba_unsaved_neighbors
416
+ item.odba_isolated_store
417
+ end
418
+ }
419
+ current_level = next_level
420
+ end
421
+ end
422
+
423
+ def odba_stubize(obj, opts = {}) # :nodoc:
424
+ return false if frozen?
425
+ id = obj.odba_id
426
+ odba_potentials.each { |name|
427
+ var = instance_variable_get(name)
428
+ # must not be synchronized because of the following if
429
+ # statement (if an object has already been replaced by
430
+ # a stub, it will have the correct id and it
431
+ # will be ignored)
412
432
  case var
413
433
  when Stub
414
434
  # no need to make a new stub
415
435
  when Persistable
416
- if(var.odba_id == id)
436
+ if var.odba_id == id
417
437
  stub = ODBA::Stub.new(id, self, obj)
418
438
  instance_variable_set(name, stub)
419
439
  end
420
- end
421
- }
440
+ end
441
+ }
422
442
  odba_notify_observers(:stubize, id, obj.object_id)
423
443
  ## allow CacheEntry to retire
424
444
  true
425
- end
426
- # Recursively stores all connected Persistables.
427
- def odba_take_snapshot
428
- @odba_snapshot_level ||= 0
429
- snapshot_level = @odba_snapshot_level.next
430
- current_level = [self]
431
- tree_level = 0
432
- while(!current_level.empty?)
433
- tree_level += 1
434
- obj_count = 0
435
- next_level = []
436
- current_level.each { |item|
437
- if(item.odba_unsaved?(snapshot_level))
438
- obj_count += 1
439
- next_level += item.odba_unsaved_neighbors(snapshot_level)
440
- item.odba_snapshot(snapshot_level)
441
- end
442
- }
443
- current_level = next_level #.uniq
444
- end
445
- end
446
- def odba_target_ids # :nodoc:
447
- odba_potentials.collect { |name|
448
- var = instance_variable_get(name)
449
- if(var.is_a?(ODBA::Persistable))
450
- var.odba_id
451
- end
452
- }.compact.uniq
453
- end
454
- def odba_unsaved_neighbors(snapshot_level = nil) # :nodoc:
455
- unsaved = []
456
- odba_potentials.each { |name|
457
- item = instance_variable_get(name)
458
- if(item.is_a?(ODBA::Persistable) \
459
- && item.odba_unsaved?(snapshot_level))
460
- unsaved.push(item)
461
- end
462
- }
463
- unsaved
464
- end
465
- def odba_unsaved?(snapshot_level = nil) # :nodoc:
466
- if(snapshot_level.nil?)
467
- !@odba_persistent
468
- #true
469
- else
445
+ end
446
+
447
+ # Recursively stores all connected Persistables.
448
+ def odba_take_snapshot
449
+ @odba_snapshot_level ||= 0
450
+ snapshot_level = @odba_snapshot_level.next
451
+ current_level = [self]
452
+ tree_level = 0
453
+ until current_level.empty?
454
+ tree_level += 1
455
+ obj_count = 0
456
+ next_level = []
457
+ current_level.each { |item|
458
+ if item.odba_unsaved?(snapshot_level)
459
+ obj_count += 1
460
+ next_level += item.odba_unsaved_neighbors(snapshot_level)
461
+ item.odba_snapshot(snapshot_level)
462
+ end
463
+ }
464
+ current_level = next_level # .uniq
465
+ end
466
+ end
467
+
468
+ def odba_target_ids # :nodoc:
469
+ odba_potentials.collect { |name|
470
+ var = instance_variable_get(name)
471
+ if var.is_a?(ODBA::Persistable)
472
+ var.odba_id
473
+ end
474
+ }.compact.uniq
475
+ end
476
+
477
+ def odba_unsaved_neighbors(snapshot_level = nil) # :nodoc:
478
+ unsaved = []
479
+ odba_potentials.each { |name|
480
+ item = instance_variable_get(name)
481
+ if item.is_a?(ODBA::Persistable) \
482
+ && item.odba_unsaved?(snapshot_level)
483
+ unsaved.push(item)
484
+ end
485
+ }
486
+ unsaved
487
+ end
488
+
489
+ def odba_unsaved?(snapshot_level = nil) # :nodoc:
490
+ if snapshot_level.nil?
491
+ !@odba_persistent
492
+ # true
493
+ else
470
494
  @odba_snapshot_level ||= 0
471
- @odba_snapshot_level.to_i < snapshot_level
472
- end
473
- end
474
- protected
495
+ @odba_snapshot_level.to_i < snapshot_level
496
+ end
497
+ end
498
+
499
+ protected
500
+
475
501
  attr_writer :odba_id
476
- def odba_replace_excluded!
477
- odba_exclude_vars.each { |name|
478
- instance_variable_set(name, nil)
479
- }
480
- end
481
- end
502
+ def odba_replace_excluded!
503
+ odba_exclude_vars.each { |name|
504
+ instance_variable_set(name, nil)
505
+ }
506
+ end
507
+ end
482
508
  end
509
+
483
510
  class Array # :nodoc: all
484
- include ODBA::Persistable
485
- def odba_collection
486
- coll = []
487
- each_with_index { |item, index|
488
- coll.push([index, item])
489
- }
490
- coll
491
- end
492
- def odba_cut_connection(remove_object)
493
- super(remove_object)
494
- delete_if { |val| val.eql?(remove_object) }
495
- end
496
- def odba_prefetch?
497
- super || any? { |item|
498
- item.respond_to?(:odba_prefetch?) \
499
- && item.odba_prefetch?
500
- }
501
- end
511
+ include ODBA::Persistable
512
+ def odba_collection
513
+ coll = []
514
+ each_with_index { |item, index|
515
+ coll.push([index, item])
516
+ }
517
+ coll
518
+ end
519
+
520
+ def odba_cut_connection(remove_object)
521
+ super
522
+ delete_if { |val| val.eql?(remove_object) }
523
+ end
524
+
525
+ def odba_prefetch?
526
+ super || any? { |item|
527
+ item.respond_to?(:odba_prefetch?) \
528
+ && item.odba_prefetch?
529
+ }
530
+ end
531
+
502
532
  def odba_replace!(obj) # :nodoc:
503
533
  super
504
534
  replace(obj)
505
535
  end
506
- def odba_replace_persistables
507
- clear
508
- super
509
- end
510
- def odba_restore(collection=[])
511
- collection.each { |key, val|
512
- self[key] = val
513
- }
514
- end
515
- def odba_unsaved_neighbors(snapshot_level = nil)
516
- unsaved = super
517
- each { |item|
518
- #odba_extend_enumerable(item)
519
- if(item.is_a?(ODBA::Persistable) \
520
- && item.odba_unsaved?(snapshot_level))
521
- unsaved.push(item)
522
- end
523
- }
524
- unsaved
525
- end
526
- def odba_unsaved?(snapshot_level = nil)
527
- super || (snapshot_level.nil? && any? { |val|
528
- val.is_a?(ODBA::Persistable) && val.odba_unsaved?
529
- } )
530
- end
531
- def odba_stubize(obj, opts={}) # :nodoc:
532
- return false if(frozen?)
536
+
537
+ def odba_replace_persistables
538
+ clear
539
+ super
540
+ end
541
+
542
+ def odba_restore(collection = [])
543
+ collection.each { |key, val|
544
+ self[key] = val
545
+ }
546
+ end
547
+
548
+ def odba_unsaved_neighbors(snapshot_level = nil)
549
+ unsaved = super
550
+ each { |item|
551
+ # odba_extend_enumerable(item)
552
+ if item.is_a?(ODBA::Persistable) \
553
+ && item.odba_unsaved?(snapshot_level)
554
+ unsaved.push(item)
555
+ end
556
+ }
557
+ unsaved
558
+ end
559
+
560
+ def odba_unsaved?(snapshot_level = nil)
561
+ super || (snapshot_level.nil? && any? { |val|
562
+ val.is_a?(ODBA::Persistable) && val.odba_unsaved?
563
+ })
564
+ end
565
+
566
+ def odba_stubize(obj, opts = {}) # :nodoc:
567
+ return false if frozen?
533
568
  super
534
569
  if opts[:force]
535
570
  id = obj.odba_id
@@ -546,73 +581,83 @@ class Array # :nodoc: all
546
581
  false
547
582
  end
548
583
  end
549
- def odba_target_ids
550
- ids = super
551
- self.each { |value|
552
- if(value.is_a?(ODBA::Persistable))
553
- ids.push(value.odba_id)
554
- end
555
- }
556
- ids.uniq
557
- end
584
+
585
+ def odba_target_ids
586
+ ids = super
587
+ each { |value|
588
+ if value.is_a?(ODBA::Persistable)
589
+ ids.push(value.odba_id)
590
+ end
591
+ }
592
+ ids.uniq
593
+ end
558
594
  end
595
+
559
596
  class Hash # :nodoc: all
560
- include ODBA::Persistable
561
- def odba_cut_connection(remove_object)
562
- super(remove_object)
563
- delete_if { |key, val|
564
- key.eql?(remove_object) || val.eql?(remove_object)
565
- }
566
- end
567
- def odba_collection
568
- self.to_a
569
- end
570
- def odba_prefetch?
571
- super || any? { |item|
572
- item.respond_to?(:odba_prefetch?) \
573
- && item.odba_prefetch?
574
- }
575
- end
597
+ include ODBA::Persistable
598
+ def odba_cut_connection(remove_object)
599
+ super
600
+ delete_if { |key, val|
601
+ key.eql?(remove_object) || val.eql?(remove_object)
602
+ }
603
+ end
604
+
605
+ def odba_collection
606
+ to_a
607
+ end
608
+
609
+ def odba_prefetch?
610
+ super || any? { |item|
611
+ item.respond_to?(:odba_prefetch?) \
612
+ && item.odba_prefetch?
613
+ }
614
+ end
615
+
576
616
  def odba_replace!(obj) # :nodoc:
577
617
  super
578
618
  replace(obj)
579
619
  end
580
- def odba_replace_persistables
581
- clear
582
- super
583
- end
584
- def odba_restore(collection=[])
585
- collection.each { |key, val|
586
- self[key] = val
587
- }
588
- end
589
- def odba_unsaved?(snapshot_level = nil)
590
- super || (snapshot_level.nil? && any? { |key, val|
591
- val.is_a?(ODBA::Persistable) && val.odba_unsaved? \
592
- || key.is_a?(ODBA::Persistable) && key.odba_unsaved?
593
- })
594
- end
595
- def odba_unsaved_neighbors(snapshot_level = nil)
596
- unsaved = super
597
- each { |pair|
598
- pair.each { |item|
599
- #odba_extend_enumerable(item)
600
- if(item.is_a?(ODBA::Persistable)\
601
- && item.odba_unsaved?(snapshot_level))
602
- unsaved.push(item)
603
- end
604
- }
605
- }
606
- unsaved
607
- end
608
- def odba_stubize(obj, opts={}) # :nodoc:
609
- return false if(frozen?)
620
+
621
+ def odba_replace_persistables
622
+ clear
623
+ super
624
+ end
625
+
626
+ def odba_restore(collection = [])
627
+ collection.each { |key, val|
628
+ self[key] = val
629
+ }
630
+ end
631
+
632
+ def odba_unsaved?(snapshot_level = nil)
633
+ super || (snapshot_level.nil? && any? { |key, val|
634
+ val.is_a?(ODBA::Persistable) && val.odba_unsaved? \
635
+ || key.is_a?(ODBA::Persistable) && key.odba_unsaved?
636
+ })
637
+ end
638
+
639
+ def odba_unsaved_neighbors(snapshot_level = nil)
640
+ unsaved = super
641
+ each { |pair|
642
+ pair.each { |item|
643
+ # odba_extend_enumerable(item)
644
+ if item.is_a?(ODBA::Persistable) \
645
+ && item.odba_unsaved?(snapshot_level)
646
+ unsaved.push(item)
647
+ end
648
+ }
649
+ }
650
+ unsaved
651
+ end
652
+
653
+ def odba_stubize(obj, opts = {}) # :nodoc:
654
+ return false if frozen?
610
655
  super
611
656
  if opts[:force]
612
657
  dup = {}
613
658
  each do |pair|
614
659
  pair.odba_stubize(obj)
615
- dup.store *pair
660
+ dup.store(*pair)
616
661
  end
617
662
  replace dup
618
663
  true
@@ -620,16 +665,17 @@ class Hash # :nodoc: all
620
665
  false
621
666
  end
622
667
  end
623
- def odba_target_ids
624
- ids = super
625
- self.each { |key, value|
626
- if(value.is_a?(ODBA::Persistable))
627
- ids.push(value.odba_id)
628
- end
629
- if(key.is_a?(ODBA::Persistable))
630
- ids.push(key.odba_id)
631
- end
632
- }
633
- ids.uniq
634
- end
668
+
669
+ def odba_target_ids
670
+ ids = super
671
+ each { |key, value|
672
+ if value.is_a?(ODBA::Persistable)
673
+ ids.push(value.odba_id)
674
+ end
675
+ if key.is_a?(ODBA::Persistable)
676
+ ids.push(key.odba_id)
677
+ end
678
+ }
679
+ ids.uniq
680
+ end
635
681
  end