baza 0.0.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.
- data/.document +5 -0
- data/.rspec +1 -0
- data/Gemfile +18 -0
- data/Gemfile.lock +55 -0
- data/LICENSE.txt +20 -0
- data/README.rdoc +19 -0
- data/Rakefile +49 -0
- data/VERSION +1 -0
- data/include/db.rb +784 -0
- data/include/dbtime.rb +35 -0
- data/include/drivers/.DS_Store +0 -0
- data/include/drivers/mysql/mysql.rb +604 -0
- data/include/drivers/mysql/mysql_columns.rb +155 -0
- data/include/drivers/mysql/mysql_indexes.rb +69 -0
- data/include/drivers/mysql/mysql_sqlspecs.rb +5 -0
- data/include/drivers/mysql/mysql_tables.rb +443 -0
- data/include/drivers/sqlite3/libknjdb_java_sqlite3.rb +83 -0
- data/include/drivers/sqlite3/libknjdb_sqlite3_ironruby.rb +69 -0
- data/include/drivers/sqlite3/sqlite3.rb +184 -0
- data/include/drivers/sqlite3/sqlite3_columns.rb +177 -0
- data/include/drivers/sqlite3/sqlite3_indexes.rb +29 -0
- data/include/drivers/sqlite3/sqlite3_sqlspecs.rb +5 -0
- data/include/drivers/sqlite3/sqlite3_tables.rb +449 -0
- data/include/dump.rb +122 -0
- data/include/idquery.rb +109 -0
- data/include/model.rb +873 -0
- data/include/model_custom.rb +153 -0
- data/include/model_handler.rb +957 -0
- data/include/model_handler_sqlhelper.rb +499 -0
- data/include/query_buffer.rb +87 -0
- data/include/revision.rb +342 -0
- data/include/row.rb +153 -0
- data/include/sqlspecs.rb +5 -0
- data/lib/baza.rb +8 -0
- data/spec/baza_spec.rb +286 -0
- data/spec/db_spec_encoding_test_file.txt +1 -0
- data/spec/spec_helper.rb +12 -0
- metadata +215 -0
@@ -0,0 +1,87 @@
|
|
1
|
+
#This class buffers a lot of queries and flushes them out via transactions.
|
2
|
+
class Baza::QueryBuffer
|
3
|
+
#Constructor. Takes arguments to be used and a block.
|
4
|
+
def initialize(args)
|
5
|
+
@args = args
|
6
|
+
@queries = []
|
7
|
+
@inserts = {}
|
8
|
+
@queries_count = 0
|
9
|
+
@debug = @args[:debug]
|
10
|
+
@lock = Mutex.new
|
11
|
+
|
12
|
+
STDOUT.puts "Query buffer started." if @debug
|
13
|
+
|
14
|
+
if block_given?
|
15
|
+
begin
|
16
|
+
yield(self)
|
17
|
+
ensure
|
18
|
+
self.flush
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
#Adds a query to the buffer.
|
24
|
+
def query(str)
|
25
|
+
@lock.synchronize do
|
26
|
+
STDOUT.print "Adding to buffer: #{str}\n" if @debug
|
27
|
+
@queries << str
|
28
|
+
@queries_count += 1
|
29
|
+
end
|
30
|
+
|
31
|
+
self.flush if @queries_count >= 1000
|
32
|
+
return nil
|
33
|
+
end
|
34
|
+
|
35
|
+
#Delete as on a normal Baza::Db.
|
36
|
+
#===Examples
|
37
|
+
# db.q_buffer do |buffer|
|
38
|
+
# buffer.delete(:users, {:id => 5})
|
39
|
+
# end
|
40
|
+
def delete(table, where)
|
41
|
+
STDOUT.puts "Delete called on table #{table} with arguments: '#{where}'." if @debug
|
42
|
+
self.query(@args[:db].delete(table, where, :return_sql => true))
|
43
|
+
return nil
|
44
|
+
end
|
45
|
+
|
46
|
+
#Plans to inset a hash into a table. It will only be inserted when flush is called.
|
47
|
+
#===Examples
|
48
|
+
# db.q_buffer do |buffer|
|
49
|
+
# buffer.insert(:users, {:name => "John Doe"})
|
50
|
+
# end
|
51
|
+
def insert(table, data)
|
52
|
+
@lock.synchronize do
|
53
|
+
@inserts[table] = [] if !@inserts.key?(table)
|
54
|
+
@inserts[table] << data
|
55
|
+
@queries_count += 1
|
56
|
+
end
|
57
|
+
|
58
|
+
self.flush if @queries_count >= 1000
|
59
|
+
return nil
|
60
|
+
end
|
61
|
+
|
62
|
+
#Flushes all queries out in a transaction. This will automatically be called for every 1000 queries.
|
63
|
+
def flush
|
64
|
+
return nil if @queries_count <= 0
|
65
|
+
|
66
|
+
@lock.synchronize do
|
67
|
+
@args[:db].transaction do
|
68
|
+
@queries.shift(1000).each do |str|
|
69
|
+
STDOUT.print "Executing via buffer: #{str}\n" if @debug
|
70
|
+
@args[:db].q(str)
|
71
|
+
end
|
72
|
+
|
73
|
+
@inserts.each do |table, datas_arr|
|
74
|
+
while !datas_arr.empty?
|
75
|
+
datas_chunk_arr = datas_arr.shift(1000)
|
76
|
+
@args[:db].insert_multi(table, datas_chunk_arr)
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
@inserts.clear
|
82
|
+
@queries_count = 0
|
83
|
+
end
|
84
|
+
|
85
|
+
return nil
|
86
|
+
end
|
87
|
+
end
|
data/include/revision.rb
ADDED
@@ -0,0 +1,342 @@
|
|
1
|
+
#This class takes a database-schema from a hash and runs it against the database. It then checks that the database matches the given schema.
|
2
|
+
#
|
3
|
+
#===Examples
|
4
|
+
# db = Baza::Db.new(:type => "sqlite3", :path => "test_db.sqlite3")
|
5
|
+
# schema = {
|
6
|
+
# "tables" => {
|
7
|
+
# "User" => {
|
8
|
+
# "columns" => [
|
9
|
+
# {"name" => "id", "type" => "int", "autoincr" => true, "primarykey" => true},
|
10
|
+
# {"name" => "name", "type" => "varchar"},
|
11
|
+
# {"name" => "lastname", "type" => "varchar"}
|
12
|
+
# ],
|
13
|
+
# "indexes" => [
|
14
|
+
# "name",
|
15
|
+
# {"name" => "lastname", "columns" => ["lastname"]}
|
16
|
+
# ],
|
17
|
+
# "on_create_after" => proc{|d|
|
18
|
+
# d["db"].insert("User", {"name" => "John", "lastname" => "Doe"})
|
19
|
+
# }
|
20
|
+
# }
|
21
|
+
# }
|
22
|
+
# }
|
23
|
+
#
|
24
|
+
# rev = Baza::Revision.new
|
25
|
+
# rev.init_db("db" => db, "schema" => schema)
|
26
|
+
class Baza::Revision
|
27
|
+
def initialize(args = {})
|
28
|
+
@args = args
|
29
|
+
end
|
30
|
+
|
31
|
+
#This initializes a database-structure and content based on a schema-hash.
|
32
|
+
#===Examples
|
33
|
+
# dbrev = Baza::Revision.new
|
34
|
+
# dbrev.init_db("db" => db_obj, "schema" => schema_hash)
|
35
|
+
def init_db(args)
|
36
|
+
schema = args["schema"]
|
37
|
+
db = args["db"]
|
38
|
+
|
39
|
+
#Check for normal bugs and raise apropiate error.
|
40
|
+
raise "'schema' argument was not a Hash: '#{schema.class.name}'." if !schema.is_a?(Hash)
|
41
|
+
raise "':return_keys' is not 'symbols' - Knjdbrevision will not work without it." if db.opts[:return_keys] != "symbols"
|
42
|
+
raise "No tables given." if !schema.has_key?("tables")
|
43
|
+
|
44
|
+
#Cache tables to avoid constant reloading.
|
45
|
+
if !args.key?("tables_cache") or args["tables_cache"]
|
46
|
+
print "Caching tables-list.\n" if args["debug"]
|
47
|
+
tables = db.tables.list
|
48
|
+
else
|
49
|
+
print "Skipping tables-cache.\n" if args["debug"]
|
50
|
+
end
|
51
|
+
|
52
|
+
schema["tables"].each do |table_name, table_data|
|
53
|
+
begin
|
54
|
+
begin
|
55
|
+
table_obj = db.tables[table_name]
|
56
|
+
|
57
|
+
#Cache indexes- and column-objects to avoid constant reloading.
|
58
|
+
cols = table_obj.columns
|
59
|
+
indexes = table_obj.indexes
|
60
|
+
|
61
|
+
if table_data["columns"]
|
62
|
+
first_col = true
|
63
|
+
table_data["columns"].each do |col_data|
|
64
|
+
begin
|
65
|
+
col_obj = table_obj.column(col_data["name"])
|
66
|
+
col_str = "#{table_name}.#{col_obj.name}"
|
67
|
+
type = col_data["type"].to_s
|
68
|
+
dochange = false
|
69
|
+
|
70
|
+
if !first_col and !col_data["after"]
|
71
|
+
#Try to find out the previous column - if so we can set "after" which makes the column being created in the right order as defined.
|
72
|
+
if !col_data.has_key?("after")
|
73
|
+
prev_no = table_data["columns"].index(col_data)
|
74
|
+
if prev_no != nil and prev_no != 0
|
75
|
+
prev_no = prev_no - 1
|
76
|
+
prev_col_data = table_data["columns"][prev_no]
|
77
|
+
col_data["after"] = prev_col_data["name"]
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
actual_after = nil
|
82
|
+
set_next = false
|
83
|
+
cols.each do |col_name, col_iter|
|
84
|
+
if col_iter.name == col_obj.name
|
85
|
+
break
|
86
|
+
else
|
87
|
+
actual_after = col_iter.name
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
if actual_after != col_data["after"]
|
92
|
+
print "Changing '#{col_str}' after from '#{actual_after}' to '#{col_data["after"]}'.\n" if args["debug"]
|
93
|
+
dochange = true
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
#BUGFIX: When using SQLite3 the primary-column or a autoincr-column may never change type from int... This will break it!
|
98
|
+
if db.opts[:type] == "sqlite3" and col_obj.type.to_s == "int" and (col_data["primarykey"] or col_data["autoincr"]) and db.int_types.index(col_data["type"].to_s)
|
99
|
+
type = "int"
|
100
|
+
end
|
101
|
+
|
102
|
+
if type and col_obj.type.to_s != type
|
103
|
+
print "Type mismatch on #{col_str}: #{col_data["type"]}, #{col_obj.type}\n" if args["debug"]
|
104
|
+
dochange = true
|
105
|
+
end
|
106
|
+
|
107
|
+
if col_data.has_key?("primarykey") and col_obj.primarykey? != col_data["primarykey"]
|
108
|
+
print "Primary-key mismatch for #{col_str}: #{col_data["primarykey"]}, #{col_obj.primarykey?}\n" if args["debug"]
|
109
|
+
dochange = true
|
110
|
+
end
|
111
|
+
|
112
|
+
if col_data.has_key?("autoincr") and col_obj.autoincr? != col_data["autoincr"]
|
113
|
+
print "Auto-increment mismatch for #{col_str}: #{col_data["autoincr"]}, #{col_obj.autoincr?}\n" if args["debug"]
|
114
|
+
dochange = true
|
115
|
+
end
|
116
|
+
|
117
|
+
if col_data.has_key?("maxlength") and col_obj.maxlength.to_s != col_data["maxlength"].to_s
|
118
|
+
print "Maxlength mismatch on #{col_str}: #{col_data["maxlength"]}, #{col_obj.maxlength}\n" if args["debug"]
|
119
|
+
dochange = true
|
120
|
+
end
|
121
|
+
|
122
|
+
if col_data.has_key?("null") and col_obj.null?.to_s != col_data["null"].to_s
|
123
|
+
print "Null mismatch on #{col_str}: #{col_data["null"]}, #{col_obj.null?}\n" if args["debug"]
|
124
|
+
dochange = true
|
125
|
+
end
|
126
|
+
|
127
|
+
if col_data.has_key?("default") and col_obj.default.to_s != col_data["default"].to_s
|
128
|
+
print "Default mismatch on #{col_str}: #{col_data["default"]}, #{col_obj.default}\n" if args["debug"]
|
129
|
+
dochange = true
|
130
|
+
end
|
131
|
+
|
132
|
+
if col_data.has_key?("comment") and col_obj.respond_to?(:comment) and col_obj.comment.to_s != col_data["comment"].to_s
|
133
|
+
print "Comment mismatch on #{col_str}: #{col_data["comment"]}, #{col_obj.comment}\n" if args["debug"]
|
134
|
+
dochange = true
|
135
|
+
end
|
136
|
+
|
137
|
+
if col_data.is_a?(Hash) and col_data["on_before_alter"]
|
138
|
+
callback_data = col_data["on_before_alter"].call("db" => db, "table" => table_obj, "col" => col_obj, "col_data" => col_data)
|
139
|
+
if callback_data and callback_data["action"]
|
140
|
+
if callback_data["action"] == "retry"
|
141
|
+
raise Knj::Errors::Retry
|
142
|
+
end
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
if dochange
|
147
|
+
col_obj.change(col_data)
|
148
|
+
|
149
|
+
#Change has been made - update cache.
|
150
|
+
cols = table_obj.columns
|
151
|
+
end
|
152
|
+
|
153
|
+
first_col = false
|
154
|
+
rescue Errno::ENOENT => e
|
155
|
+
print "Column not found: #{table_obj.name}.#{col_data["name"]}.\n" if args["debug"]
|
156
|
+
|
157
|
+
if col_data.has_key?("renames")
|
158
|
+
raise "'renames' was not an array for column '#{table_obj.name}.#{col_data["name"]}'." if !col_data["renames"].is_a?(Array)
|
159
|
+
|
160
|
+
rename_found = false
|
161
|
+
col_data["renames"].each do |col_name|
|
162
|
+
begin
|
163
|
+
col_rename = table_obj.column(col_name)
|
164
|
+
rescue Errno::ENOENT => e
|
165
|
+
next
|
166
|
+
end
|
167
|
+
|
168
|
+
print "Rename #{table_obj.name}.#{col_name} to #{table_obj.name}.#{col_data["name"]}\n" if args["debug"]
|
169
|
+
if col_data.is_a?(Hash) and col_data["on_before_rename"]
|
170
|
+
col_data["on_before_rename"].call("db" => db, "table" => table_obj, "col" => col_rename, "col_data" => col_data)
|
171
|
+
end
|
172
|
+
|
173
|
+
col_rename.change(col_data)
|
174
|
+
|
175
|
+
#Change has been made - update cache.
|
176
|
+
cols = table_obj.columns
|
177
|
+
|
178
|
+
if col_data.is_a?(Hash) and col_data["on_after_rename"]
|
179
|
+
col_data["on_after_rename"].call("db" => db, "table" => table_obj, "col" => col_rename, "col_data" => col_data)
|
180
|
+
end
|
181
|
+
|
182
|
+
rename_found = true
|
183
|
+
break
|
184
|
+
end
|
185
|
+
|
186
|
+
retry if rename_found
|
187
|
+
end
|
188
|
+
|
189
|
+
oncreated = col_data["on_created"]
|
190
|
+
col_data.delete("on_created") if col_data["oncreated"]
|
191
|
+
col_obj = table_obj.create_columns([col_data])
|
192
|
+
|
193
|
+
#Change has been made - update cache.
|
194
|
+
cols = table_obj.columns
|
195
|
+
|
196
|
+
oncreated.call("db" => db, "table" => table_obj) if oncreated
|
197
|
+
end
|
198
|
+
end
|
199
|
+
end
|
200
|
+
|
201
|
+
if table_data["columns_remove"]
|
202
|
+
table_data["columns_remove"].each do |column_name, column_data|
|
203
|
+
begin
|
204
|
+
col_obj = table_obj.column(column_name)
|
205
|
+
rescue Errno::ENOENT => e
|
206
|
+
next
|
207
|
+
end
|
208
|
+
|
209
|
+
column_data["callback"].call if column_data.is_a?(Hash) and column_data["callback"]
|
210
|
+
col_obj.drop
|
211
|
+
end
|
212
|
+
end
|
213
|
+
|
214
|
+
if table_data["indexes"]
|
215
|
+
table_data["indexes"].each do |index_data|
|
216
|
+
if index_data.is_a?(String)
|
217
|
+
index_data = {"name" => index_data, "columns" => [index_data]}
|
218
|
+
end
|
219
|
+
|
220
|
+
begin
|
221
|
+
index_obj = table_obj.index(index_data["name"])
|
222
|
+
|
223
|
+
rewrite_index = false
|
224
|
+
rewrite_index = true if index_data.key?("unique") and index_data["unique"] != index_obj.unique?
|
225
|
+
|
226
|
+
if rewrite_index
|
227
|
+
index_obj.drop
|
228
|
+
table_obj.create_indexes([index_data])
|
229
|
+
end
|
230
|
+
rescue Errno::ENOENT => e
|
231
|
+
table_obj.create_indexes([index_data])
|
232
|
+
end
|
233
|
+
end
|
234
|
+
end
|
235
|
+
|
236
|
+
if table_data["indexes_remove"]
|
237
|
+
table_data["indexes_remove"].each do |index_name, index_data|
|
238
|
+
begin
|
239
|
+
index_obj = table_obj.index(index_name)
|
240
|
+
rescue Errno::ENOENT => e
|
241
|
+
next
|
242
|
+
end
|
243
|
+
|
244
|
+
if index_data.is_a?(Hash) and index_data["callback"]
|
245
|
+
index_data["callback"].call if index_data["callback"]
|
246
|
+
end
|
247
|
+
|
248
|
+
index_obj.drop
|
249
|
+
end
|
250
|
+
end
|
251
|
+
|
252
|
+
rows_init("db" => db, "table" => table_obj, "rows" => table_data["rows"]) if table_data and table_data["rows"]
|
253
|
+
rescue Errno::ENOENT => e
|
254
|
+
if table_data.key?("renames")
|
255
|
+
table_data["renames"].each do |table_name_rename|
|
256
|
+
begin
|
257
|
+
table_rename = db.tables[table_name_rename.to_sym]
|
258
|
+
table_rename.rename(table_name)
|
259
|
+
raise Knj::Errors::Retry
|
260
|
+
rescue Errno::ENOENT
|
261
|
+
next
|
262
|
+
end
|
263
|
+
end
|
264
|
+
end
|
265
|
+
|
266
|
+
if !table_data.key?("columns")
|
267
|
+
print "Notice: Skipping creation of '#{table_name}' because no columns were given in hash.\n"
|
268
|
+
next
|
269
|
+
end
|
270
|
+
|
271
|
+
if table_data["on_create"]
|
272
|
+
table_data["on_create"].call("db" => db, "table_name" => table_name, "table_data" => table_data)
|
273
|
+
end
|
274
|
+
|
275
|
+
db.tables.create(table_name, table_data)
|
276
|
+
table_obj = db.tables[table_name.to_sym]
|
277
|
+
|
278
|
+
if table_data["on_create_after"]
|
279
|
+
table_data["on_create_after"].call("db" => db, "table_name" => table_name, "table_data" => table_data)
|
280
|
+
end
|
281
|
+
|
282
|
+
rows_init("db" => db, "table" => table_obj, "rows" => table_data["rows"]) if table_data["rows"]
|
283
|
+
end
|
284
|
+
rescue Knj::Errors::Retry
|
285
|
+
retry
|
286
|
+
end
|
287
|
+
end
|
288
|
+
|
289
|
+
if schema["tables_remove"]
|
290
|
+
schema["tables_remove"].each do |table_name, table_data|
|
291
|
+
begin
|
292
|
+
table_obj = db.tables[table_name.to_sym]
|
293
|
+
table_data["callback"].call("db" => db, "table" => table_obj) if table_data.is_a?(Hash) and table_data["callback"]
|
294
|
+
table_obj.drop
|
295
|
+
rescue Errno::ENOENT => e
|
296
|
+
next
|
297
|
+
end
|
298
|
+
end
|
299
|
+
end
|
300
|
+
|
301
|
+
|
302
|
+
#Free cache.
|
303
|
+
tables.clear if tables
|
304
|
+
tables = nil
|
305
|
+
end
|
306
|
+
|
307
|
+
private
|
308
|
+
|
309
|
+
#This method checks if certain rows are present in a table based on a hash.
|
310
|
+
def rows_init(args)
|
311
|
+
db = args["db"]
|
312
|
+
table = args["table"]
|
313
|
+
|
314
|
+
raise "No db given." if !db
|
315
|
+
raise "No table given." if !table
|
316
|
+
|
317
|
+
args["rows"].each do |row_data|
|
318
|
+
if row_data["find_by"]
|
319
|
+
find_by = row_data["find_by"]
|
320
|
+
elsif row_data["data"]
|
321
|
+
find_by = row_data["data"]
|
322
|
+
else
|
323
|
+
raise "Could not figure out the find-by."
|
324
|
+
end
|
325
|
+
|
326
|
+
rows_found = 0
|
327
|
+
args["db"].select(table.name, find_by) do |d_rows|
|
328
|
+
rows_found += 1
|
329
|
+
|
330
|
+
if Knj::ArrayExt.hash_diff?(Knj::ArrayExt.hash_sym(row_data["data"]), Knj::ArrayExt.hash_sym(d_rows), {"h2_to_h1" => false})
|
331
|
+
print "Data was not right - updating row: #{JSON.generate(row_data["data"])}\n" if args["debug"]
|
332
|
+
args["db"].update(table.name, row_data["data"], d_rows)
|
333
|
+
end
|
334
|
+
end
|
335
|
+
|
336
|
+
if rows_found == 0
|
337
|
+
print "Inserting row: #{JSON.generate(row_data["data"])}\n" if args["debug"]
|
338
|
+
table.insert(row_data["data"])
|
339
|
+
end
|
340
|
+
end
|
341
|
+
end
|
342
|
+
end
|
data/include/row.rb
ADDED
@@ -0,0 +1,153 @@
|
|
1
|
+
class Baza::Row
|
2
|
+
attr_reader :args, :data
|
3
|
+
|
4
|
+
def is_knj?; return true; end
|
5
|
+
|
6
|
+
def initialize(args)
|
7
|
+
@args = {}
|
8
|
+
args.each do |key, value|
|
9
|
+
@args[key.to_sym] = value
|
10
|
+
end
|
11
|
+
|
12
|
+
@args[:db] = $db if !@args[:db] and $db and $db.class.to_s == "Baza::Db"
|
13
|
+
@args[:objects] = $objects if !@args[:objects] and $objects and $objects.is_a?(Baza::ModelHandler)
|
14
|
+
@args[:col_id] = :id if !@args[:col_id]
|
15
|
+
raise "No table given." if !@args[:table]
|
16
|
+
|
17
|
+
if @args[:data] and (@args[:data].is_a?(Integer) or @args[:data].is_a?(Fixnum) or @args[:data].is_a?(String))
|
18
|
+
@data = {@args[:col_id].to_sym => @args[:data].to_s}
|
19
|
+
self.reload
|
20
|
+
elsif @args[:data] and @args[:data].is_a?(Hash)
|
21
|
+
@data = {}
|
22
|
+
@args[:data].each do |key, value|
|
23
|
+
@data[key.to_sym] = value
|
24
|
+
end
|
25
|
+
elsif @args[:id]
|
26
|
+
@data = {}
|
27
|
+
@data[@args[:col_id].to_sym] = @args[:id]
|
28
|
+
self.reload
|
29
|
+
else
|
30
|
+
raise ArgumentError.new("Invalid data: #{@args[:data].to_s} (#{@args[:data].class.to_s})")
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def db
|
35
|
+
if !@args[:force_selfdb]
|
36
|
+
curthread = Thread.current
|
37
|
+
if curthread.is_a?(Knj::Thread) and curthread[:knjappserver] and curthread[:knjappserver][:db]
|
38
|
+
return curthread[:knjappserver][:db]
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
return @args[:db]
|
43
|
+
end
|
44
|
+
|
45
|
+
def ob
|
46
|
+
return @args[:objects] if @args.key?(:objects)
|
47
|
+
return $ob if $ob and $ob.is_a?(Baza::ModelHandler)
|
48
|
+
return false
|
49
|
+
end
|
50
|
+
|
51
|
+
alias :objects :ob
|
52
|
+
|
53
|
+
def reload
|
54
|
+
last_id = self.id
|
55
|
+
data = self.db.single(@args[:table], {@args[:col_id] => self.id})
|
56
|
+
if !data
|
57
|
+
raise Errno::ENOENT.new("Could not find any data for the object with ID: '#{last_id}' in the table '#{@args[:table].to_s}'.")
|
58
|
+
end
|
59
|
+
|
60
|
+
@data = {}
|
61
|
+
data.each do |key, value|
|
62
|
+
@data[key.to_sym] = value
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def update(newdata)
|
67
|
+
self.db.update(@args[:table], newdata, {@args[:col_id] => self.id})
|
68
|
+
self.reload
|
69
|
+
|
70
|
+
if self.ob
|
71
|
+
self.ob.call("object" => self, "signal" => "update")
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
def delete
|
76
|
+
self.db.delete(@args[:table], {@args[:col_id] => self.id})
|
77
|
+
self.destroy
|
78
|
+
end
|
79
|
+
|
80
|
+
def destroy
|
81
|
+
@args = nil
|
82
|
+
@data = nil
|
83
|
+
end
|
84
|
+
|
85
|
+
def has_key?(key)
|
86
|
+
return @data.key?(key.to_sym)
|
87
|
+
end
|
88
|
+
|
89
|
+
def [](key)
|
90
|
+
raise "No valid key given." if !key
|
91
|
+
raise "No data was loaded on the object? Maybe you are trying to call a deleted object?" if !@data
|
92
|
+
|
93
|
+
if @data.key?(key)
|
94
|
+
return @data[key]
|
95
|
+
elsif @data.key?(key.to_sym)
|
96
|
+
return @data[key.to_sym]
|
97
|
+
elsif @data.key?(key.to_s)
|
98
|
+
return @data[key.to_s]
|
99
|
+
end
|
100
|
+
|
101
|
+
raise "No such key: #{key.to_s}."
|
102
|
+
end
|
103
|
+
|
104
|
+
def []=(key, value)
|
105
|
+
self.update(key.to_sym => value)
|
106
|
+
self.reload
|
107
|
+
end
|
108
|
+
|
109
|
+
def id
|
110
|
+
return @data[@args[:col_id]]
|
111
|
+
end
|
112
|
+
|
113
|
+
def title
|
114
|
+
if @args[:col_title]
|
115
|
+
return @data[@args[:col_title].to_sym]
|
116
|
+
end
|
117
|
+
|
118
|
+
if @data.key?(:title)
|
119
|
+
return @data[:title]
|
120
|
+
elsif @data.key?(:name)
|
121
|
+
return @data[:name]
|
122
|
+
end
|
123
|
+
|
124
|
+
raise "'col_title' has not been set for the class: '#{self.class.to_s}'."
|
125
|
+
end
|
126
|
+
|
127
|
+
alias :name :title
|
128
|
+
|
129
|
+
def each(&args)
|
130
|
+
return @data.each(&args)
|
131
|
+
end
|
132
|
+
|
133
|
+
def to_hash
|
134
|
+
return @data.clone
|
135
|
+
end
|
136
|
+
|
137
|
+
def esc(str)
|
138
|
+
return self.db.escape(str)
|
139
|
+
end
|
140
|
+
|
141
|
+
def method_missing(*args)
|
142
|
+
func_name = args[0].to_s
|
143
|
+
if match = func_name.match(/^(\S+)\?$/) and @data.key?(match[1].to_sym)
|
144
|
+
if @data[match[1].to_sym] == "1" or @data[match[1].to_sym] == "yes"
|
145
|
+
return true
|
146
|
+
elsif @data[match[1].to_sym] == "0" or @data[match[1].to_sym] == "no"
|
147
|
+
return false
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
raise sprintf("No such method: %s", func_name)
|
152
|
+
end
|
153
|
+
end
|