Module: Lore::Table_Instance

Included in:
Table_Accessor
Defined in:
lib/lore/table_instance.rb

Overview

Used as mixin for Table_Accessor. This module holds methods provided by Table_Accessor instances.

Instance Method Summary collapse

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(meth) ⇒ Object



130
131
132
133
134
135
136
# File 'lib/lore/table_instance.rb', line 130

def method_missing(meth)
  begin
    return attr[meth]
  rescue ::Exception => excep
    raise excep
  end
end

Instance Method Details

#<=>(other) ⇒ Object

See ==



256
257
258
# File 'lib/lore/table_instance.rb', line 256

def <=>(other)
  return !(self.==(other))
end

#==(other) ⇒ Object

Returns true if instance points to same records as other instance. Only compares primary key values.



230
231
232
233
234
# File 'lib/lore/table_instance.rb', line 230

def ==(other)
  result = true
  return false if self.class.to_s != other.class.to_s
  return id() == other.id()
end

#===(other) ⇒ Object

Returns true if instance points to same records as other instance, also compares non-key attribute values.



251
252
253
254
# File 'lib/lore/table_instance.rb', line 251

def ===(other)
  return false unless (self == other)
  
end

#[](clause) ⇒ Object

Explicit attribute request. Example:

Car[Vehicle.name]

In case name is attribute field in Car and Vehicle.



224
225
226
# File 'lib/lore/table_instance.rb', line 224

def [](clause)
  abs_attr(clause)
end

#[]=(key, value) ⇒ Object

Sets attribute value. Example:

instance[:name] = 'Wombat'
instance.commit


216
217
218
# File 'lib/lore/table_instance.rb', line 216

def []=(key, value)
  set_attribute_value(key, value)
end

#abs_attr(klass = nil) ⇒ Object

Returns value hash of instance attributes of a given subtype like:

{
  'id' => 123, 
  'name' => 'example'
}

Common usage:

table_accessor.abs_attr(Klass_A)[:id]  ->  123


306
307
308
309
310
311
312
313
# File 'lib/lore/table_instance.rb', line 306

def abs_attr(klass=nil)
  klass = klass.to_s if klass.instance_of? Symbol
  return get_attribute_values if klass.nil?
  return get_attribute_values[klass.table_name] if klass.kind_of? Lore::Table_Accessor
  return get_attribute_values[klass] if klass.instance_of? String
  return get_attribute_values[klass.to_s.split('.')[0..1].join('.').to_s][klass.to_s.split('.').at(-1)] if klass.instance_of? Lore::Clause

end

#attrObject

Returns value hash of instance attributes like:

{
  'schema.table.id' => 123, 
  'schema.atable.name' => 'example'
}

Common usage:

table_instance.attr[:id]  ->  123

But it is recommended to use

table_instance.id  -> 123


280
281
282
283
284
285
286
287
288
289
290
291
292
# File 'lib/lore/table_instance.rb', line 280

def attr

  if @flat_attr.nil? then
    @flat_attr = Attribute_Hash.new
    get_attribute_values.each_pair { |table, attribs| 
      attribs.each_pair { |attrib_name, value|
        @flat_attr[attrib_name] = value unless value.nil?
      }
    }
  end
  @flat_attr
  
end

#commitObject Also known as: save

Commit changes on Table_Accessor instance to DB. Results in an / several SQL update calls.

Common usage:

unit['name'] = 'changed'
unit.commit()


328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
# File 'lib/lore/table_instance.rb', line 328

def commit
# {{{

  return unless @touched
  
  input_filters = self.class.get_input_filters
  if input_filters then
    @attribute_values.each_pair { |table,keys|
      keys.each_pair { |key, value|
        @attribute_values[table][key] = input_filters[key.intern].call(value) if input_filters[key.intern]
      }
    }
  end

  begin
    Lore::Validation::Parameter_Validator.invalid_params(self.class, 
                                                         @attribute_values)
  rescue Lore::Exception::Invalid_Klass_Parameters => ikp    
  # log'n'throw: 
    ikp.log
    raise ikp
  end

  table_accessor.before_commit(self)

  Table_Updater.perform_update(table_accessor, 
                               self)

  table_accessor.after_commit(self)

  @touched = false
  
end

#deleteObject

Delete this instance from DB. Common usage:

unit = Some_Table_Accessor.select { ... }.first
unit.delete


370
371
372
373
374
375
376
377
378
379
380
# File 'lib/lore/table_instance.rb', line 370

def delete

  # Called before entity_instance.delete
  table_accessor.before_instance_delete(self)

  Table_Deleter.perform_delete(table_accessor, 
                               @attribute_values)
  # Called after entity_instance.delete
  table_accessor.after_instance_delete(self)

end

#get_attribute_valuesObject

Returns all attribute values as hash.



261
262
263
# File 'lib/lore/table_instance.rb', line 261

def get_attribute_values() # :nodoc:
  @attribute_values
end

#get_label_stringObject



100
101
102
103
104
105
106
107
108
109
110
# File 'lib/lore/table_instance.rb', line 100

def get_label_string
  value = ''
  Lore.logger.debug { 'LABEL ATTRIBS: ' << @attribute_values.inspect }
  table_accessor.get_labels.each { |label_attrib|
    Lore.logger.debug { 'LABEL_STRING: ' << label_attrib }
    label_parts = label_attrib.split('.')
    value << @attribute_values[label_parts[0..1].join('.')][label_parts[2]].to_s + ' '
  }
  value = '[no label given]' if value == ''
  return value
end

#get_primary_key_valuesObject

def



315
316
317
# File 'lib/lore/table_instance.rb', line 315

def get_primary_key_values
  @primary_key_values
end

#idObject

Return primary key value. In case primary key is composed, return it as array.



237
238
239
240
241
242
243
244
245
246
247
# File 'lib/lore/table_instance.rb', line 237

def id
  key = []
  table = table_accessor.table_name
  table_accessor.get_primary_keys[table].each { |attrib_array|
    attrib_array.each { |field|
      key << get_attribute_values[table][field]
    }
  }
  return key.first if key.length < 2
  return key
end

#inspectObject

def



382
383
384
# File 'lib/lore/table_instance.rb', line 382

def inspect
  get_attribute_values.inspect
end

#is_cached_entity?Boolean

Whether this instance has been loaded from cache or live from DB.

Returns:

  • (Boolean)


121
122
123
124
# File 'lib/lore/table_instance.rb', line 121

def is_cached_entity?
  # Set in initialize via marshal_load
  @loaded_from_cache
end

#keyObject

Returns primary key values of own table



96
97
98
# File 'lib/lore/table_instance.rb', line 96

def key
  @primary_key_values[table_accessor.get_table_name]
end

#marshal_dumpObject

Create a marshalled dump of this model instance. Returns attribute values as The only difference between model instances is their value set.



87
88
89
90
91
92
93
# File 'lib/lore/table_instance.rb', line 87

def marshal_dump
  { 
    :klass => self.class.to_s, 
    :values => get_attribute_values, 
    :joined => @joined_models
  }
end

#marshal_load(dump) ⇒ Object

Creates an instance of self from marshalled value set.



113
114
115
116
117
# File 'lib/lore/table_instance.rb', line 113

def marshal_load(dump)
  klass = eval(dump[:klass])
  dump[:joined].map { |m| m = eval(m) }
  return initialize(dump[:values], dump[:joined], :cached)
end

#move(sortpos, criteria) ⇒ Object



138
139
140
# File 'lib/lore/table_instance.rb', line 138

def move(sortpos, criteria)
  Lore::Movable.move(self, table_accessor.get_order_attr, sortpos, criteria)
end

#set_attribute_value(attrib_name, attrib_value) ⇒ Object

Set value for given attribute, e.g. for later commit. It is recommended to use random access assignment instead:

instance.set_attribute_value(:name, 'Wombat')

is same as

instance[:name] = 'Wombat'


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
199
200
201
202
203
204
205
206
207
208
209
210
211
# File 'lib/lore/table_instance.rb', line 149

def set_attribute_value(attrib_name, attrib_value)
# {{{

  if @input_filters && (@input_filters.has_key?(attrib_name.intern)) then
    attrib_value = @input_filters[attrib_name.intern].call(attrib_value)
  end

  @touched = true
  # Delete cached value of @flat_attr: 
  @flat_attr = nil 
  save_attribute_values = @attribute_values.dup
  attrib_name = attrib_name.to_s
  attrib_name_array = attrib_name.split('.')
  
  # Attrib name is implicit (no table name given). 
  # Check for ambiguous attribute name: 
  if attrib_name_array[2].nil? then
    changed_table = false
    @attribute_values.each { |table, attributes|
      
      if attributes.has_key?(attrib_name) then
        @attribute_values[table][attrib_name] = attrib_value
        changed_table = true
      elsif attributes.has_key?(attrib_name) && changed_table then
        raise Lore::Exception::Ambiguous_Attribute.new(table, 
                                                       changed_table, 
                                                       attrib_name)
      end
    }
    
  # Attrib name is explicit (also includes table name). 
  # No need to check for ambiguous attribute: 
  else 
    attrib_name_index = attrib_name_array[2]
    attrib_table      = attrib_name_array[0]+'.'+attrib_name_array[1]

    @attribute_values[attrib_table][attrib_name_index] = attrib_value
  end

  begin
    
  #  Lore::Validation::Parameter_Validator.invalid_params(
  #                          self.class, 
  #                          @attribute_values)
    
  rescue Lore::Exception::Invalid_Klass_Parameters => ikp
  
    # load saved (stable, validated) attribute_values: 
    @attribute_values = save_attribute_values
    # log'n'throw: 
    ikp.log
    raise ikp

  rescue Lore::Exception::Ambiguous_Attribute => aa
    
    # load saved (stable, validated) attribute_values: 
    @attribute_values = save_attribute_values
    # log'n'throw: 
    raise aa
    
  end
  
end

#setup_instanceObject

retreive class instance variables from concrete Table_Accessor this object is an instance of:



46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
# File 'lib/lore/table_instance.rb', line 46

def setup_instance() # :nodoc: 
  
  @touched = false

  @primary_key_values = Hash.new
  self.class.get_primary_keys.each_pair { |table, attrib_array|
    @primary_key_values[table] = Hash.new
    attrib_array.each { |field|
      begin
        pk_attrib_value = @attribute_values[table][field]
        # NOTE: Field length in Postgres is limited to 25 characters normally. 
        pk_attrib_value = @attribute_values[table][field.to_s[0..24]] unless pk_attrib_value
        @primary_key_values[table][field] = pk_attrib_value
      rescue ::Exception => excep
        # We end here if a coder tried to hack a query. We let him 
        # continue in his plans, it might make sense after all. 
      end
    }
  }

  # Applying filter to *all* attribute values, including derived attributes. 
  # This way, an output filter can be added in a derived type that does not 
  # exist in a base type. 
  output_filters = self.class.get_output_filters
  if output_filters then
    @attribute_values.each_pair { |table,keys|
      keys.each_pair { |key, value|
        @attribute_values[table][key] = output_filters[key.intern].call(value) if output_filters[key.intern]
      }
    }
  end
  
end

#table_accessorObject

def



80
81
82
# File 'lib/lore/table_instance.rb', line 80

def table_accessor
  self.class
end

#touched?Boolean

Returns:

  • (Boolean)


126
127
128
# File 'lib/lore/table_instance.rb', line 126

def touched?
  @touched
end