Class: Knj::Datarow

Inherits:
Object show all
Defined in:
lib/knj/datarow.rb

Overview

This class helps create models in a framework with Knj::Db and Knj::Objects.

Examples

db = Knj::Db.new(:type => "sqlite3", :path => "somepath.sqlite3")
ob = Knj::Objects.new(:db => db, :datarow => true, :path => "path_of_model_class_files")
user = ob.get(:User, 1) #=> <Models::User> that extends <Knj::Datarow>

Direct Known Subclasses

Translations::Translation

Constant Summary collapse

@@refs =
{}

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(data, args = nil) ⇒ Datarow

Initializes the object. This should be called from ‘Knj::Objects’ and not manually.

Examples

user = ob.get(:User, 3)


557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
# File 'lib/knj/datarow.rb', line 557

def initialize(data, args = nil)
  if data.is_a?(Hash) and data.key?(:id)
    @data = data
    @id = @data[:id].to_i
  elsif data
    @id = data.to_i
    
    classname = self.class.classname.to_sym
    if self.class.ob.ids_cache_should.key?(classname)
      #ID caching is enabled for this model - dont reload until first use.
      raise Errno::ENOENT, "ID was not found in cache: '#{id}'." if !self.class.ob.ids_cache[classname].key?(@id)
      @should_reload = true
    else
      #ID caching is not enabled - reload now to check if row exists. Else set 'should_reload'-variable if 'skip_reload' is set.
      if !args or !args[:skip_reload]
        self.reload
      else
        @should_reload = true
      end
    end
  else
    raise ArgumentError, "Could not figure out the data from '#{data.class.name}'."
  end
  
  if @id.to_i <= 0
    raise "Invalid ID: '#{@id}' from '#{@data}'." if @data
    raise "Invalid ID: '#{@id}'."
  end
end

Class Method Details

.autodelete_dataObject

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.

Examples

This will trigger Knj::Objects to automatically delete all the users pictures, when deleting the current user.

class Models::User < Knj::Datarow
  has_many [
    {:class => :Picture, :col => :user_id, :method => :pictures, :autodelete => true}
  ]
end


68
69
70
# File 'lib/knj/datarow.rb', line 68

def self.autodelete_data
  return @autodelete_data
end

.autozero_dataObject

Returns the autozero-data (if any).



73
74
75
# File 'lib/knj/datarow.rb', line 73

def self.autozero_data
  return @autozero_data
end

.classnameObject

Returns the classname of the object without any subclasses.



518
519
520
# File 'lib/knj/datarow.rb', line 518

def self.classname
  return @classname
end

.classname=(newclassname) ⇒ Object

Sets the classname to something specific in order to hack the behaviour.



523
524
525
# File 'lib/knj/datarow.rb', line 523

def self.classname=(newclassname)
  @classname = newclassname
end

.columns_sqlhelper_argsObject

Returns various data for the objects-sql-helper. This can be used to view various informations about the columns and more.



335
336
337
338
# File 'lib/knj/datarow.rb', line 335

def self.columns_sqlhelper_args
  raise "No SQLHelper arguments has been spawned yet." if !@columns_sqlhelper_args
  return @columns_sqlhelper_args
end

.dbObject

Returns the ‘Knj::Db’-object that handels this class.



25
26
27
# File 'lib/knj/datarow.rb', line 25

def self.db
  return @db
end

.depending_dataObject

This is used by ‘Knj::Objects’ to find out what other objects this class depends on. Returns the array that tells about depending data.

Examples

This will tell Knj::Objects that files depends on users. It can prevent the user from being deleted, if any files depend on it.

class Models::User < Knj::Datarow
  has_many [
    {:class => :File, :col => :user_id, :method => :files, :depends => true}
  ]
end


50
51
52
# File 'lib/knj/datarow.rb', line 50

def self.depending_data
  return @depending_data
end

.has_many(arr) ⇒ Object

This is used to define datarows that this object can have a lot of.

Examples

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.

class Models::User < Knj::Datarow
  has_many [
    [:Picture, :user_id, :pictures],
    {:class => :File, :col => :user_id, :method => :files}
  ]
end


102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
# File 'lib/knj/datarow.rb', line 102

def self.has_many(arr)
  arr.each do |val|
    if val.is_a?(Array)
      classname, colname, methodname = *val
    elsif val.is_a?(Hash)
      classname, colname, methodname = nil, nil, nil
      
      val.each do |hkey, hval|
        case hkey
          when :class
            classname = hval
          when :col
            colname = hval
          when :method
            methodname = hval
          when :depends, :autodelete, :autozero, :where
            #ignore
          else
            raise "Invalid key for 'has_many': '#{hkey}'."
        end
      end
      
      colname = "#{self.name.to_s.split("::").last.to_s.downcase}_id".to_sym if colname.to_s.empty?
      
      if val[:depends]
        @depending_data = [] if !@depending_data
        @depending_data << {
          :colname => colname,
          :classname => classname
        }
      end
      
      if val[:autodelete]
        @autodelete_data = [] if !@autodelete_data
        @autodelete_data << {
          :colname => colname,
          :classname => classname
        }
      end
      
      if val[:autozero]
        @autozero_data = [] if !@autozero_data
        @autozero_data << {
          :colname => colname,
          :classname => classname
        }
      end
    else
      raise "Unknown argument: '#{val.class.name}'."
    end
    
    raise "No classname given." if !classname
    methodname = "#{classname.to_s.downcase}s".to_sym if !methodname
    raise "No column was given for '#{self.name}' regarding has-many-class: '#{classname}'." if !colname
    
    if val.is_a?(Hash) and val.key?(:where)
      where_args = val[:where]
    else
      where_args = nil
    end
    
    define_method(methodname) do |*args, &block|
      if args and args[0]
        list_args = args[0] 
      else
        list_args = {}
      end
      
      list_args.merge!(where_args) if where_args
      list_args[colname.to_s] = self.id
      
      return self.class.ob.list(classname, list_args, &block)
    end
    
    define_method("#{methodname}_count".to_sym) do |*args|
      list_args = args[0] if args and args[0]
      list_args = {} if !list_args
      list_args[colname.to_s] = self.id
      list_args["count"] = true
      
      return self.class.ob.list(classname, list_args)
    end
    
    define_method("#{methodname}_last".to_sym) do |args|
      args = {} if !args
      return self.class.ob.list(classname, {"orderby" => [["id", "desc"]], "limit" => 1}.merge(args))
    end
    
    self.joined_tables(
      classname => {
        :where => {
          colname.to_s => {:type => :col, :name => :id}
        }
      }
    )
  end
end

.has_one(arr) ⇒ Object

This define is this object has one element of another datarow-class. It define various methods and joins based on that.

Examples

class Models::User < Knj::Datarow
  has_one [
    #Defines the method 'group', which returns a 'Group'-object by the column 'group_id'.
    :Group,

    #Defines the method 'type', which returns a 'Type'-object by the column 'type_id'.
    {:class => :Type, :col => :type_id, :method => :type}
  ]
end


211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
# File 'lib/knj/datarow.rb', line 211

def self.has_one(arr)
  arr.each do |val|
    methodname = nil
    colname = nil
    classname = nil
    
    if val.is_a?(Symbol)
      classname = val
      methodname = val.to_s.downcase.to_sym
      colname = "#{val.to_s.downcase}_id".to_sym
    elsif val.is_a?(Array)
      classname, colname, methodname = *val
    elsif val.is_a?(Hash)
      classname, colname, methodname = nil, nil, nil
      
      val.each do |hkey, hval|
        case hkey
          when :class
            classname = hval
          when :col
            colname = hval
          when :method
            methodname = hval
          when :required
            #ignore
          else
            raise "Invalid key for class '#{self.name}' functionality 'has_many': '#{hkey}'."
        end
      end
      
      if val[:required]
        colname = "#{classname.to_s.downcase}_id".to_sym if !colname
        self.required_data << {
          :col => colname,
          :class => classname
        }
      end
    else
      raise "Unknown argument-type: '#{arr.class.name}'."
    end
    
    methodname = classname.to_s.downcase if !methodname
    colname = "#{classname.to_s.downcase}_id".to_sym if !colname
    
    define_method(methodname) do
      return self.class.ob.get_try(self, colname, classname)
    end
    
    methodname_html = "#{methodname}_html".to_sym
    define_method(methodname_html) do |*args|
      obj = self.__send__(methodname)
      return self.class.ob.events.call(:no_html, classname) if !obj
      
      raise "Class '#{classname}' does not have a 'html'-method." if !obj.respond_to?(:html)
      return obj.html(*args)
    end
    
    methodname_name = "#{methodname}_name".to_sym
    define_method(methodname_name) do |*args|
      obj = self.__send__(methodname)
      return self.class.ob.events.call(:no_name, classname) if !obj
      return obj.name(*args)
    end
    
    self.joined_tables(
      classname => {
        :where => {
          "id" => {:type => :col, :name => colname}
        }
      }
    )
  end
end

.has_translation(arr) ⇒ Object

This method initializes joins, sets methods to update translations and makes the translations automatically be deleted when the object is deleted.

Examples

class Models::Article < Knj::Datarow
  #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.
  has_translation [:title, :content]
end

article = ob.get(:Article, 1)
print "The title in the current language is: '#{article.title}'."

article.title = 'Title in english if the language is english'


296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
# File 'lib/knj/datarow.rb', line 296

def self.has_translation(arr)
  @translations = [] if !@translations
  
  arr.each do |val|
    @translations << val
    
    val_dc = val.to_s.downcase
    table_name = "Translation_#{val_dc}".to_sym
    
    joined_tables(
      table_name => {
        :where => {
          "object_class" => self.name,
          "object_id" => {:type => :col, :name => :id},
          "key" => val.to_s,
          "locale" => proc{|d| _session[:locale]}
        },
        :parent_table => :Translation,
        :datarow => Knj::Translations::Translation,
        :ob => @ob
      }
    )
    
    self.define_translation_methods(:val => val, :val_dc => val_dc)
  end
end

.initialized?Boolean

Returns true if this class has been initialized.

Returns:

  • (Boolean)


55
56
57
58
# File 'lib/knj/datarow.rb', line 55

def self.initialized?
  return false if !@columns_sqlhelper_args
  return true
end

.is_nullstamp?(stamp) ⇒ Boolean

This tests if a certain string is a date-null-stamp.

Examples

time_str = dbrow[:date]
print "No valid date on the row." if Knj::Datarow.is_nullstamp?(time_str)

Returns:

  • (Boolean)


88
89
90
91
# File 'lib/knj/datarow.rb', line 88

def self.is_nullstamp?(stamp)
  return true if !stamp or stamp == "0000-00-00 00:00:00" or stamp == "0000-00-00"
  return false
end

.joined_tables(hash) ⇒ Object

Returns data about joined tables for this class.



329
330
331
332
# File 'lib/knj/datarow.rb', line 329

def self.joined_tables(hash)
  @columns_joined_tables = {} if !@columns_joined_tables
  @columns_joined_tables.merge!(hash)
end

.list(d, &block) ⇒ Object

This method helps returning objects and supports various arguments. It should be called by Object#list.

Examples

ob.list(:User, {"username_lower" => "john doe"}) do |user|
  print user.id
end

array = ob.list(:User, {"id" => 1})
print array.length


430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
# File 'lib/knj/datarow.rb', line 430

def self.list(d, &block)
  args = d.args
  
  if args["count"]
    count = true
    args.delete("count")
    sql = "SELECT COUNT(#{@table_str}.#{@sep_col}id#{@sep_col}) AS count"
  elsif args["select_col_as_array"]
    select_col_as_array = true
    sql = "SELECT #{@table_str}.#{@sep_col}#{args["select_col_as_array"]}#{@sep_col} AS id"
    args.delete("select_col_as_array")
  else
    sql = "SELECT #{@table_str}.*"
  end
  
  qargs = nil
  ret = self.list_helper(d)
  
  sql << " FROM #{@table_str}"
  sql << ret[:sql_joins]
  sql << " WHERE 1=1"
  sql << ret[:sql_where]
  
  args.each do |key, val|
    case key
      when "return_sql"
        #ignore
      when :cloned_ubuf
        qargs = {:cloned_ubuf => true}
      else
        raise "Invalid key: '#{key}' for '#{self.name}'. Valid keys are: '#{@columns_sqlhelper_args[:cols].keys.sort}'. Date-keys: '#{@columns_sqlhelper_args[:cols_date]}'."
    end
  end
  
  #The count will bug if there is a group-by-statement.
  grp_shown = false
  if !count and !ret[:sql_groupby]
    sql << " GROUP BY #{@table_str}.#{@sep_col}id#{@sep_col}"
    grp_shown = true
  end
  
  if ret[:sql_groupby]
    if !grp_shown
      sql << " GROUP BY"
    else
      sql << ", "
    end
    
    sql << ret[:sql_groupby]
  end
  
  sql << ret[:sql_order]
  sql << ret[:sql_limit]
  
  return sql.to_s if args["return_sql"]
  
  if select_col_as_array
    enum = Enumerator.new do |yielder|
      @db.q(sql, qargs) do |data|
        yielder << data[:id]
      end
    end
    
    if block
      enum.each(&block)
      return nil
    elsif @ob.args[:array_enum]
      return Array_enumerator.new(enum)
    else
      return enum.to_a
    end
  elsif count
    ret = @db.query(sql).fetch
    return ret[:count].to_i if ret
    return 0
  end
  
  return @ob.list_bysql(self.classname, sql, qargs, &block)
end

.list_helper(d) ⇒ Object

Helps call ‘sqlhelper’ on Knj::Objects to generate SQL-strings.



511
512
513
514
515
# File 'lib/knj/datarow.rb', line 511

def self.list_helper(d)
  self.load_columns(d) if !@columns_sqlhelper_args
  @columns_sqlhelper_args[:table] = @table
  return @ob.sqlhelper(d.args, @columns_sqlhelper_args)
end

.load_columns(d) ⇒ Object

Called by Knj::Objects to initialize the model and load column-data on-the-fly.



341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
# File 'lib/knj/datarow.rb', line 341

def self.load_columns(d)
  @ob = d.ob
  @db = d.db
  
  @classname = self.name.split("::").last.to_sym if !@classname
  @table = @classname if !@table
  @mutex = Monitor.new if !@mutex
  
  #Cache these to avoid method-lookups.
  @sep_col = @db.sep_col
  @sep_table = @db.sep_table
  @table_str = "#{@sep_table}#{@db.esc_table(@table)}#{@sep_table}"
  
  @mutex.synchronize do
    inst_methods = self.instance_methods(false)
    
    sqlhelper_args = {
      :db => @db,
      :table => @table,
      :cols_bools => [],
      :cols_date => [],
      :cols_dbrows => [],
      :cols_num => [],
      :cols_str => [],
      :cols => {}
    }
    
    sqlhelper_args[:table] = @table
    
    @db.tables[table].columns do |col_obj|
      col_name = col_obj.name
      col_type = col_obj.type
      col_type = :int if col_type == :bigint or col_type == :tinyint or col_type == :mediumint or col_type == :smallint
      sqlhelper_args[:cols][col_name] = true
      
      self.define_bool_methods(:inst_methods => inst_methods, :col_name => col_name)
      
      if col_type == :enum and col_obj.maxlength == "'0','1'"
        sqlhelper_args[:cols_bools] << col_name
      elsif col_type == :int and col_name.slice(-3, 3) == "_id"
        sqlhelper_args[:cols_dbrows] << col_name
      elsif col_type == :int or col_type == :decimal
        sqlhelper_args[:cols_num] << col_name
      elsif col_type == :varchar or col_type == :text or col_type == :enum
        sqlhelper_args[:cols_str] << col_name
      elsif col_type == :date or col_type == :datetime
        sqlhelper_args[:cols_date] << col_name
        self.define_date_methods(:inst_methods => inst_methods, :col_name => col_name)
      end
      
      if col_type == :int or col_type == :decimal
        self.define_numeric_methods(:inst_methods => inst_methods, :col_name => col_name)
      end
      
      if col_type == :int or col_type == :varchar
        self.define_text_methods(:inst_methods => inst_methods, :col_name => col_name)
      end
      
      if col_type == :time
        self.define_time_methods(:inst_methods => inst_methods, :col_name => col_name)
      end
    end
    
    if @columns_joined_tables
      @columns_joined_tables.each do |table_name, table_data|
        table_data[:where].each do |key, val|
          val[:table] = @table if val.is_a?(Hash) and !val.key?(:table) and val[:type].to_sym == :col
        end
        
        table_data[:datarow] = @ob.args[:module].const_get(table_name.to_sym) if !table_data.key?(:datarow)
      end
      
      sqlhelper_args[:joined_tables] = @columns_joined_tables
    end
    
    @columns_sqlhelper_args = sqlhelper_args
  end
  
  self.init_class(d) if self.respond_to?(:init_class)
end

.obObject

Returns the ‘Knj::Objects’-object that handels this class.



20
21
22
# File 'lib/knj/datarow.rb', line 20

def self.ob
  return @ob
end

.required_dataObject

This is used by ‘Knj::Objects’ to find out what data is required for this class. Returns the array that tells about required data.

Examples

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.

class Models::User < Knj::Datarow
  has_one [
    {:class => :Group, :col => :group_id, :method => :group, :required => true}
  ]
end


37
38
39
40
# File 'lib/knj/datarow.rb', line 37

def self.required_data
  @required_data = [] if !@required_data
  return @required_data
end

.tableObject

Returns the table-name that should be used for this datarow.

Examples

db.query("SELECT * FROM `#{Models::User.table}` WHERE username = 'John Doe'") do |data|
  print data[:id]
end


532
533
534
# File 'lib/knj/datarow.rb', line 532

def self.table
  return @table
end

.table=(newtable) ⇒ Object

This can be used to manually set the table-name. Useful when meta-programming classes that extends the datarow-class.

Examples

Models::User.table = "prefix_User"


539
540
541
542
# File 'lib/knj/datarow.rb', line 539

def self.table=(newtable)
  @table = newtable
  @columns_sqlhelper_args[:table] = @table if @columns_sqlhelper_args.is_a?(Hash)
end

.translationsObject

This returns all translations for this datarow-class.



324
325
326
# File 'lib/knj/datarow.rb', line 324

def self.translations
  return @translations
end

Instance Method Details

#[](key) ⇒ Object

Returns a specific data from the object by key.

print "Username: #{user[:username]}\n"
print "ID: #{user[:id]}\n"
print "ID again: #{user.id}\n"


667
668
669
670
671
672
673
674
# File 'lib/knj/datarow.rb', line 667

def [](key)
  raise "Key was not a symbol: '#{key.class.name}'." if !key.is_a?(Symbol)
  return @id if !@data and key == :id and @id
  self.reload if @should_reload
  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
  return @data[key] if @data.key?(key)
  raise "No such key: '#{key}' on '#{self.class.name}' (#{@data.keys.join(", ")}) (#{@should_reload})."
end

#[]=(key, value) ⇒ Object

Writes/updates a keys value on the object.

user = ob.get_by(:User, {"username" => "John Doe"})
user[:username] = 'New username'


679
680
681
682
# File 'lib/knj/datarow.rb', line 679

def []=(key, value)
  self.update(key.to_sym => value)
  self.should_reload
end

#__object_unique_id__Object

This enable Wref to not return the wrong object.



692
693
694
695
# File 'lib/knj/datarow.rb', line 692

def __object_unique_id__
  return 0 if self.deleted?
  return self.id
end

#dataObject

Returns the data-hash that contains all the data from the database.



608
609
610
611
# File 'lib/knj/datarow.rb', line 608

def data
  self.reload if @should_reload
  return @data
end

#dbObject

Returns the Knj::Db which handels this model.



15
16
17
# File 'lib/knj/datarow.rb', line 15

def db
  return self.class.db
end

#deleted?Boolean

Returns true if the object has been deleted.

Examples

print "That user is deleted." if user.deleted?

Returns:

  • (Boolean)


641
642
643
644
# File 'lib/knj/datarow.rb', line 641

def deleted?
  return true if !@data and !@id
  return false
end

#deleted_from_db?Boolean

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.

Examples

print “That user is deleted.” if user.deleted_from_db?

Returns:

  • (Boolean)


649
650
651
652
653
654
655
656
657
658
659
660
661
# File 'lib/knj/datarow.rb', line 649

def deleted_from_db?
  #Try to avoid db-query if object is already deleted.
  return true if self.deleted?
  
  #Try to reload data. Destroy object and return true if the row is gone from the database.
  begin
    self.reload
    return false
  rescue Errno::ENOENT
    self.destroy
    return true
  end
end

#destroyObject

Forcefully destroys the object. This is done after deleting it and should not be called manually.



623
624
625
626
627
# File 'lib/knj/datarow.rb', line 623

def destroy
  @id = nil
  @data = nil
  @should_reload = nil
end

#each(*args, &block) ⇒ Object

Loops through the data on the object.

Examples

user = ob.get(:User, 1)
user.each do |key, val|
  print "#{key}: #{val}\n" #=> username: John Doe
end


730
731
732
733
# File 'lib/knj/datarow.rb', line 730

def each(*args, &block)
  self.reload if @should_reload
  return @data.each(*args, &block)
end

#htmlObject

Returns the HTML for making a link to the object.



754
755
756
# File 'lib/knj/datarow.rb', line 754

def html
  return "<a href=\"#{Knj::Web.ahref_parse(self.url)}\">#{self.name_html}</a>"
end

#idObject

Returns the objects ID.

Raises:

  • (Errno::ENOENT)


685
686
687
688
689
# File 'lib/knj/datarow.rb', line 685

def id
  raise Errno::ENOENT, "This object has been deleted." if self.deleted?
  raise "No ID on object." if !@id
  return @id
end

#is_knj?Boolean

This helps various parts of the framework determine if this is a datarow class without requiring it.

Examples

print "This is a knj-object." if obj.respond_to?("is_knj?")

Returns:

  • (Boolean)


80
81
82
# File 'lib/knj/datarow.rb', line 80

def is_knj?
  return true
end

#key?(key) ⇒ Boolean Also known as: has_key?

Returns true if that key exists on the object.

Examples

print "Looks like the user has a name." if user.key?(:name)

Returns:

  • (Boolean)


632
633
634
635
# File 'lib/knj/datarow.rb', line 632

def key?(key)
  self.reload if @should_reload
  return @data.key?(key.to_sym)
end

#nameObject Also known as: title

Tries to figure out, and returns, the possible name or title for the object.



698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
# File 'lib/knj/datarow.rb', line 698

def name
  self.reload if @should_reload
  
  if @data.key?(:title)
    return @data[:title]
  elsif @data.key?(:name)
    return @data[:name]
  end
  
  obj_methods = self.class.instance_methods(false)
  [:name, :title].each do |method_name|
    return self.method(method_name).call if obj_methods.index(method_name)
  end
  
  raise "Couldnt figure out the title/name of the object on class #{self.class.name}."
end

#name_htmlObject

Calls the name-method and returns a HTML-escaped value. Also “[no name]” if the name is empty.



716
717
718
719
720
# File 'lib/knj/datarow.rb', line 716

def name_html
  name_str = self.name.to_s
  name_str = "[no name]" if name_str.length <= 0
  return name_str
end

#obObject

Returns the Knj::Objects which handels this model.



10
11
12
# File 'lib/knj/datarow.rb', line 10

def ob
  return self.class.ob
end

#reloadObject

Reloads the data from the database.

Examples

old_username = user[:username]
user.reload
print "The username changed in the database!" if user[:username] != old_username

Raises:

  • (Errno::ENOENT)


592
593
594
595
596
# File 'lib/knj/datarow.rb', line 592

def reload
  @data = self.class.db.single(self.class.table, {:id => @id})
  raise Errno::ENOENT, "Could not find any data for the object with ID: '#{@id}' in the table '#{self.class.table}'." if !@data
  @should_reload = false
end

#should_reloadObject

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.

Examples

obj = _ob.get(:User, 5)
obj.should_reload


602
603
604
605
# File 'lib/knj/datarow.rb', line 602

def should_reload
  @should_reload = true
  @data = nil
end

#tableObject

Returns the class-name but without having to call the class-table-method. To make code look shorter.

Examples

user = ob.get_by(:User, {:username => 'John Doe'})
db.query("SELECT * FROM `#{user.table}` WHERE username = 'John Doe'") do |data|
  print data[:id]
end


550
551
552
# File 'lib/knj/datarow.rb', line 550

def table
  return self.class.table
end

#to_hashObject

Hash-compatible.



736
737
738
739
# File 'lib/knj/datarow.rb', line 736

def to_hash
  self.reload if @should_reload
  return @data.clone
end

#update(newdata) ⇒ Object

Writes/updates new data for the object.

Examples

user.update(:username => 'New username', :date_changed => Time.now)


616
617
618
619
620
# File 'lib/knj/datarow.rb', line 616

def update(newdata)
  self.class.db.update(self.class.table, newdata, {:id => @id})
  self.should_reload
  self.class.ob.call("object" => self, "signal" => "update")
end

#urlObject

Returns a default-URL to show the object.



742
743
744
745
# File 'lib/knj/datarow.rb', line 742

def url
  cname = self.class.classname.to_s.downcase
  return "?show=#{cname}_show&#{cname}_id=#{self.id}"
end

#url_editObject

Returns the URL for editting the object.



748
749
750
751
# File 'lib/knj/datarow.rb', line 748

def url_edit
  cname = self.class.classname.to_s.downcase
  return "?show=#{cname}_edit&#{cname}_id=#{self.id}"
end