baza 0.0.15 → 0.0.16

Sign up to get free protection for your applications and to get access to all the features.
@@ -3,10 +3,10 @@ require "string-cases"
3
3
 
4
4
  class Baza::ModelHandler
5
5
  attr_reader :args, :events, :data, :ids_cache, :ids_cache_should
6
-
6
+
7
7
  def initialize(args)
8
8
  require "monitor"
9
-
9
+
10
10
  @callbacks = {}
11
11
  @args = args
12
12
  @args[:col_id] = :id if !@args[:col_id]
@@ -17,10 +17,10 @@ class Baza::ModelHandler
17
17
  @locks = {}
18
18
  @data = {}
19
19
  @lock_require = Monitor.new
20
-
20
+
21
21
  Knj.gem_require(:Wref, "wref") if @args[:cache] == :weak and !Kernel.const_defined?(:Wref)
22
22
  require "#{@args[:array_enumerator_path]}array_enumerator" if @args[:array_enum] and !Kernel.const_defined?(:Array_enumerator)
23
-
23
+
24
24
  #Set up various events.
25
25
  @events = Knj::Event_handler.new
26
26
  @events.add_event(:name => :no_html, :connections_max => 1)
@@ -28,134 +28,134 @@ class Baza::ModelHandler
28
28
  @events.add_event(:name => :no_date, :connections_max => 1)
29
29
  @events.add_event(:name => :missing_class, :connections_max => 1)
30
30
  @events.add_event(:name => :require_class, :connections_max => 1)
31
-
31
+
32
32
  raise "No DB given." if !@args[:db] and !@args[:custom]
33
33
  raise "No class path given." if !@args[:class_path] and (@args[:require] or !@args.key?(:require))
34
-
34
+
35
35
  if args[:require_all]
36
36
  loads = []
37
-
37
+
38
38
  Dir.foreach(@args[:class_path]) do |file|
39
39
  next if file == "." or file == ".." or !file.match(/\.rb$/)
40
40
  file_parsed = file
41
41
  file_parsed.gsub!(@args[:class_pre], "") if @args.key?(:class_pre)
42
42
  file_parsed.gsub!(/\.rb$/, "")
43
43
  file_parsed = StringCases.snake_to_camel(file_parsed)
44
-
44
+
45
45
  loads << file_parsed
46
46
  self.requireclass(file_parsed, {:load => false})
47
47
  end
48
-
48
+
49
49
  loads.each do |load_class|
50
50
  self.load_class(load_class)
51
51
  end
52
52
  end
53
-
53
+
54
54
  #Set up ID-caching.
55
55
  @ids_cache_should = {}
56
-
56
+
57
57
  if @args[:models]
58
58
  @ids_cache = {}
59
-
59
+
60
60
  @args[:models].each do |classname, classargs|
61
61
  @ids_cache_should[classname] = true if classargs[:cache_ids]
62
62
  self.cache_ids(classname)
63
63
  end
64
64
  end
65
65
  end
66
-
66
+
67
67
  #Caches all IDs for a specific classname.
68
68
  def cache_ids(classname)
69
69
  classname = classname.to_sym
70
70
  return nil if !@ids_cache_should or !@ids_cache_should[classname]
71
-
71
+
72
72
  newcache = {}
73
73
  @args[:db].q("SELECT `#{@args[:col_id]}` FROM `#{classname}` ORDER BY `#{@args[:col_id]}`") do |data|
74
74
  newcache[data[@args[:col_id]].to_i] = true
75
75
  end
76
-
76
+
77
77
  @ids_cache[classname] = newcache
78
78
  end
79
-
79
+
80
80
  def init_class(classname)
81
81
  classname = classname.to_sym
82
82
  return false if @objects.key?(classname)
83
-
83
+
84
84
  if @args[:cache] == :weak
85
- @objects[classname] = Wref_map.new
85
+ @objects[classname] = Wref::Map.new
86
86
  else
87
87
  @objects[classname] = {}
88
88
  end
89
-
89
+
90
90
  @locks[classname] = Monitor.new
91
91
  end
92
-
92
+
93
93
  def uninit_class(classname)
94
94
  @objects.delete(classname)
95
95
  @locks.delete(classname)
96
96
  end
97
-
97
+
98
98
  #Returns a cloned version of the @objects variable. Cloned because iteration on it may crash some of the other methods in Ruby 1.9+
99
99
  def objects
100
100
  objs_cloned = {}
101
-
101
+
102
102
  @objects.keys.each do |key|
103
103
  objs_cloned[key] = @objects[key].clone
104
104
  end
105
-
105
+
106
106
  return objs_cloned
107
107
  end
108
-
108
+
109
109
  #Returns the database-connection used by this instance of Objects.
110
110
  def db
111
111
  return @args[:db]
112
112
  end
113
-
113
+
114
114
  #Returns the total count of objects currently held by this instance.
115
115
  def count_objects
116
116
  count = 0
117
117
  @objects.keys.each do |key|
118
118
  count += @objects[key].length
119
119
  end
120
-
120
+
121
121
  return count
122
122
  end
123
-
123
+
124
124
  #This connects a block to an event. When the event is called the block will be executed.
125
125
  def connect(args, &block)
126
126
  raise "No object given." if !args["object"]
127
127
  raise "No signals given." if !args.key?("signal") and !args.key?("signals")
128
128
  args["block"] = block if block_given?
129
129
  object = args["object"].to_sym
130
-
130
+
131
131
  @callbacks[object] = {} if !@callbacks[object]
132
132
  conn_id = @callbacks[object].length.to_s
133
133
  @callbacks[object][conn_id] = args
134
134
  return conn_id
135
135
  end
136
-
136
+
137
137
  #Returns true if the given signal is connected to the given object.
138
138
  def connected?(args)
139
139
  raise "No object given." if !args["object"]
140
140
  raise "No signal given." if !args.key?("signal")
141
141
  object = args["object"].to_sym
142
-
142
+
143
143
  if @callbacks.key?(object)
144
144
  @callbacks[object].clone.each do |ckey, callback|
145
145
  return true if callback.key?("signal") and callback["signal"].to_s == args["signal"].to_s
146
146
  return true if callback.key?("signals") and (callback["signals"].include?(args["signal"].to_s) or callback["signals"].include?(args["signal"].to_sym))
147
147
  end
148
148
  end
149
-
149
+
150
150
  return false
151
151
  end
152
-
152
+
153
153
  #Unconnects a connect by 'object' and 'conn_id'.
154
154
  def unconnect(args)
155
155
  raise ArgumentError, "No object given." if !args["object"]
156
156
  object = args["object"].to_sym
157
157
  raise ArgumentError, "Object doesnt exist: '#{object}'." if !@callbacks.key?(object)
158
-
158
+
159
159
  if args["conn_id"]
160
160
  conn_ids = [args["conn_id"]]
161
161
  elsif args["conn_ids"]
@@ -163,29 +163,29 @@ class Baza::ModelHandler
163
163
  else
164
164
  raise ArgumentError, "Could not figure out connection IDs."
165
165
  end
166
-
166
+
167
167
  conn_ids.each do |conn_id|
168
168
  raise Errno::ENOENT, "Conn ID doest exist: '#{conn_id}' (#{args})." if !@callbacks[object].key?(conn_id)
169
169
  @callbacks[object].delete(conn_id)
170
170
  end
171
171
  end
172
-
172
+
173
173
  #This method is used to call the connected callbacks for an event.
174
174
  def call(args, &block)
175
175
  classstr = args["object"].class.classname.to_sym
176
-
176
+
177
177
  if @callbacks.key?(classstr)
178
178
  @callbacks[classstr].clone.each do |callback_key, callback|
179
179
  docall = false
180
-
180
+
181
181
  if callback.key?("signal") and args.key?("signal") and callback["signal"].to_s == args["signal"].to_s
182
182
  docall = true
183
183
  elsif callback["signals"] and args["signal"] and (callback["signals"].include?(args["signal"].to_s) or callback["signals"].include?(args["signal"].to_sym))
184
184
  docall = true
185
185
  end
186
-
186
+
187
187
  next if !docall
188
-
188
+
189
189
  if callback["block"]
190
190
  callargs = []
191
191
  arity = callback["block"].arity
@@ -196,7 +196,7 @@ class Baza::ModelHandler
196
196
  else
197
197
  raise "Unknown number of arguments: #{arity}"
198
198
  end
199
-
199
+
200
200
  callback["block"].call(*callargs)
201
201
  else
202
202
  raise "No valid callback given."
@@ -204,23 +204,23 @@ class Baza::ModelHandler
204
204
  end
205
205
  end
206
206
  end
207
-
207
+
208
208
  def requireclass(classname, args = {})
209
209
  classname = classname.to_sym
210
210
  return false if @objects.key?(classname)
211
211
  classname_snake = StringCases.camel_to_snake(classname)
212
-
212
+
213
213
  @lock_require.synchronize do
214
214
  #Maybe the classname got required meanwhile the synchronized wait - check again.
215
215
  return false if @objects.key?(classname)
216
-
216
+
217
217
  if @events.connected?(:require_class)
218
218
  @events.call(:require_class, {
219
219
  :class => classname
220
220
  })
221
221
  else
222
222
  doreq = false
223
-
223
+
224
224
  if args[:require]
225
225
  doreq = true
226
226
  elsif args.key?(:require) and !args[:require]
@@ -228,7 +228,7 @@ class Baza::ModelHandler
228
228
  elsif @args[:require] or !@args.key?(:require)
229
229
  doreq = true
230
230
  end
231
-
231
+
232
232
  if doreq
233
233
  filename = "#{@args[:class_path]}/#{@args[:class_pre]}#{classname_snake}.rb"
234
234
  filename_req = "#{@args[:class_path]}/#{@args[:class_pre]}#{classname_snake}"
@@ -236,7 +236,7 @@ class Baza::ModelHandler
236
236
  require filename_req
237
237
  end
238
238
  end
239
-
239
+
240
240
  if args[:class]
241
241
  classob = args[:class]
242
242
  else
@@ -253,15 +253,15 @@ class Baza::ModelHandler
253
253
  end
254
254
  end
255
255
  end
256
-
256
+
257
257
  if (classob.respond_to?(:load_columns) or classob.respond_to?(:datarow_init)) and (!args.key?(:load) or args[:load])
258
258
  self.load_class(classname, args)
259
259
  end
260
-
260
+
261
261
  self.init_class(classname)
262
262
  end
263
263
  end
264
-
264
+
265
265
  #Loads a Datarow-class by calling various static methods.
266
266
  def load_class(classname, args = {})
267
267
  if args[:class]
@@ -269,24 +269,24 @@ class Baza::ModelHandler
269
269
  else
270
270
  classob = @args[:module].const_get(classname)
271
271
  end
272
-
272
+
273
273
  pass_arg = Knj::Hash_methods.new(:ob => self, :db => @args[:db])
274
274
  classob.load_columns(pass_arg) if classob.respond_to?(:load_columns)
275
275
  classob.datarow_init(pass_arg) if classob.respond_to?(:datarow_init)
276
276
  end
277
-
277
+
278
278
  #Returns the instance of classname, but only if it already exists.
279
279
  def get_if_cached(classname, id)
280
280
  classname = classname.to_sym
281
281
  id = id.to_i
282
-
283
- if wref_map = @objects[classname] and obj = wref_map.get!(id)
282
+
283
+ if wref_map = @objects[classname] and obj = wref_map.get(id)
284
284
  return obj
285
285
  end
286
-
286
+
287
287
  return nil
288
288
  end
289
-
289
+
290
290
  #Returns true if a row of the given classname and the ID exists. Will use ID-cache if set in arguments and spawned otherwise it will do an actual lookup.
291
291
  #===Examples
292
292
  # print "User 5 exists." if ob.exists?(:User, 5)
@@ -294,7 +294,7 @@ class Baza::ModelHandler
294
294
  #Make sure the given data are in the correct types.
295
295
  classname = classname.to_sym
296
296
  id = id.to_i
297
-
297
+
298
298
  #Check if ID-cache is enabled for that classname. Avoid SQL-lookup by using that.
299
299
  if @ids_cache_should.key?(classname)
300
300
  if @ids_cache[classname].key?(id)
@@ -303,15 +303,15 @@ class Baza::ModelHandler
303
303
  return false
304
304
  end
305
305
  end
306
-
306
+
307
307
  #If the object currently exists in cache, we dont have to do a lookup either.
308
- return true if @objects.key?(classname) and obj = @objects[classname].get!(id) and !obj.deleted?
309
-
308
+ return true if @objects.key?(classname) and obj = @objects[classname].get(id) and !obj.deleted?
309
+
310
310
  #Okay - no other options than to actually do a real lookup.
311
311
  begin
312
312
  table = @args[:module].const_get(classname).table
313
313
  row = @args[:db].single(table, {@args[:col_id] => id})
314
-
314
+
315
315
  if row
316
316
  return true
317
317
  else
@@ -321,13 +321,13 @@ class Baza::ModelHandler
321
321
  return false
322
322
  end
323
323
  end
324
-
324
+
325
325
  #Gets an object from the ID or the full data-hash in the database.
326
326
  #===Examples
327
327
  # inst = ob.get(:User, 5)
328
328
  def get(classname, data, args = nil)
329
329
  classname = classname.to_sym
330
-
330
+
331
331
  if data.is_a?(Integer) or data.is_a?(String) or data.is_a?(Fixnum)
332
332
  id = data.to_i
333
333
  elsif data.is_a?(Hash) and data.key?(@args[:col_id].to_sym)
@@ -337,29 +337,29 @@ class Baza::ModelHandler
337
337
  elsif
338
338
  raise ArgumentError, "Unknown data for class '#{classname}': '#{data.class.to_s}' (#{data})."
339
339
  end
340
-
340
+
341
341
  if @objects.key?(classname)
342
342
  case @args[:cache]
343
343
  when :weak
344
- if obj = @objects[classname].get!(id) and obj.id.to_i == id
344
+ if obj = @objects[classname].get(id) and obj.id.to_i == id
345
345
  return obj
346
346
  end
347
347
  else
348
348
  return @objects[classname][id] if @objects[classname].key?(id)
349
349
  end
350
350
  end
351
-
351
+
352
352
  self.requireclass(classname) if !@objects.key?(classname)
353
-
353
+
354
354
  @locks[classname].synchronize do
355
355
  #Maybe the object got spawned while we waited for the lock? If so we shouldnt spawn another instance.
356
- if @args[:cache] == :weak and obj = @objects[classname].get!(id) and obj.id.to_i == id
356
+ if @args[:cache] == :weak and obj = @objects[classname].get(id) and obj.id.to_i == id
357
357
  return obj
358
358
  end
359
-
359
+
360
360
  #Spawn object.
361
361
  obj = @args[:module].const_get(classname).new(data, args)
362
-
362
+
363
363
  #Save object in cache.
364
364
  case @args[:cache]
365
365
  when :none
@@ -369,10 +369,10 @@ class Baza::ModelHandler
369
369
  return obj
370
370
  end
371
371
  end
372
-
372
+
373
373
  raise "Unexpected run?"
374
374
  end
375
-
375
+
376
376
  #Same as normal get but returns false if not found instead of raising error.
377
377
  def get!(*args, &block)
378
378
  begin
@@ -381,7 +381,7 @@ class Baza::ModelHandler
381
381
  return false
382
382
  end
383
383
  end
384
-
384
+
385
385
  def object_finalizer(id)
386
386
  classname = @objects_idclass[id]
387
387
  if classname
@@ -389,30 +389,30 @@ class Baza::ModelHandler
389
389
  @objects_idclass.delete(id)
390
390
  end
391
391
  end
392
-
392
+
393
393
  #Returns the first object found from the given arguments. Also automatically limits the results to 1.
394
394
  def get_by(classname, args = {})
395
395
  classname = classname.to_sym
396
396
  self.requireclass(classname)
397
397
  classob = @args[:module].const_get(classname)
398
-
398
+
399
399
  raise "list-function has not been implemented for '#{classname}'." if !classob.respond_to?(:list)
400
-
400
+
401
401
  args["limit"] = 1
402
402
  self.list(classname, args) do |obj|
403
403
  return obj
404
404
  end
405
-
405
+
406
406
  return false
407
407
  end
408
-
408
+
409
409
  #Searches for an object with the given data. If not found it creates it. Returns the found or created object in the end.
410
410
  def get_or_add(classname, data, args = nil)
411
411
  obj = self.get_by(classname, data.clone)
412
412
  obj = self.add(classname, data) if !obj
413
413
  return obj
414
414
  end
415
-
415
+
416
416
  def get_try(obj, col_name, obj_name = nil)
417
417
  if !obj_name
418
418
  if match = col_name.to_s.match(/^(.+)_id$/)
@@ -421,17 +421,17 @@ class Baza::ModelHandler
421
421
  raise "Could not figure out objectname for: #{col_name}."
422
422
  end
423
423
  end
424
-
424
+
425
425
  id_data = obj[col_name].to_i
426
426
  return false if id_data.to_i <= 0
427
-
427
+
428
428
  begin
429
429
  return self.get(obj_name, id_data)
430
430
  rescue Errno::ENOENT
431
431
  return false
432
432
  end
433
433
  end
434
-
434
+
435
435
  #Returns an array-list of objects. If given a block the block will be called for each element and memory will be spared if running weak-link-mode.
436
436
  #===Examples
437
437
  # ob.list(:User) do |user|
@@ -442,10 +442,10 @@ class Baza::ModelHandler
442
442
  classname = classname.to_sym
443
443
  self.requireclass(classname)
444
444
  classob = @args[:module].const_get(classname)
445
-
445
+
446
446
  raise "list-function has not been implemented for '#{classname}'." if !classob.respond_to?("list")
447
447
  ret = classob.list(Knj::Hash_methods.new(:args => args, :ob => self, :db => @args[:db]), &block)
448
-
448
+
449
449
  #If 'ret' is an array and a block is given then the list-method didnt return blocks. We emulate it instead with the following code.
450
450
  if block and ret.is_a?(Array)
451
451
  ret.each do |obj|
@@ -460,20 +460,20 @@ class Baza::ModelHandler
460
460
  return ret
461
461
  end
462
462
  end
463
-
463
+
464
464
  #Yields every object that is missing certain required objects (based on 'has_many' required-argument).
465
465
  def list_invalid_required(args, &block)
466
466
  enum = Enumerator.new do |yielder|
467
467
  classname = args[:class]
468
468
  classob = @args[:module].const_get(classname)
469
469
  required_data = classob.required_data
470
-
470
+
471
471
  if required_data and !required_data.empty?
472
472
  required_data.each do |req_data|
473
473
  self.list(args[:class], :cloned_ubuf => true) do |obj|
474
474
  puts "Checking #{obj.classname}(#{obj.id}) for required #{req_data[:class]}." if args[:debug]
475
475
  id = obj[req_data[:col]]
476
-
476
+
477
477
  begin
478
478
  raise Errno::ENOENT if !id
479
479
  obj_req = self.get(req_data[:class], id)
@@ -484,23 +484,23 @@ class Baza::ModelHandler
484
484
  end
485
485
  end
486
486
  end
487
-
487
+
488
488
  return Knj.handle_return(:enum => enum, :block => block)
489
489
  end
490
-
490
+
491
491
  #Returns select-options-HTML for inserting into a HTML-select-element.
492
492
  def list_opts(classname, args = {})
493
493
  Knj::ArrayExt.hash_sym(args)
494
494
  classname = classname.to_sym
495
-
495
+
496
496
  if args[:list_args].is_a?(Hash)
497
497
  list_args = args[:list_args]
498
498
  else
499
499
  list_args = {}
500
500
  end
501
-
501
+
502
502
  html = ""
503
-
503
+
504
504
  if args[:addnew] or args[:add]
505
505
  html << "<option"
506
506
  html << " selected=\"selected\"" if !args[:selected]
@@ -510,21 +510,21 @@ class Baza::ModelHandler
510
510
  html << " selected=\"selected\"" if !args[:selected]
511
511
  html << " value=\"\">#{_("None")}</option>"
512
512
  end
513
-
513
+
514
514
  self.list(classname, args[:list_args]) do |object|
515
515
  html << "<option value=\"#{object.id.html}\""
516
-
516
+
517
517
  selected = false
518
518
  if args[:selected].is_a?(Array) and args[:selected].index(object) != nil
519
519
  selected = true
520
520
  elsif args[:selected] and args[:selected].respond_to?("is_knj?") and args[:selected].id.to_s == object.id.to_s
521
521
  selected = true
522
522
  end
523
-
523
+
524
524
  html << " selected=\"selected\"" if selected
525
-
525
+
526
526
  obj_methods = object.class.instance_methods(false)
527
-
527
+
528
528
  begin
529
529
  if obj_methods.index("name") != nil or obj_methods.index(:name) != nil
530
530
  objhtml = object.name.html
@@ -532,7 +532,7 @@ class Baza::ModelHandler
532
532
  objhtml = object.title.html
533
533
  elsif object.respond_to?(:data)
534
534
  obj_data = object.data
535
-
535
+
536
536
  if obj_data.key?(:name)
537
537
  objhtml = obj_data[:name]
538
538
  elsif obj_data.key?(:title)
@@ -541,34 +541,34 @@ class Baza::ModelHandler
541
541
  else
542
542
  objhtml = ""
543
543
  end
544
-
544
+
545
545
  raise "Could not figure out which name-method to call?" if !objhtml
546
546
  html << ">#{objhtml}</option>"
547
547
  rescue => e
548
548
  html << ">[#{object.class.name}: #{e.message}]</option>"
549
549
  end
550
550
  end
551
-
551
+
552
552
  return html
553
553
  end
554
-
554
+
555
555
  #Returns a hash which can be used to generate HTML-select-elements.
556
556
  def list_optshash(classname, args = {})
557
557
  Knj::ArrayExt.hash_sym(args)
558
558
  classname = classname.to_sym
559
-
559
+
560
560
  if args[:list_args].is_a?(Hash)
561
561
  list_args = args[:list_args]
562
562
  else
563
563
  list_args = {}
564
564
  end
565
-
565
+
566
566
  if RUBY_VERSION[0..2] == 1.8 and Php4r.class_exists("Dictionary")
567
567
  list = Dictionary.new
568
568
  else
569
569
  list = {}
570
570
  end
571
-
571
+
572
572
  if args[:addnew] or args[:add]
573
573
  list["0"] = _("Add new")
574
574
  elsif args[:choose]
@@ -578,7 +578,7 @@ class Baza::ModelHandler
578
578
  elsif args[:none]
579
579
  list["0"] = _("None")
580
580
  end
581
-
581
+
582
582
  self.list(classname, args[:list_args]) do |object|
583
583
  if object.respond_to?(:name)
584
584
  list[object.id] = object.name
@@ -588,16 +588,16 @@ class Baza::ModelHandler
588
588
  raise "Object of class '#{object.class.name}' doesnt support 'name' or 'title."
589
589
  end
590
590
  end
591
-
591
+
592
592
  return list
593
593
  end
594
-
594
+
595
595
  #Returns a list of a specific object by running specific SQL against the database.
596
596
  def list_bysql(classname, sql, args = nil, &block)
597
597
  classname = classname.to_sym
598
598
  ret = [] if !block
599
599
  qargs = nil
600
-
600
+
601
601
  if args
602
602
  args.each do |key, val|
603
603
  case key
@@ -608,19 +608,19 @@ class Baza::ModelHandler
608
608
  end
609
609
  end
610
610
  end
611
-
611
+
612
612
  if @args[:array_enum]
613
613
  enum = Enumerator.new do |yielder|
614
614
  @args[:db].q(sql, qargs) do |d_obs|
615
615
  yielder << self.get(classname, d_obs)
616
616
  end
617
617
  end
618
-
618
+
619
619
  if block
620
620
  enum.each(&block)
621
621
  return nil
622
622
  else
623
- return Array_enumerator.new(enum)
623
+ return ArrayEnumerator.new(enum)
624
624
  end
625
625
  else
626
626
  @args[:db].q(sql, qargs) do |d_obs|
@@ -630,7 +630,7 @@ class Baza::ModelHandler
630
630
  ret << self.get(classname, d_obs)
631
631
  end
632
632
  end
633
-
633
+
634
634
  if !block
635
635
  return ret
636
636
  else
@@ -638,7 +638,7 @@ class Baza::ModelHandler
638
638
  end
639
639
  end
640
640
  end
641
-
641
+
642
642
  #Add a new object to the database and to the cache.
643
643
  #===Examples
644
644
  # obj = ob.add(:User, {:username => "User 1"})
@@ -646,7 +646,7 @@ class Baza::ModelHandler
646
646
  raise "data-variable was not a hash: '#{data.class.name}'." if !data.is_a?(Hash)
647
647
  classname = classname.to_sym
648
648
  self.requireclass(classname)
649
-
649
+
650
650
  if @args[:custom]
651
651
  classobj = @args[:module].const_get(classname)
652
652
  retob = classobj.add(Knj::Hash_methods.new(
@@ -655,43 +655,43 @@ class Baza::ModelHandler
655
655
  ))
656
656
  else
657
657
  classobj = @args[:module].const_get(classname)
658
-
658
+
659
659
  #Run the class 'add'-method to check various data.
660
660
  classobj.add(Knj::Hash_methods.new(:ob => self, :db => @args[:db], :data => data)) if classobj.respond_to?(:add)
661
-
661
+
662
662
  #Check if various required data is given. If not then raise an error telling about it.
663
663
  required_data = classobj.required_data
664
664
  required_data.each do |req_data|
665
665
  raise "No '#{req_data[:class]}' given by the data '#{req_data[:col]}'." if !data.key?(req_data[:col])
666
666
  raise "The '#{req_data[:class]}' by ID '#{data[req_data[:col]]}' could not be found with the data '#{req_data[:col]}'." if !self.exists?(req_data[:class], data[req_data[:col]])
667
667
  end
668
-
668
+
669
669
  #If 'skip_ret' is given, then the ID wont be looked up and the object wont be spawned. Be aware the connected events wont be executed either. In return it will go a lot faster.
670
670
  if args and args[:skip_ret] and !@ids_cache_should.key?(classname)
671
671
  ins_args = nil
672
672
  else
673
673
  ins_args = {:return_id => true}
674
674
  end
675
-
675
+
676
676
  #Insert and (maybe?) get ID.
677
677
  ins_id = @args[:db].insert(classobj.table, data, ins_args).to_i
678
-
678
+
679
679
  #Add ID to ID-cache if ID-cache is active for that classname.
680
680
  @ids_cache[classname][ins_id] = true if ins_id != 0 and @ids_cache_should.key?(classname)
681
-
681
+
682
682
  #Skip the rest if we are told not to return result.
683
683
  return nil if args and args[:skip_ret]
684
-
684
+
685
685
  #Spawn the object.
686
686
  retob = self.get(classname, ins_id, {:skip_reload => true})
687
687
  end
688
-
688
+
689
689
  self.call("object" => retob, "signal" => "add")
690
690
  retob.send(:add_after, {}) if retob.respond_to?(:add_after)
691
-
691
+
692
692
  return retob
693
693
  end
694
-
694
+
695
695
  #Adds several objects to the database at once. This is faster than adding every single object by itself, since this will do multi-inserts if supported by the database.
696
696
  #===Examples
697
697
  # ob.adds(:User, [{:username => "User 1"}, {:username => "User 2"})
@@ -705,31 +705,31 @@ class Baza::ModelHandler
705
705
  ))
706
706
  end
707
707
  end
708
-
708
+
709
709
  db.insert_multi(classname, datas)
710
710
  self.cache_ids(classname)
711
711
  end
712
-
712
+
713
713
  #Calls a static method on a class. Passes the d-variable which contains the Objects-object, database-reference and more...
714
714
  def static(class_name, method_name, *args, &block)
715
715
  class_name = class_name
716
716
  method_name = method_name
717
-
717
+
718
718
  self.requireclass(class_name)
719
719
  class_obj = @args[:module].const_get(class_name)
720
-
720
+
721
721
  #Sometimes this raises the exception but actually responds to the class? Therefore commented out. - knj
722
722
  #raise "The class '#{class_obj.name}' has no such method: '#{method_name}' (#{class_obj.methods.sort.join(", ")})." if !class_obj.respond_to?(method_name)
723
-
723
+
724
724
  pass_args = [Knj::Hash_methods.new(:ob => self, :db => self.db)]
725
-
725
+
726
726
  args.each do |arg|
727
727
  pass_args << arg
728
728
  end
729
-
729
+
730
730
  class_obj.send(method_name, *pass_args, &block)
731
731
  end
732
-
732
+
733
733
  #Unset object. Do this if you are sure, that there are no more references left. This will be done automatically when deleting it.
734
734
  def unset(object)
735
735
  if object.is_a?(Array)
@@ -738,32 +738,32 @@ class Baza::ModelHandler
738
738
  end
739
739
  return nil
740
740
  end
741
-
741
+
742
742
  classname = object.class.name
743
-
743
+
744
744
  if @args[:module]
745
745
  classname = classname.gsub(@args[:module].name + "::", "")
746
746
  end
747
-
747
+
748
748
  classname = classname.to_sym
749
749
  @objects[classname].delete(object.id.to_i)
750
750
  end
751
-
751
+
752
752
  def unset_class(classname)
753
753
  if classname.is_a?(Array)
754
754
  classname.each do |classn|
755
755
  self.unset_class(classn)
756
756
  end
757
-
757
+
758
758
  return false
759
759
  end
760
-
760
+
761
761
  classname = classname.to_sym
762
-
762
+
763
763
  return false if !@objects.key?(classname)
764
764
  @objects.delete(classname)
765
765
  end
766
-
766
+
767
767
  #Delete an object. Both from the database and from the cache.
768
768
  #===Examples
769
769
  # user = ob.get(:User, 1)
@@ -772,12 +772,12 @@ class Baza::ModelHandler
772
772
  #Return false if the object has already been deleted.
773
773
  return false if object.deleted?
774
774
  classname = object.class.classname.to_sym
775
-
775
+
776
776
  self.call("object" => object, "signal" => "delete_before")
777
777
  self.unset(object)
778
778
  obj_id = object.id
779
779
  object.delete if object.respond_to?(:delete)
780
-
780
+
781
781
  #If autodelete is set by 'has_many'-method, go through it and delete the various objects first.
782
782
  if autodelete_data = object.class.autodelete_data
783
783
  autodelete_data.each do |adel_data|
@@ -786,7 +786,7 @@ class Baza::ModelHandler
786
786
  end
787
787
  end
788
788
  end
789
-
789
+
790
790
  #If depend is set by 'has_many'-method, check if any objects exists and raise error if so.
791
791
  if dep_datas = object.class.depending_data
792
792
  dep_datas.each do |dep_data|
@@ -795,7 +795,7 @@ class Baza::ModelHandler
795
795
  end
796
796
  end
797
797
  end
798
-
798
+
799
799
  #If autozero is set by 'has_many'-method, check if any objects exists and set the ID to zero.
800
800
  if autozero_datas = object.class.autozero_data
801
801
  autozero_datas.each do |zero_data|
@@ -804,7 +804,7 @@ class Baza::ModelHandler
804
804
  end
805
805
  end
806
806
  end
807
-
807
+
808
808
  #Delete any translations that has been set on the object by 'has_translation'-method.
809
809
  if object.class.translations
810
810
  begin
@@ -813,41 +813,41 @@ class Baza::ModelHandler
813
813
  _kas.trans_del(object)
814
814
  end
815
815
  end
816
-
817
-
816
+
817
+
818
818
  #If a buffer is given in arguments, then use that to delete the object.
819
819
  if args and buffer = args[:db_buffer]
820
820
  buffer.delete(object.table, {:id => obj_id})
821
821
  else
822
822
  @args[:db].delete(object.table, {:id => obj_id})
823
823
  end
824
-
824
+
825
825
  @ids_cache[classname].delete(obj_id.to_i) if @ids_cache_should.key?(classname)
826
826
  self.call("object" => object, "signal" => "delete")
827
827
  object.destroy
828
828
  return nil
829
829
  end
830
-
830
+
831
831
  #Deletes several objects as one. If running datarow-mode it checks all objects before it starts to actually delete them. Its faster than deleting every single object by itself...
832
832
  def deletes(objs)
833
833
  tables = {}
834
-
834
+
835
835
  begin
836
836
  objs.each do |obj|
837
837
  next if obj.deleted?
838
838
  tablen = obj.table
839
-
839
+
840
840
  if !tables.key?(tablen)
841
841
  tables[tablen] = []
842
842
  end
843
-
843
+
844
844
  tables[tablen] << obj.id
845
845
  obj.delete if obj.respond_to?(:delete)
846
-
846
+
847
847
  #Remove from ID-cache.
848
848
  classname = obj.class.classname.to_sym
849
849
  @ids_cache[classname].delete(obj.id.to_i) if @ids_cache_should.key?(classname)
850
-
850
+
851
851
  #Unset any data on the object, so it seems deleted.
852
852
  obj.destroy
853
853
  end
@@ -860,7 +860,7 @@ class Baza::ModelHandler
860
860
  end
861
861
  end
862
862
  end
863
-
863
+
864
864
  #Deletes all objects with the given IDs 500 at a time to prevent memory exhaustion or timeout.
865
865
  #===Examples
866
866
  # ob.delete_ids(:class => :Person, :ids => [1, 3, 5, 6, 7, 8, 9])
@@ -869,20 +869,20 @@ class Baza::ModelHandler
869
869
  objs = self.list(args[:class], "id" => ids)
870
870
  self.deletes(objs)
871
871
  end
872
-
872
+
873
873
  return nil
874
874
  end
875
-
875
+
876
876
  #Try to clean up objects by unsetting everything, start the garbagecollector, get all the remaining objects via ObjectSpace and set them again. Some (if not all) should be cleaned up and our cache should still be safe... dirty but works.
877
877
  def clean(classn)
878
878
  if classn.is_a?(Array)
879
879
  classn.each do |realclassn|
880
880
  self.clean(realclassn)
881
881
  end
882
-
882
+
883
883
  return nil
884
884
  end
885
-
885
+
886
886
  if @args[:cache] == :weak
887
887
  @objects[classn].clean
888
888
  elsif @args[:cache] == :none
@@ -891,7 +891,7 @@ class Baza::ModelHandler
891
891
  return false if !@objects.key?(classn)
892
892
  @objects[classn] = {}
893
893
  GC.start
894
-
894
+
895
895
  @objects.keys.each do |classn|
896
896
  data = @objects[classn]
897
897
  classobj = @args[:module].const_get(classn)
@@ -903,19 +903,19 @@ class Baza::ModelHandler
903
903
  #Object has been unset - skip it.
904
904
  next
905
905
  end
906
-
906
+
907
907
  raise e
908
908
  end
909
909
  end
910
910
  end
911
911
  end
912
912
  end
913
-
913
+
914
914
  #Erases the whole cache and regenerates it from ObjectSpace if not running weak-link-caching. If running weaklink-caching then it will only removes the dead links.
915
915
  def clean_all
916
916
  self.clean(@objects.keys)
917
917
  end
918
-
918
+
919
919
  def classes_loaded
920
920
  return @objects.keys
921
921
  end