knjrbfw 0.0.111 → 0.0.113

Sign up to get free protection for your applications and to get access to all the features.
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: knjrbfw
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.111
4
+ version: 0.0.113
5
5
  platform: ruby
6
6
  authors:
7
7
  - Kasper Johansen
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-04-13 00:00:00.000000000 Z
11
+ date: 2015-04-21 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: wref
@@ -228,8 +228,6 @@ files:
228
228
  - lib/knj/compiler.rb
229
229
  - lib/knj/cpufreq.rb
230
230
  - lib/knj/csv.rb
231
- - lib/knj/datarow.rb
232
- - lib/knj/datarow_custom.rb
233
231
  - lib/knj/degulesider.rb
234
232
  - lib/knj/erb/apache_knjerb.conf
235
233
  - lib/knj/erb/cache/README
@@ -363,7 +361,6 @@ files:
363
361
  - lib/knj/scripts/ip2location.rb
364
362
  - lib/knj/scripts/keepalive.rb
365
363
  - lib/knj/scripts/php_to_rb_helper.rb
366
- - lib/knj/scripts/process_meta_exec.rb
367
364
  - lib/knj/scripts/speed_test.rb
368
365
  - lib/knj/scripts/svn_merge.rb
369
366
  - lib/knj/scripts/upgrade_knjrbfw_checker.rb
@@ -382,7 +379,6 @@ files:
382
379
  - lib/knj/thread.rb
383
380
  - lib/knj/thread2.rb
384
381
  - lib/knj/threadhandler.rb
385
- - lib/knj/translations.rb
386
382
  - lib/knj/unix_proc.rb
387
383
  - lib/knj/web.rb
388
384
  - lib/knj/webscripts/image.rhtml
@@ -1,873 +0,0 @@
1
- #This class helps create models in a framework with Knj::Db and Knj::Objects.
2
- #===Examples
3
- # db = Knj::Db.new(:type => "sqlite3", :path => "somepath.sqlite3")
4
- # ob = Knj::Objects.new(:db => db, :datarow => true, :path => "path_of_model_class_files")
5
- # user = ob.get(:User, 1) #=> <Models::User> that extends <Knj::Datarow>
6
- class Knj::Datarow
7
- @@refs = {}
8
-
9
- #Returns the Knj::Objects which handels this model.
10
- def ob
11
- return self.class.ob
12
- end
13
-
14
- #Returns the Knj::Db which handels this model.
15
- def db
16
- return self.class.db
17
- end
18
-
19
- #Returns the 'Knj::Objects'-object that handels this class.
20
- def self.ob
21
- return @ob
22
- end
23
-
24
- #Returns the 'Knj::Db'-object that handels this class.
25
- def self.db
26
- return @db
27
- end
28
-
29
- #This is used by 'Knj::Objects' to find out what data is required for this class. Returns the array that tells about required data.
30
- #===Examples
31
- #When adding a new user, this can fail if the ':group_id' is not given, or the ':group_id' doesnt refer to a valid group-row in the db.
32
- # class Models::User < Knj::Datarow
33
- # has_one [
34
- # {:class => :Group, :col => :group_id, :method => :group, :required => true}
35
- # ]
36
- # end
37
- def self.required_data
38
- @required_data = [] if !@required_data
39
- return @required_data
40
- end
41
-
42
- #This is used by 'Knj::Objects' to find out what other objects this class depends on. Returns the array that tells about depending data.
43
- #===Examples
44
- #This will tell Knj::Objects that files depends on users. It can prevent the user from being deleted, if any files depend on it.
45
- # class Models::User < Knj::Datarow
46
- # has_many [
47
- # {:class => :File, :col => :user_id, :method => :files, :depends => true}
48
- # ]
49
- # end
50
- def self.depending_data
51
- return @depending_data
52
- end
53
-
54
- #Returns true if this class has been initialized.
55
- def self.initialized?
56
- return false if !@columns_sqlhelper_args
57
- return true
58
- end
59
-
60
- #This is used by 'Knj::Objects' to find out which other objects should be deleted when an object of this class is deleted automatically. Returns the array that tells about autodelete data.
61
- #===Examples
62
- #This will trigger Knj::Objects to automatically delete all the users pictures, when deleting the current user.
63
- # class Models::User < Knj::Datarow
64
- # has_many [
65
- # {:class => :Picture, :col => :user_id, :method => :pictures, :autodelete => true}
66
- # ]
67
- # end
68
- def self.autodelete_data
69
- return @autodelete_data
70
- end
71
-
72
- #Returns the autozero-data (if any).
73
- def self.autozero_data
74
- return @autozero_data
75
- end
76
-
77
- #This helps various parts of the framework determine if this is a datarow class without requiring it.
78
- #===Examples
79
- # print "This is a knj-object." if obj.respond_to?("is_knj?")
80
- def is_knj?
81
- return true
82
- end
83
-
84
- #This tests if a certain string is a date-null-stamp.
85
- #===Examples
86
- # time_str = dbrow[:date]
87
- # print "No valid date on the row." if Knj::Datarow.is_nullstamp?(time_str)
88
- def self.is_nullstamp?(stamp)
89
- return true if !stamp or stamp == "0000-00-00 00:00:00" or stamp == "0000-00-00"
90
- return false
91
- end
92
-
93
- #This is used to define datarows that this object can have a lot of.
94
- #===Examples
95
- #This will define the method "pictures" on 'Models::User' that will return all pictures for the users and take possible Objects-sql-arguments. It will also enabling joining pictures when doing Objects-sql-lookups.
96
- # class Models::User < Knj::Datarow
97
- # has_many [
98
- # [:Picture, :user_id, :pictures],
99
- # {:class => :File, :col => :user_id, :method => :files}
100
- # ]
101
- # end
102
- def self.has_many(arr)
103
- arr.each do |val|
104
- if val.is_a?(Array)
105
- classname, colname, methodname = *val
106
- elsif val.is_a?(Hash)
107
- classname, colname, methodname = nil, nil, nil
108
-
109
- val.each do |hkey, hval|
110
- case hkey
111
- when :class
112
- classname = hval
113
- when :col
114
- colname = hval
115
- when :method
116
- methodname = hval
117
- when :depends, :autodelete, :autozero, :where
118
- #ignore
119
- else
120
- raise "Invalid key for 'has_many': '#{hkey}'."
121
- end
122
- end
123
-
124
- colname = "#{self.name.to_s.split("::").last.to_s.downcase}_id".to_sym if colname.to_s.empty?
125
-
126
- if val[:depends]
127
- @depending_data = [] if !@depending_data
128
- @depending_data << {
129
- :colname => colname,
130
- :classname => classname
131
- }
132
- end
133
-
134
- if val[:autodelete]
135
- @autodelete_data = [] if !@autodelete_data
136
- @autodelete_data << {
137
- :colname => colname,
138
- :classname => classname
139
- }
140
- end
141
-
142
- if val[:autozero]
143
- @autozero_data = [] if !@autozero_data
144
- @autozero_data << {
145
- :colname => colname,
146
- :classname => classname
147
- }
148
- end
149
- else
150
- raise "Unknown argument: '#{val.class.name}'."
151
- end
152
-
153
- raise "No classname given." if !classname
154
- methodname = "#{classname.to_s.downcase}s".to_sym if !methodname
155
- raise "No column was given for '#{self.name}' regarding has-many-class: '#{classname}'." if !colname
156
-
157
- if val.is_a?(Hash) and val.key?(:where)
158
- where_args = val[:where]
159
- else
160
- where_args = nil
161
- end
162
-
163
- self.define_many_methods(classname, methodname, colname, where_args)
164
-
165
- self.joined_tables(
166
- classname => {
167
- :where => {
168
- colname.to_s => {:type => :col, :name => :id}
169
- }
170
- }
171
- )
172
- end
173
- end
174
-
175
- #This define is this object has one element of another datarow-class. It define various methods and joins based on that.
176
- #===Examples
177
- # class Models::User < Knj::Datarow
178
- # has_one [
179
- # #Defines the method 'group', which returns a 'Group'-object by the column 'group_id'.
180
- # :Group,
181
- #
182
- # #Defines the method 'type', which returns a 'Type'-object by the column 'type_id'.
183
- # {:class => :Type, :col => :type_id, :method => :type}
184
- # ]
185
- # end
186
- def self.has_one(arr)
187
- arr.each do |val|
188
- methodname = nil
189
- colname = nil
190
- classname = nil
191
-
192
- if val.is_a?(Symbol)
193
- classname = val
194
- methodname = val.to_s.downcase.to_sym
195
- colname = "#{val.to_s.downcase}_id".to_sym
196
- elsif val.is_a?(Array)
197
- classname, colname, methodname = *val
198
- elsif val.is_a?(Hash)
199
- classname, colname, methodname = nil, nil, nil
200
-
201
- val.each do |hkey, hval|
202
- case hkey
203
- when :class
204
- classname = hval
205
- when :col
206
- colname = hval
207
- when :method
208
- methodname = hval
209
- when :required
210
- #ignore
211
- else
212
- raise "Invalid key for class '#{self.name}' functionality 'has_many': '#{hkey}'."
213
- end
214
- end
215
-
216
- if val[:required]
217
- colname = "#{classname.to_s.downcase}_id".to_sym if !colname
218
- self.required_data << {
219
- :col => colname,
220
- :class => classname
221
- }
222
- end
223
- else
224
- raise "Unknown argument-type: '#{arr.class.name}'."
225
- end
226
-
227
- methodname = classname.to_s.downcase if !methodname
228
- colname = "#{classname.to_s.downcase}_id".to_sym if !colname
229
- self.define_one_methods(classname, methodname, colname)
230
-
231
- self.joined_tables(
232
- classname => {
233
- :where => {
234
- "id" => {:type => :col, :name => colname}
235
- }
236
- }
237
- )
238
- end
239
- end
240
-
241
- #This method initializes joins, sets methods to update translations and makes the translations automatically be deleted when the object is deleted.
242
- #===Examples
243
- # class Models::Article < Knj::Datarow
244
- # #Defines methods such as: 'title', 'title=', 'content', 'content='. When used with Knjappserver these methods will change what they return and set based on the current language of the session.
245
- # has_translation [:title, :content]
246
- # end
247
- #
248
- # article = ob.get(:Article, 1)
249
- # print "The title in the current language is: '#{article.title}'."
250
- #
251
- # article.title = 'Title in english if the language is english'
252
- def self.has_translation(arr)
253
- @translations = [] if !@translations
254
-
255
- arr.each do |val|
256
- @translations << val
257
-
258
- val_dc = val.to_s.downcase
259
- table_name = "Translation_#{val_dc}".to_sym
260
-
261
- joined_tables(
262
- table_name => {
263
- :where => {
264
- "object_class" => self.name,
265
- "object_id" => {:type => :col, :name => :id},
266
- "key" => val.to_s,
267
- "locale" => proc{|d| _session[:locale]}
268
- },
269
- :parent_table => :Translation,
270
- :datarow => Knj::Translations::Translation,
271
- :ob => @ob
272
- }
273
- )
274
-
275
- self.define_translation_methods(:val => val, :val_dc => val_dc)
276
- end
277
- end
278
-
279
- #This returns all translations for this datarow-class.
280
- def self.translations
281
- return @translations
282
- end
283
-
284
- #Returns data about joined tables for this class.
285
- def self.joined_tables(hash)
286
- @columns_joined_tables = {} if !@columns_joined_tables
287
- @columns_joined_tables.merge!(hash)
288
- end
289
-
290
- #Returns various data for the objects-sql-helper. This can be used to view various informations about the columns and more.
291
- def self.columns_sqlhelper_args
292
- raise "No SQLHelper arguments has been spawned yet." if !@columns_sqlhelper_args
293
- return @columns_sqlhelper_args
294
- end
295
-
296
- #Called by Knj::Objects to initialize the model and load column-data on-the-fly.
297
- def self.load_columns(d)
298
- @ob = d.ob
299
- @db = d.db
300
-
301
- @classname = self.name.split("::").last.to_sym if !@classname
302
- @table = @classname if !@table
303
- @mutex = Monitor.new if !@mutex
304
-
305
- #Cache these to avoid method-lookups.
306
- @sep_col = @db.sep_col
307
- @sep_table = @db.sep_table
308
- @table_str = "#{@sep_table}#{@db.esc_table(@table)}#{@sep_table}"
309
-
310
- @mutex.synchronize do
311
- inst_methods = self.instance_methods(false)
312
-
313
- sqlhelper_args = {
314
- :db => @db,
315
- :table => @table,
316
- :cols_bools => [],
317
- :cols_date => [],
318
- :cols_dbrows => [],
319
- :cols_num => [],
320
- :cols_str => [],
321
- :cols => {}
322
- }
323
-
324
- sqlhelper_args[:table] = @table
325
-
326
- @db.tables[table].columns do |col_obj|
327
- col_name = col_obj.name.to_s
328
- col_name_sym = col_name.to_sym
329
- col_type = col_obj.type
330
- col_type = :int if col_type == :bigint or col_type == :tinyint or col_type == :mediumint or col_type == :smallint
331
- sqlhelper_args[:cols][col_name] = true
332
-
333
- self.define_bool_methods(inst_methods, col_name)
334
-
335
- if col_type == :enum and col_obj.maxlength == "'0','1'"
336
- sqlhelper_args[:cols_bools] << col_name
337
- elsif col_type == :int and col_name.slice(-3, 3) == "_id"
338
- sqlhelper_args[:cols_dbrows] << col_name
339
- elsif col_type == :int or col_type == :decimal
340
- sqlhelper_args[:cols_num] << col_name
341
- elsif col_type == :varchar or col_type == :text or col_type == :enum
342
- sqlhelper_args[:cols_str] << col_name
343
- elsif col_type == :date or col_type == :datetime
344
- sqlhelper_args[:cols_date] << col_name
345
- self.define_date_methods(inst_methods, col_name_sym)
346
- end
347
-
348
- if col_type == :int or col_type == :decimal
349
- self.define_numeric_methods(inst_methods, col_name_sym)
350
- end
351
-
352
- if col_type == :int or col_type == :varchar
353
- self.define_text_methods(inst_methods, col_name_sym)
354
- end
355
-
356
- if col_type == :time
357
- self.define_time_methods(inst_methods, col_name_sym)
358
- end
359
- end
360
-
361
- if @columns_joined_tables
362
- @columns_joined_tables.each do |table_name, table_data|
363
- table_data[:where].each do |key, val|
364
- val[:table] = @table if val.is_a?(Hash) and !val.key?(:table) and val[:type].to_sym == :col
365
- end
366
-
367
- table_data[:datarow] = @ob.args[:module].const_get(table_name.to_sym) if !table_data.key?(:datarow)
368
- end
369
-
370
- sqlhelper_args[:joined_tables] = @columns_joined_tables
371
- end
372
-
373
- @columns_sqlhelper_args = sqlhelper_args
374
- end
375
-
376
- self.init_class(d) if self.respond_to?(:init_class)
377
- end
378
-
379
- #This method helps returning objects and supports various arguments. It should be called by Object#list.
380
- #===Examples
381
- # ob.list(:User, {"username_lower" => "john doe"}) do |user|
382
- # print user.id
383
- # end
384
- #
385
- # array = ob.list(:User, {"id" => 1})
386
- # print array.length
387
- def self.list(d, &block)
388
- args = d.args
389
-
390
- if args["count"]
391
- count = true
392
- args.delete("count")
393
- sql = "SELECT COUNT(#{@table_str}.#{@sep_col}id#{@sep_col}) AS count"
394
- elsif args["select_col_as_array"]
395
- select_col_as_array = true
396
- sql = "SELECT #{@table_str}.#{@sep_col}#{args["select_col_as_array"]}#{@sep_col} AS id"
397
- args.delete("select_col_as_array")
398
- else
399
- sql = "SELECT #{@table_str}.*"
400
- end
401
-
402
- qargs = nil
403
- ret = self.list_helper(d)
404
-
405
- sql << " FROM #{@table_str}"
406
- sql << ret[:sql_joins]
407
- sql << " WHERE 1=1"
408
- sql << ret[:sql_where]
409
-
410
- args.each do |key, val|
411
- case key
412
- when "return_sql"
413
- #ignore
414
- when :cloned_ubuf
415
- qargs = {:cloned_ubuf => true}
416
- else
417
- raise "Invalid key: '#{key}' for '#{self.name}'. Valid keys are: '#{@columns_sqlhelper_args[:cols].keys.sort}'. Date-keys: '#{@columns_sqlhelper_args[:cols_date]}'."
418
- end
419
- end
420
-
421
- #The count will bug if there is a group-by-statement.
422
- grp_shown = false
423
- if !count and !ret[:sql_groupby]
424
- sql << " GROUP BY #{@table_str}.#{@sep_col}id#{@sep_col}"
425
- grp_shown = true
426
- end
427
-
428
- if ret[:sql_groupby]
429
- if !grp_shown
430
- sql << " GROUP BY"
431
- else
432
- sql << ", "
433
- end
434
-
435
- sql << ret[:sql_groupby]
436
- end
437
-
438
- sql << ret[:sql_order]
439
- sql << ret[:sql_limit]
440
-
441
- return sql.to_s if args["return_sql"]
442
-
443
- if select_col_as_array
444
- enum = Enumerator.new do |yielder|
445
- @db.q(sql, qargs) do |data|
446
- yielder << data[:id]
447
- end
448
- end
449
-
450
- if block
451
- enum.each(&block)
452
- return nil
453
- elsif @ob.args[:array_enum]
454
- return Array_enumerator.new(enum)
455
- else
456
- return enum.to_a
457
- end
458
- elsif count
459
- ret = @db.query(sql).fetch
460
- return ret[:count].to_i if ret
461
- return 0
462
- end
463
-
464
- return @ob.list_bysql(self.classname, sql, qargs, &block)
465
- end
466
-
467
- #Helps call 'sqlhelper' on Knj::Objects to generate SQL-strings.
468
- def self.list_helper(d)
469
- self.load_columns(d) if !@columns_sqlhelper_args
470
- @columns_sqlhelper_args[:table] = @table
471
- return @ob.sqlhelper(d.args, @columns_sqlhelper_args)
472
- end
473
-
474
- #Returns the classname of the object without any subclasses.
475
- def self.classname
476
- return @classname
477
- end
478
-
479
- #Sets the classname to something specific in order to hack the behaviour.
480
- def self.classname=(newclassname)
481
- @classname = newclassname
482
- end
483
-
484
- #Returns the table-name that should be used for this datarow.
485
- #===Examples
486
- # db.query("SELECT * FROM `#{Models::User.table}` WHERE username = 'John Doe'") do |data|
487
- # print data[:id]
488
- # end
489
- def self.table
490
- return @table
491
- end
492
-
493
- #This can be used to manually set the table-name. Useful when meta-programming classes that extends the datarow-class.
494
- #===Examples
495
- # Models::User.table = "prefix_User"
496
- def self.table=(newtable)
497
- @table = newtable
498
- @columns_sqlhelper_args[:table] = @table if @columns_sqlhelper_args.is_a?(Hash)
499
- end
500
-
501
- #Returns the class-name but without having to call the class-table-method. To make code look shorter.
502
- #===Examples
503
- # user = ob.get_by(:User, {:username => 'John Doe'})
504
- # db.query("SELECT * FROM `#{user.table}` WHERE username = 'John Doe'") do |data|
505
- # print data[:id]
506
- # end
507
- def table
508
- return self.class.table
509
- end
510
-
511
- #Initializes the object. This should be called from 'Knj::Objects' and not manually.
512
- #===Examples
513
- # user = ob.get(:User, 3)
514
- def initialize(data, args = nil)
515
- if data.is_a?(Hash) and data.key?(:id)
516
- @data = data
517
- @id = @data[:id].to_i
518
- elsif data
519
- @id = data.to_i
520
-
521
- classname = self.class.classname.to_sym
522
- if self.class.ob.ids_cache_should.key?(classname)
523
- #ID caching is enabled for this model - dont reload until first use.
524
- raise Errno::ENOENT, "ID was not found in cache: '#{id}'." if !self.class.ob.ids_cache[classname].key?(@id)
525
- @should_reload = true
526
- else
527
- #ID caching is not enabled - reload now to check if row exists. Else set 'should_reload'-variable if 'skip_reload' is set.
528
- if !args or !args[:skip_reload]
529
- self.reload
530
- else
531
- @should_reload = true
532
- end
533
- end
534
- else
535
- raise ArgumentError, "Could not figure out the data from '#{data.class.name}'."
536
- end
537
-
538
- if @id.to_i <= 0
539
- raise "Invalid ID: '#{@id}' from '#{@data}'." if @data
540
- raise "Invalid ID: '#{@id}'."
541
- end
542
- end
543
-
544
- #Reloads the data from the database.
545
- #===Examples
546
- # old_username = user[:username]
547
- # user.reload
548
- # print "The username changed in the database!" if user[:username] != old_username
549
- def reload
550
- @data = self.class.db.single(self.class.table, {:id => @id})
551
- raise Errno::ENOENT, "Could not find any data for the object with ID: '#{@id}' in the table '#{self.class.table}'." if !@data
552
- @should_reload = false
553
- end
554
-
555
- #Tells the object that it should reloads its data because it has changed. It wont reload before it is required though, which may save you a couple of SQL-calls.
556
- #===Examples
557
- # obj = _ob.get(:User, 5)
558
- # obj.should_reload
559
- def should_reload
560
- @should_reload = true
561
- @data = nil
562
- end
563
-
564
- #Returns the data-hash that contains all the data from the database.
565
- def data
566
- self.reload if @should_reload
567
- return @data
568
- end
569
-
570
- #Writes/updates new data for the object.
571
- #===Examples
572
- # user.update(:username => 'New username', :date_changed => Time.now)
573
- def update(newdata)
574
- self.class.db.update(self.class.table, newdata, {:id => @id})
575
- self.should_reload
576
- self.class.ob.call("object" => self, "signal" => "update")
577
- end
578
-
579
- #Forcefully destroys the object. This is done after deleting it and should not be called manually.
580
- def destroy
581
- @id = nil
582
- @data = nil
583
- @should_reload = nil
584
- end
585
-
586
- #Returns true if that key exists on the object.
587
- #===Examples
588
- # print "Looks like the user has a name." if user.key?(:name)
589
- def key?(key)
590
- self.reload if @should_reload
591
- return @data.key?(key.to_sym)
592
- end
593
- alias has_key? key?
594
-
595
- #Returns true if the object has been deleted.
596
- #===Examples
597
- # print "That user is deleted." if user.deleted?
598
- def deleted?
599
- return true if !@data and !@id
600
- return false
601
- end
602
-
603
- #Returns true if the given object no longer exists in the database. Also destroys the data on the object and sets it to deleted-status, if it no longer exists.
604
- #===Examples
605
- # print "That user is deleted." if user.deleted_from_db?
606
- def deleted_from_db?
607
- #Try to avoid db-query if object is already deleted.
608
- return true if self.deleted?
609
-
610
- #Try to reload data. Destroy object and return true if the row is gone from the database.
611
- begin
612
- self.reload
613
- return false
614
- rescue Errno::ENOENT
615
- self.destroy
616
- return true
617
- end
618
- end
619
-
620
- #Returns a specific data from the object by key.
621
- # print "Username: #{user[:username]}\n"
622
- # print "ID: #{user[:id]}\n"
623
- # print "ID again: #{user.id}\n"
624
- def [](key)
625
- raise "Key was not a symbol: '#{key.class.name}'." if !key.is_a?(Symbol)
626
- return @id if !@data and key == :id and @id
627
- self.reload if @should_reload
628
- raise "No data was loaded on the object? Maybe you are trying to call a deleted object? (#{self.class.classname}(#{@id}), #{@should_reload})" if !@data
629
- return @data[key] if @data.key?(key)
630
- raise "No such key: '#{key}' on '#{self.class.name}' (#{@data.keys.join(", ")}) (#{@should_reload})."
631
- end
632
-
633
- #Writes/updates a keys value on the object.
634
- # user = ob.get_by(:User, {"username" => "John Doe"})
635
- # user[:username] = 'New username'
636
- def []=(key, value)
637
- self.update(key.to_sym => value)
638
- self.should_reload
639
- end
640
-
641
- #Returns the objects ID.
642
- def id
643
- raise Errno::ENOENT, "This object has been deleted." if self.deleted?
644
- raise "No ID on object." if !@id
645
- return @id
646
- end
647
-
648
- #This enable Wref to not return the wrong object.
649
- def __object_unique_id__
650
- return 0 if self.deleted?
651
- return self.id
652
- end
653
-
654
- #Tries to figure out, and returns, the possible name or title for the object.
655
- def name
656
- self.reload if @should_reload
657
-
658
- if @data.key?(:title)
659
- return @data[:title]
660
- elsif @data.key?(:name)
661
- return @data[:name]
662
- end
663
-
664
- obj_methods = self.class.instance_methods(false)
665
- [:name, :title].each do |method_name|
666
- return self.method(method_name).call if obj_methods.index(method_name)
667
- end
668
-
669
- raise "Couldnt figure out the title/name of the object on class #{self.class.name}."
670
- end
671
-
672
- #Calls the name-method and returns a HTML-escaped value. Also "[no name]" if the name is empty.
673
- def name_html
674
- name_str = self.name.to_s
675
- name_str = "[no name]" if name_str.length <= 0
676
- return name_str
677
- end
678
-
679
- alias title name
680
-
681
- #Loops through the data on the object.
682
- #===Examples
683
- # user = ob.get(:User, 1)
684
- # user.each do |key, val|
685
- # print "#{key}: #{val}\n" #=> username: John Doe
686
- # end
687
- def each(*args, &block)
688
- self.reload if @should_reload
689
- return @data.each(*args, &block)
690
- end
691
-
692
- #Hash-compatible.
693
- def to_hash
694
- self.reload if @should_reload
695
- return @data.clone
696
- end
697
-
698
- #Returns a default-URL to show the object.
699
- def url
700
- cname = self.class.classname.to_s.downcase
701
- return "?show=#{cname}_show&#{cname}_id=#{self.id}"
702
- end
703
-
704
- #Returns the URL for editting the object.
705
- def url_edit
706
- cname = self.class.classname.to_s.downcase
707
- return "?show=#{cname}_edit&#{cname}_id=#{self.id}"
708
- end
709
-
710
- #Returns the HTML for making a link to the object.
711
- def html(args = nil)
712
- if args and args[:edit]
713
- url = self.url_edit
714
- else
715
- url = self.url
716
- end
717
-
718
- return "<a href=\"#{Knj::Web.ahref_parse(url)}\">#{self.name_html}</a>"
719
- end
720
-
721
- private
722
-
723
- #Various methods to define methods based on the columns for the datarow.
724
- def self.define_translation_methods(args)
725
- define_method("#{args[:val_dc]}=") do |newtransval|
726
- begin
727
- _hb.trans_set(self, {
728
- args[:val] => newtransval
729
- })
730
- rescue NameError
731
- _kas.trans_set(self, {
732
- args[:val] => newtransval
733
- })
734
- end
735
- end
736
-
737
- define_method("#{args[:val_dc]}") do
738
- begin
739
- return _hb.trans(self, args[:val])
740
- rescue NameError
741
- return _kas.trans(self, args[:val])
742
- end
743
- end
744
-
745
- define_method("#{args[:val_dc]}_html") do
746
- begin
747
- str = _hb.trans(self, args[:val])
748
- rescue NameError
749
- str = _kas.trans(self, args[:val])
750
- end
751
-
752
- if str.to_s.strip.length <= 0
753
- return "[no translation for #{args[:val]}]"
754
- end
755
-
756
- return str
757
- end
758
- end
759
-
760
- #Defines the boolean-methods based on enum-columns.
761
- def self.define_bool_methods(inst_methods, col_name)
762
- #Spawns a method on the class which returns true if the data is 1.
763
- if !inst_methods.include?("#{col_name}?".to_sym)
764
- define_method("#{col_name}?") do
765
- return true if self[col_name.to_sym].to_s == "1"
766
- return false
767
- end
768
- end
769
- end
770
-
771
- #Defines date- and time-columns based on datetime- and date-columns.
772
- def self.define_date_methods(inst_methods, col_name)
773
- if !inst_methods.include?("#{col_name}_str".to_sym)
774
- define_method("#{col_name}_str") do |*method_args|
775
- if Datet.is_nullstamp?(self[col_name])
776
- return self.class.ob.events.call(:no_date, self.class.name)
777
- end
778
-
779
- return Datet.in(self[col_name]).out(*method_args)
780
- end
781
- end
782
-
783
- if !inst_methods.include?(col_name)
784
- define_method(col_name) do |*method_args|
785
- return false if Datet.is_nullstamp?(self[col_name])
786
- return Datet.in(self[col_name])
787
- end
788
- end
789
- end
790
-
791
- #Define various methods based on integer-columns.
792
- def self.define_numeric_methods(inst_methods, col_name)
793
- if !inst_methods.include?("#{col_name}_format".to_sym)
794
- define_method("#{col_name}_format") do |*method_args|
795
- return Knj::Locales.number_out(self[col_name], *method_args)
796
- end
797
- end
798
- end
799
-
800
- #Define methods to look up objects directly.
801
- #===Examples
802
- # user = Models::User.by_username('John Doe')
803
- # print user.id
804
- def self.define_text_methods(inst_methods, col_name)
805
- if !inst_methods.include?("by_#{col_name}".to_sym) and RUBY_VERSION.to_s.slice(0, 3) != "1.8"
806
- define_singleton_method("by_#{col_name}") do |arg|
807
- return self.class.ob.get_by(self.class.table, {col_name.to_s => arg})
808
- end
809
- end
810
- end
811
-
812
- #Defines dbtime-methods based on time-columns.
813
- def self.define_time_methods(inst_methods, col_name)
814
- if !inst_methods.include?("#{col_name}_dbt".to_sym)
815
- define_method("#{col_name}_dbt") do
816
- return Knj::Db::Dbtime.new(self[col_name.to_sym])
817
- end
818
- end
819
- end
820
-
821
- #Memory friendly helper method that defines methods for 'has_many'.
822
- def self.define_many_methods(classname, methodname, colname, where_args)
823
- define_method(methodname) do |*args, &block|
824
- if args and args[0]
825
- list_args = args[0]
826
- else
827
- list_args = {}
828
- end
829
-
830
- list_args.merge!(where_args) if where_args
831
- list_args[colname.to_s] = self.id
832
-
833
- return self.class.ob.list(classname, list_args, &block)
834
- end
835
-
836
- define_method("#{methodname}_count".to_sym) do |*args|
837
- list_args = args[0] if args and args[0]
838
- list_args = {} if !list_args
839
- list_args[colname.to_s] = self.id
840
- list_args["count"] = true
841
-
842
- return self.class.ob.list(classname, list_args)
843
- end
844
-
845
- define_method("#{methodname}_last".to_sym) do |args|
846
- args = {} if !args
847
- return self.class.ob.list(classname, {"orderby" => [["id", "desc"]], "limit" => 1}.merge(args))
848
- end
849
- end
850
-
851
- #Memory friendly helper method that defines methods for 'has_one'.
852
- def self.define_one_methods(classname, methodname, colname)
853
- define_method(methodname) do
854
- return self.class.ob.get_try(self, colname, classname)
855
- end
856
-
857
- methodname_html = "#{methodname}_html".to_sym
858
- define_method(methodname_html) do |*args|
859
- obj = self.__send__(methodname)
860
- return self.class.ob.events.call(:no_html, classname) if !obj
861
-
862
- raise "Class '#{classname}' does not have a 'html'-method." if !obj.respond_to?(:html)
863
- return obj.html(*args)
864
- end
865
-
866
- methodname_name = "#{methodname}_name".to_sym
867
- define_method(methodname_name) do |*args|
868
- obj = self.__send__(methodname)
869
- return self.class.ob.events.call(:no_name, classname) if !obj
870
- return obj.name(*args)
871
- end
872
- end
873
- end