Class: Lore::Table_Accessor

Inherits:
Object show all
Extended by:
Aspect, Cache::Cacheable, Model_Shortcuts, Polymorphic_Class_Methods, Prepare, Prepare_Class_Methods, Query_Shortcuts
Includes:
Model_Instance, Polymorphic_Instance_Methods, Prepare
Defined in:
lib/lore/model/polymorphic.rb,
lib/lore/model/table_accessor.rb

Direct Known Subclasses

Model

Constant Summary collapse

@@logger =
Lore.logger

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Aspect

after_commit, after_instance_delete, before_commit, before_instance_delete

Methods included from Prepare

define_default_preps

Methods included from Query_Shortcuts

all, all_with, delete, delete_all, each, find, set, value_of

Methods included from Model_Shortcuts

html_escape_values_of

Methods included from Polymorphic_Class_Methods

is_polymorphic, is_polymorphic?, polymorphic_attribute, polymorphic_attribute_index, select_polymorphic

Methods included from Prepare_Class_Methods

by_id, execute_prepared, prepare

Methods included from Cache::Cacheable

create_entity_cache, entity_cache, flush_entity_cache, read_entity_cache, use_entity_cache

Methods included from Polymorphic_Instance_Methods

#get_concrete_model

Methods included from Model_Instance

#<=>, #==, #===, #[], #abs_attr, #attr, #attribute_values, #commit, #delete, #get_attribute_value_map, #get_attribute_values, #get_label_string, #get_primary_key_value_map, #get_primary_key_values, #id, #inspect, #is_cached_entity?, #key, #marshal_dump, #marshal_load, #method_missing, #obj_id, #pkey, #pkeys, #set_attribute_value, #set_attribute_values, #table_accessor, #touch, #touched?, #untouch, #update_pkey_values, #update_values

Constructor Details

#initialize(values, joined_models = [], cache = nil) ⇒ Table_Accessor

Constructor is usually wrapped by e.g. self.load or Model_Instancemarshal_load. Constructor just accepts a value hash, and returns a Table_Accessor instance holding it. Note that this method is operating on a Table_Accessor instance, not on class Table_Accessor itself.



94
95
96
97
98
99
100
101
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
# File 'lib/lore/model/table_accessor.rb', line 94

def initialize(values, joined_models=[], cache=nil) 
# {{{
  # Note: 
  # 90% of additional time used on a query compared to 
  # plain, unprocessed SQL queries is consumed here - so 
  # be efficient! 
  
  @loaded_from_cache = (cache == :cached)
  @joined_models     = joined_models

  if @loaded_from_cache then
    @attribute_values_flat = values
  else
    @attribute_values_flat = {}
    field_index = 0
    models  = [ self.class ]
    models |= joined_models
    models.each { |model|
      tables = model.all_table_names
      fields = model.get_fields_flat
      # Increment over all fields, do not use each_with_index
      fields.each { |field|
        # First value set has precedence
        @attribute_values_flat[field] ||= values[field_index] 
        field_index += 1 
      }
    }
    # 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. 

    return if self.class.output_filters_disabled?

    output_filters = self.class.__filters__.output_filters
    @attribute_values_flat.each_pair { |attribute, value|
      filter = output_filters[attribute]
      @attribute_values_flat[attribute] = filter.call(value) if filter
    }
  end
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method in the class Lore::Model_Instance

Class Method Details

.[](attribute_name) ⇒ Object

Returns full attribute name of given attribute



599
600
601
602
# File 'lib/lore/model/table_accessor.rb', line 599

def self.[](attribute_name)
# {{{
  return "#{@table_name}.#{attribute_name}"
end

.__associations__Object



57
58
59
# File 'lib/lore/model/table_accessor.rb', line 57

def self.__associations__
  @__associations__
end

.__attributes__Object



60
61
62
# File 'lib/lore/model/table_accessor.rb', line 60

def self.__attributes__
  @__attributes__
end

.__delete_strategy__Object



73
74
75
# File 'lib/lore/model/table_accessor.rb', line 73

def self.__delete_strategy__
  @delete_strategy
end

.__filters__Object



54
55
56
# File 'lib/lore/model/table_accessor.rb', line 54

def self.__filters__
  @__filters__
end

.__insert_strategy__Object



67
68
69
# File 'lib/lore/model/table_accessor.rb', line 67

def self.__insert_strategy__
  @insert_strategy
end

.__select_strategy__Object



64
65
66
# File 'lib/lore/model/table_accessor.rb', line 64

def self.__select_strategy__
  @select_strategy
end

.__update_strategy__Object



70
71
72
# File 'lib/lore/model/table_accessor.rb', line 70

def self.__update_strategy__
  @update_strategy
end

.all_table_namesObject

Returns all (i.e. including joined) tables as Array of Strings, ordered by join order.



340
341
342
343
344
345
346
# File 'lib/lore/model/table_accessor.rb', line 340

def self.all_table_names
# {{{
  return @table_names if @table_names
  @table_names = [@table_name]
  @table_names += @__associations__.joins.keys_flat
  return @table_names
end

.create(attrib_values = {}) ⇒ Object

Returns a new Table_Accessor instance by inserting given attribute values into db and returning an instance for further operations.

Raises:

  • (::Exception)


735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
# File 'lib/lore/model/table_accessor.rb', line 735

def self.create(attrib_values={})
# {{{
  attrib_values[:concrete_model] = self.to_s 
  before_create(attrib_values)

  input_filters = @__filters__.input_filters
  attrib_key  = ''
  attrib_name = ''

  attrib_values.each_pair { |attrib_name, attrib_value|
    if attrib_name.instance_of? Symbol then 
      attrib_key = attrib_name
    else 
      attrib_key = attrib_name.split('.')[-1].to_sym
    end
    
    if (input_filters && input_filters[attrib_key]) then
      attrib_values[attrib_name] = input_filters[attrib_key].call(attrib_value) 
    end
  }
  after_filters(attrib_values)
  
  values = distribute_attrib_values(attrib_values)
  
  before_validation(values)
  if @__associations__.polymorphics then
    Lore.logger.debug { "Polymorphic create on #{self.to_s}" }
    @__associations__.polymorphics.each_pair { |table, model_field|
      values[table][model_field] = self.to_s
    }
  end
  Lore::Validation::Parameter_Validator.validate(self, values)

  before_insert(attrib_values)

  # retreive all final attrib values after insert: (this way, also 
  # sequence values are resolved): 
  
  attrib_values = @insert_strategy.perform_insert(values)
  
  # This would be a double check, as self.load already filters 
  # non-primary key attributes
  select_keys = Hash.new
  @__associations__.primary_keys[table_name].each { |key|
    select_keys["#{table_name}.#{key}"] = attrib_values[table_name][key]
  }
  
  obj = self.load(select_keys)
  raise ::Exception.new("Could not load created instance of #{self.to_s}: #{select_keys.inspect}") unless obj
  after_create(obj)
  
  return obj
  
end

.delete(value_keys = nil, &block) ⇒ Object

Delete this object and use Table_Deleter to delete its entity tuple from database.



858
859
860
861
862
863
864
865
866
867
# File 'lib/lore/model/table_accessor.rb', line 858

def self.delete(value_keys=nil, &block)
# {{{
  if value_keys then
    before_delete(value_keys)
    @delete_strategy.perform_delete(value_keys)
    after_delete(value_keys)
  else 
    @delete_strategy.block_delete(&block)
  end
end

.disable_output_filtersObject

}}}



201
202
203
# File 'lib/lore/model/table_accessor.rb', line 201

def self.disable_output_filters
  @output_filters_disabled = true
end

.distribute_attrib_values(attrib_values) ⇒ Object

}}}



700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
# File 'lib/lore/model/table_accessor.rb', line 700

def self.distribute_attrib_values(attrib_values)
# {{{
  values = {}
  # Predefine
  attrib_name_array = []
  # distribute attrib names to tables: 
  @__attributes__.fields().each_pair { |table, attribs|
    table_values = {}
    attrib_name_array = []

    attrib_values.each_pair { |attrib_name, attrib_value|
      attrib_name_array   = attrib_name.split('.') unless attrib_name.instance_of?(Symbol)
      attrib_name_array ||= []
      attrib_short_name   = false
      if attrib_name_array.at(2)
        attrib_short_name = attrib_name_array.at(2)
      else
        attrib_name = attrib_name.to_sym
      end
      
      if attribs.include? attrib_name then
        table_values[attrib_name] = attrib_value
      elsif attrib_short_name && 
            attribs.include?(attrib_short_name) &&
            table == "#{attrib_name_array.at(0)}.#{attrib_name_array.at(1)}" then
        table_values[attrib_name_array.at(2)] = attrib_value
      end
    }
    values[table] = table_values
  }
  values
end

.enable_output_filtersObject



204
205
206
# File 'lib/lore/model/table_accessor.rb', line 204

def self.enable_output_filters
  @output_filters_disabled = false
end

.explicit_insert(keys) ⇒ Object

Wrap explicit select. Example:

SomeModule::SomeAccessor.explicit_insert({
                      table_name_A =>
                        {'some_field'=>'2', 
                        'other_field'=>'3'}, 
                      table_name_A =>
                        {'another_field'=>'5'}
                     })

Note that field in ‘field’=>‘value’ is exactly the field name in the table (e.g. table_name_A) it holds.



674
675
676
677
# File 'lib/lore/model/table_accessor.rb', line 674

def self.explicit_insert(keys)
# {{{
  @insert_strategy.perform_insert(keys)
end

.get(*key_values) ⇒ Object

Load an instance by only providing primary key values. This is useful for polymorphic treatment of models, as you don’t have to know about primary key names.

Example:

The_Model.get(123)

Resolves to

The_Model.load(:the_model_id => 123)

If there is more than one primary key attribute, key values have to be provided in the same order they are specified in the database.



847
848
849
850
851
852
853
854
# File 'lib/lore/model/table_accessor.rb', line 847

def self.get(*key_values)
# {{{
  pkeys = {}
  get_primary_keys[table_name].uniq.each_with_index { |pkey, idx|
    pkeys[pkey] = key_values.at(idx)
  }
  load(pkeys)
end

.get_fieldsObject

Returns all attribute fields as Hash of Array of Strings, in the same order as defined in the table, mapped by table names. Example: (Article < Content)

Article.get_fields 
--> 
{ 
  'public.content' => [ :content_id, :title, :date ], 
  'public.article' => [ :author, :lead_in ]
}

Also see get_fields_flat.



362
363
364
365
# File 'lib/lore/model/table_accessor.rb', line 362

def self.get_fields
  @fields ||= @__attributes__.fields
  @fields
end

.get_fields_flatObject

Returns all attribute fields as Hash of Array of Strings, in the same order as defined in the table, mapped by table names. Example: (Article < Content)

Article.get_fields_flat
--> 
[ :content_id, :title, :date, :author, :lead_in

Also see example in documentation to get_fields.



377
378
379
380
# File 'lib/lore/model/table_accessor.rb', line 377

def self.get_fields_flat
  @fields_flat ||= @__attributes__.fields_flat
  @fields_flat
end

.get_own_primary_keysObject

Return primary key names of own table only, i.e. skipping inherited ones.



287
288
289
290
291
292
293
# File 'lib/lore/model/table_accessor.rb', line 287

def self.get_own_primary_keys
# {{{
  if !@own_primary_keys then
    @own_primary_keys = @__attributes__.primary_keys[@table_name].uniq
  end
  @own_primary_keys
end

.get_primary_keysObject

Recursively gets primary keys from parent, if own primary keys don’t have been set, yet: Returns all derived primary keys WITHOUT OWN PKEYS.



280
281
282
283
# File 'lib/lore/model/table_accessor.rb', line 280

def self.get_primary_keys 
# {{{
  @__attributes__.primary_keys
end

.get_sequencesObject

Recursively gets sequences from parent, if own sequences don’t have been set, yet:



309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
# File 'lib/lore/model/table_accessor.rb', line 309

def self.get_sequences 
# {{{
  
  if @sequences.nil? then
    if @is_a_klasses.nil? then
      return Hash.new
    else
      seq_map = Hash.new
      @is_a_klasses.each_pair { |foreign_key,k|
        seq_map[k.table_name] = k.get_sequences
      }
      return seq_map
    end
  else
    return @sequences
  end

end

.insert(keys) ⇒ Object

Wrap default select. Example:

SomeModule::SomeAccessor.insert({
                'some_field'=>'2', 
                'other_field'=>'3', 
                'another_field'=>'5'
                })

Note that field in ‘field’=>‘value’ is exactly the field name in the table it holds. Table_Accessor.insert basically resolves an explicit hash and passes it to Table_Accessor.explicit_insert.



689
690
691
692
693
694
695
696
697
698
# File 'lib/lore/model/table_accessor.rb', line 689

def self.insert(keys)
# {{{
  # Sequence values only are known after insert operation, 
  # so we have to retreive the complete key_hash back from 
  # Table_Inserter.perform_insert: 
  key_hash = @insert_strategy.perform_insert(keys)
  # key_hash has been extended by sequence_values now, so 
  # we return it: 
  key_hash
end

.inspectObject

Inspect method



272
273
274
275
# File 'lib/lore/model/table_accessor.rb', line 272

def self.inspect
# {{{
  'Lore::Table_Accessor: ' << self.to_s
end

.is_a?(model) ⇒ Boolean

Returns:

  • (Boolean)


480
481
482
# File 'lib/lore/model/table_accessor.rb', line 480

def is_a?(model)
  org_is_a?(model) || @__associations__ &&  @__associations__.has_joined_model?(model)
end

.key_arrayObject

}}}



295
296
297
298
299
300
301
302
303
304
305
# File 'lib/lore/model/table_accessor.rb', line 295

def self.key_array()
# {{{
  # TODO: Use __attributes__ here
  keys = Array.new
  get_primary_keys.each_pair { |table, attribs|
    attribs.each { |attrib|
      keys.push attrib
    }
  }
  return keys
end

.load(keys) ⇒ Object

Return new Table_Accessor instance by loading an existing entry from table if present, or false if no entry has been found. Accepts any combination of :primary_key => ‘value’ Also allows inherited primary keys.



794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
# File 'lib/lore/model/table_accessor.rb', line 794

def self.load(keys)
# {{{
  before_load(keys)

  select_keys = {}
  value = false
  @__associations__.primary_keys.each_pair { |table, pkeys| 
    pkeys.each { |attrib_name|
      full_attrib_name = "#{table}.#{attrib_name}"
      value   = keys[full_attrib_name]   # The more explicit, the better. 
      value ||= keys[attrib_name.to_sym] # Symbols are supposed to be most frequently used
      value ||= keys[attrib_name.to_s] 
      select_keys[full_attrib_name] = value unless value.nil?
    }
  }

  return false if select_keys.empty? 
  
  # We have to perform a select here instead of returning 
  # the instance with given attribute values, as this is the 
  # only way to retreive attribute values set in the DB via
  # default values, triggers, etc.
  c = Clause.new
  select_keys.each_pair { |k,v|
    c & (Clause.new(k.to_s.dup) == v.to_s)
  }

  instance = self.select { |inst|
    inst.where(c)
    inst.limit(1)
  }.first

  return false unless instance
  return instance

end

.log(message, level = :debug) ⇒ Object



42
43
44
# File 'lib/lore/model/table_accessor.rb', line 42

def self.log(message, level=:debug)
  @@logger.debug(message)
end

.method_missing(meth) ⇒ Object

Simulates inheritance: Delegate missing methods to parent Table_Accessor.

Raises:

  • (::Exception)


261
262
263
264
265
266
267
268
269
# File 'lib/lore/model/table_accessor.rb', line 261

def self.method_missing(meth)
# {{{ 
  if @is_a_klasses then
    @is_a_klasses.each_pair { |foreign_key, k|
      return (k.__send__(meth.to_s)) if k.respond_to? meth
    }
  end
  raise ::Exception.new('Undefined method '<< meth.to_s << ' for ' << self.to_s)
end

.new_polymorphic(values, joined_models = []) ⇒ Object

To be used indirectly via Model.polymorphic_select Parameter ‘values’ contains values for all fields returned from a polmymorphic select query.



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
199
# File 'lib/lore/model/table_accessor.rb', line 138

def self.new_polymorphic(values, joined_models=[])
# {{{
  # Parameter 'values' contains values for all fields returned from a 
  # polmymorphic select query. It thus contains (empty) fields that are 
  # not relevant for this model instance. 
  # Those have to be filtered out by resolving field indices and their 
  # offsets. 
  #
  # Model.new expects values in following order: 
  #
  #   [ own fields, base klass fields, aggregeate klass fields, custom join fields ]
  #
  # But polymorphic selects return: 
  #
  #   [ polymorphic base klass fields, own fields, other base klass fields ... ]
  #
  # So value array has to be transformed accordingly, which is rather 
  # complicated. 
  #
  fields               = get_fields_flat
  concrete_model_index = 0 
  concrete_model_name  = values[polymorphic_attribute_index]
  concrete_model       = eval(concrete_model_name)

  # We need to know where to inject values of the polymorphic 
  # base model: 
  concrete_base_joins   = concrete_model.__associations__.joins
  concrete_base_klasses = concrete_model.__associations__.base_klasses
  inject_index          = concrete_model.__attributes__.num_own_fields
  # Be sure to iterate just like in 
  # Table_Select.build_joined_query strategy!
  concrete_base_joins.each_pair { |table, foreign_base_tables|
    # Ignore base tables - their fields are added automatically 
    # via __attributes__.num_fields below. 
    base_model = concrete_base_klasses[table].first
    break if base_model == self # Offset ends with own fields
    inject_index += base_model.__attributes__.num_fields
  }

  # Amount of polymorphic fields defined in this model
  polymorphic_num_fields = @__attributes__.num_fields()
  # Field offset should point to index where concrete 
  # fields begin. 
  field_offset = 0 
  @__associations__.concrete_models.each { |cm|
    break if cm == concrete_model 
    concrete_model_index += 1
    field_offset += (cm.__attributes__.num_fields - polymorphic_num_fields)
  }

  field_offset_end = (field_offset + concrete_model.__attributes__.num_fields) 
  basic_values     = values[0...polymorphic_num_fields]
  concrete_values  = values[(polymorphic_num_fields + field_offset)...field_offset_end]
  
  # Basic values from polymorphic base model have to be injected 
  # into concrete values at inject_index. 
  instance_values  = concrete_values[0...inject_index]
  instance_values += basic_values # Inject happens here
  instance_values += concrete_values[inject_index..-1]

  concrete_model.new(instance_values, joined_models)
end

.org_is_a?Object



479
# File 'lib/lore/model/table_accessor.rb', line 479

alias org_is_a? is_a?

.output_filters_disabled?Boolean

Returns:

  • (Boolean)


208
209
210
# File 'lib/lore/model/table_accessor.rb', line 208

def self.output_filters_disabled? 
  @output_filters_disabled || false
end

.polymorphic_select(clause = nil, &block) ⇒ Object



623
624
625
626
627
628
629
630
# File 'lib/lore/model/table_accessor.rb', line 623

def self.polymorphic_select(clause=nil, &block)
# {{{
  if(!clause.nil? && !clause.to_s.include?('*,')) then
    query_string = @select_strategy.select_query(clause.to_s, nil, true, &block)
    return Clause.new(query_string[:query])
  end
  return Select_Query.new(self, clause.to_s, true, &block)
end

.polymorphic_select_query(clause = nil, &block) ⇒ Object

}}}



632
633
634
# File 'lib/lore/model/table_accessor.rb', line 632

def self.polymorphic_select_query(clause=nil, &block)
  query_string = @select_strategy.select_query(clause.to_s, nil, true, &block)
end

.polymorphic_select_value(what, &block) ⇒ Object

Same as select, but returns scalar value.



651
652
653
654
655
656
657
# File 'lib/lore/model/table_accessor.rb', line 651

def self.polymorphic_select_value(what, &block)
# {{{
  db_result = @select_strategy.select(what, true, &block)
  row = db_result.get_row
  return row.first if row.first
  return {}
end

.polymorphic_select_values(what, &block) ⇒ Object

}}}



659
660
661
662
# File 'lib/lore/model/table_accessor.rb', line 659

def self.polymorphic_select_values(what, &block) 
# {{{
  @select_strategy.select(what, true, &block).get_rows
end

.select(clause = nil, &block) ⇒ Object

def }}}



610
611
612
613
614
615
616
617
# File 'lib/lore/model/table_accessor.rb', line 610

def self.select(clause=nil, &block)
# {{{
  if(!clause.nil? && !clause.to_s.include?('*,')) then
    query_string = @select_strategy.select_query(clause.to_s, &block)
    return Clause.new(query_string[:query])
  end
  return Select_Query.new(self, clause.to_s, &block)
end

.select_query(clause = nil, &block) ⇒ Object

}}}



619
620
621
# File 'lib/lore/model/table_accessor.rb', line 619

def self.select_query(clause=nil, &block)
  query_string = @select_strategy.select_query(clause.to_s, &block)
end

.select_value(what, &block) ⇒ Object

Same as select, but returns scalar value.



637
638
639
640
641
642
643
# File 'lib/lore/model/table_accessor.rb', line 637

def self.select_value(what, &block)
# {{{
  db_result = @select_strategy.select(what, &block)
  row = db_result.get_row
  return row.first if row.first
  return {}
end

.select_values(what, &block) ⇒ Object

}}}



645
646
647
648
# File 'lib/lore/model/table_accessor.rb', line 645

def self.select_values(what, &block) 
# {{{
  @select_strategy.select(what, &block).get_rows
end

.set_sequences(arg) ⇒ Object

}}}



328
329
330
331
# File 'lib/lore/model/table_accessor.rb', line 328

def self.set_sequences(arg) # :nodoc:
# {{{
  @sequences = arg
end

.table_nameObject

Returns base table of this model as String.



334
335
336
# File 'lib/lore/model/table_accessor.rb', line 334

def self.table_name 
  @table_name 
end

.update(&block) ⇒ Object



605
606
607
608
# File 'lib/lore/model/table_accessor.rb', line 605

def self.update(&block)
# {{{
  query_string = @update_strategy.block_update(&block)
end

Instance Method Details

#attribute_values_by_tableObject



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
# File 'lib/lore/model/table_accessor.rb', line 212

def attribute_values_by_table
  return @attribute_values if @attribute_values

  # Note that attributes might have been shadowed 
  # in @attribute_values flat, as first attribute 
  # takes precedence in casse two tables with common 
  # field name have been joined. 
  values = @attribute_values_flat 

  @attribute_values = Hash.new
  field_index = 0

  models  = [ self.class ] 
  models |= @joined_models
  models.each { |model|
    tables = model.all_table_names
    fields = model.get_fields
    tables.each { |table|
      map = {}
      fields[table].each { |field_name|
        map[field_name] = values[field_index]
        field_index += 1
      }
      @attribute_values[table] = map
    }
  }

  # 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.__filters__.output_filters

  @attribute_values.values.map { |v|
    v.each_pair { |attribute, value|
      filter = output_filters[attribute]
      value  = filter.call(value) if filter
      value
    }
  }

  @attribute_values_flat = {}
  @attribute_values.values.each { |map| @attribute_values_flat.update map }

  return @attribute_values
end

#log(message, level = :debug) ⇒ Object



45
46
47
# File 'lib/lore/model/table_accessor.rb', line 45

def log(message, level=:debug)
  @@logger.debug(message)
end