baza 0.0.15 → 0.0.16
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile +14 -7
- data/Gemfile.lock +19 -14
- data/README.md +1 -1
- data/VERSION +1 -1
- data/baza.gemspec +24 -21
- data/include/cloner.rb +18 -0
- data/include/column.rb +9 -0
- data/include/db.rb +2 -2
- data/include/drivers/active_record/active_record.rb +14 -4
- data/include/drivers/mysql/mysql.rb +56 -36
- data/include/drivers/mysql/mysql_column.rb +1 -1
- data/include/drivers/mysql/mysql_index.rb +2 -10
- data/include/drivers/mysql/mysql_table.rb +11 -11
- data/include/drivers/mysql/mysql_tables.rb +5 -7
- data/include/drivers/sqlite3/sqlite3.rb +43 -23
- data/include/drivers/sqlite3/sqlite3_column.rb +1 -1
- data/include/drivers/sqlite3/sqlite3_index.rb +5 -8
- data/include/drivers/sqlite3/sqlite3_result_java.rb +1 -1
- data/include/drivers/sqlite3/sqlite3_table.rb +17 -18
- data/include/drivers/sqlite3/sqlite3_tables.rb +4 -7
- data/include/index.rb +9 -0
- data/include/model.rb +1 -1
- data/include/model_handler.rb +162 -162
- data/include/table.rb +9 -0
- data/lib/baza.rb +19 -1
- data/shippable.yml +4 -1
- data/spec/include/cloner_spec.rb +10 -0
- data/spec/info_active_record.rb +20 -8
- data/spec/info_active_record_shippable.rb +18 -7
- data/spec/info_mysql_shippable.rb +16 -7
- data/spec/info_sqlite3.rb +1 -1
- data/spec/support/driver_indexes_collection.rb +16 -2
- metadata +28 -25
- data/include/drivers/sqlite3/libknjdb_java_sqlite3.rb +0 -78
- data/include/drivers/sqlite3/libknjdb_sqlite3_ironruby.rb +0 -69
data/include/model_handler.rb
CHANGED
@@ -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] =
|
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
|
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
|
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
|
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
|
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
|
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
|