Class DataMapper::Adapters::DataObjectAdapter
In: lib/data_mapper/adapters/data_object_adapter.rb
lib/data_mapper/adapters/data_object_adapter.rb
Parent: AbstractAdapter

You must inherit from the DoAdapter, and implement the required methods to adapt a database library for use with the DataMapper.

NOTE: By inheriting from DoAdapter, you get a copy of all the standard sub-modules (Quoting, Coersion and Queries) in your own Adapter. You can extend and overwrite these copies without affecting the originals.

Methods

Included Modules

Sql Quoting Coersion Sql Quoting Coersion

Constants

FIND_OPTIONS = [ :select, :offset, :limit, :class, :include, :shallow_include, :reload, :conditions, :order, :intercept_load
TABLE_QUOTING_CHARACTER = '`'.freeze
COLUMN_QUOTING_CHARACTER = '`'.freeze
SYNTAX = { :now => 'NOW()'.freeze
MAGIC_PROPERTIES = { :updated_at => lambda { self.updated_at = Time::now }, :updated_on => lambda { self.updated_on = Date::today }, :created_at => lambda { self.created_at ||= Time::now }, :created_on => lambda { self.created_on ||= Date::today }
TYPES = { :integer => 'int'.freeze, :string => 'varchar'.freeze, :text => 'text'.freeze, :class => 'varchar'.freeze, :decimal => 'decimal'.freeze, :float => 'float'.freeze, :datetime => 'datetime'.freeze, :date => 'date'.freeze, :boolean => 'boolean'.freeze, :object => 'text'.freeze
FIND_OPTIONS = [ :select, :offset, :limit, :class, :include, :shallow_include, :reload, :conditions, :order, :intercept_load
TABLE_QUOTING_CHARACTER = '`'.freeze
COLUMN_QUOTING_CHARACTER = '`'.freeze
SYNTAX = { :now => 'NOW()'.freeze
MAGIC_PROPERTIES = { :updated_at => lambda { self.updated_at = Time::now }, :updated_on => lambda { self.updated_on = Date::today }, :created_at => lambda { self.created_at ||= Time::now }, :created_on => lambda { self.created_on ||= Date::today }
TYPES = { :integer => 'int'.freeze, :string => 'varchar'.freeze, :text => 'text'.freeze, :class => 'varchar'.freeze, :decimal => 'decimal'.freeze, :float => 'float'.freeze, :datetime => 'datetime'.freeze, :date => 'date'.freeze, :boolean => 'boolean'.freeze, :object => 'text'.freeze

Public Class methods

This callback copies and sub-classes modules and classes in the DoAdapter to the inherited class so you don‘t have to copy and paste large blocks of code from the DoAdapter.

Basically, when inheriting from the DoAdapter, you aren‘t just inheriting a single class, you‘re inheriting a whole graph of Types. For convenience.

[Source]

     # File lib/data_mapper/adapters/data_object_adapter.rb, line 439
439:       def self.inherited(base)
440: 
441:         commands = base.const_set('Commands', Module.new)
442: 
443:         Sql::Commands.constants.each do |name|
444:           commands.const_set(name, Class.new(Sql::Commands.const_get(name)))
445:         end
446: 
447:         mappings = base.const_set('Mappings', Module.new)
448: 
449:         Sql::Mappings.constants.each do |name|
450:           mappings.const_set(name, Class.new(Sql::Mappings.const_get(name)))
451:         end
452: 
453:         base.const_set('TYPES', TYPES.dup)
454:         base.const_set('FIND_OPTIONS', FIND_OPTIONS.dup)
455:         base.const_set('SYNTAX', SYNTAX.dup)
456: 
457:         super
458:       end

This callback copies and sub-classes modules and classes in the DoAdapter to the inherited class so you don‘t have to copy and paste large blocks of code from the DoAdapter.

Basically, when inheriting from the DoAdapter, you aren‘t just inheriting a single class, you‘re inheriting a whole graph of Types. For convenience.

[Source]

     # File lib/data_mapper/adapters/data_object_adapter.rb, line 439
439:       def self.inherited(base)
440: 
441:         commands = base.const_set('Commands', Module.new)
442: 
443:         Sql::Commands.constants.each do |name|
444:           commands.const_set(name, Class.new(Sql::Commands.const_get(name)))
445:         end
446: 
447:         mappings = base.const_set('Mappings', Module.new)
448: 
449:         Sql::Mappings.constants.each do |name|
450:           mappings.const_set(name, Class.new(Sql::Mappings.const_get(name)))
451:         end
452: 
453:         base.const_set('TYPES', TYPES.dup)
454:         base.const_set('FIND_OPTIONS', FIND_OPTIONS.dup)
455:         base.const_set('SYNTAX', SYNTAX.dup)
456: 
457:         super
458:       end

[Source]

    # File lib/data_mapper/adapters/data_object_adapter.rb, line 55
55:       def initialize(configuration)
56:         super
57:         @connection_pool = Support::ConnectionPool.new { create_connection }
58:       end

[Source]

    # File lib/data_mapper/adapters/data_object_adapter.rb, line 55
55:       def initialize(configuration)
56:         super
57:         @connection_pool = Support::ConnectionPool.new { create_connection }
58:       end

Public Instance methods

[Source]

    # File lib/data_mapper/adapters/data_object_adapter.rb, line 64
64:       def activate!
65:         @activated = true
66:         schema.activate!
67:       end

[Source]

    # File lib/data_mapper/adapters/data_object_adapter.rb, line 64
64:       def activate!
65:         @activated = true
66:         schema.activate!
67:       end

[Source]

    # File lib/data_mapper/adapters/data_object_adapter.rb, line 60
60:       def activated?
61:         @activated
62:       end

[Source]

    # File lib/data_mapper/adapters/data_object_adapter.rb, line 60
60:       def activated?
61:         @activated
62:       end

[Source]

    # File lib/data_mapper/adapters/data_object_adapter.rb, line 73
73:       def batch_insertable?
74:         true
75:       end

[Source]

    # File lib/data_mapper/adapters/data_object_adapter.rb, line 73
73:       def batch_insertable?
74:         true
75:       end

[Source]

     # File lib/data_mapper/adapters/data_object_adapter.rb, line 427
427:       def callback(instance, callback_name)
428:         instance.class.callbacks.execute(callback_name, instance)
429:       end

[Source]

     # File lib/data_mapper/adapters/data_object_adapter.rb, line 427
427:       def callback(instance, callback_name)
428:         instance.class.callbacks.execute(callback_name, instance)
429:       end

[Source]

     # File lib/data_mapper/adapters/data_object_adapter.rb, line 166
166:       def column_exists_for_table?(table_name, column_name)
167:         connection do |db|
168:           table = self.table(table_name)
169:           command = db.create_command(table.to_column_exists_sql)
170:           command.execute_reader(table.name, column_name, table.schema.name) do |reader|
171:             reader.any? { reader.item(1) == column_name.to_s }
172:           end
173:         end
174:       end

[Source]

     # File lib/data_mapper/adapters/data_object_adapter.rb, line 166
166:       def column_exists_for_table?(table_name, column_name)
167:         connection do |db|
168:           table = self.table(table_name)
169:           command = db.create_command(table.to_column_exists_sql)
170:           command.execute_reader(table.name, column_name, table.schema.name) do |reader|
171:             reader.any? { reader.item(1) == column_name.to_s }
172:           end
173:         end
174:       end

Yields an available connection. Flushes the connection-pool and reconnects if the connection returns an error.

[Source]

    # File lib/data_mapper/adapters/data_object_adapter.rb, line 79
79:       def connection
80:         begin
81:           # Yield the appropriate connection
82:           @connection_pool.hold { |active_connection| yield(active_connection) }
83:         rescue => execution_error
84:           # Log error on failure
85:           logger.error { execution_error }
86: 
87:           # Close all open connections, assuming that if one
88:           # had an error, it's likely due to a lost connection,
89:           # in which case all connections are likely broken.
90:           flush_connections!
91: 
92:           raise execution_error
93:         end
94:       end

Yields an available connection. Flushes the connection-pool and reconnects if the connection returns an error.

[Source]

    # File lib/data_mapper/adapters/data_object_adapter.rb, line 79
79:       def connection
80:         begin
81:           # Yield the appropriate connection
82:           @connection_pool.hold { |active_connection| yield(active_connection) }
83:         rescue => execution_error
84:           # Log error on failure
85:           logger.error { execution_error }
86: 
87:           # Close all open connections, assuming that if one
88:           # had an error, it's likely due to a lost connection,
89:           # in which case all connections are likely broken.
90:           flush_connections!
91: 
92:           raise execution_error
93:         end
94:       end

[Source]

     # File lib/data_mapper/adapters/data_object_adapter.rb, line 285
285:       def create(database_context, instance)
286:         callback(instance, :before_create)
287: 
288:         instance = update_magic_properties(database_context, instance)
289: 
290:         table = self.table(instance)
291:         attributes = instance.dirty_attributes
292: 
293:         if table.multi_class?
294:           instance.instance_variable_set(
295:             table[:type].instance_variable_name,
296:             attributes[:type] = instance.class.name
297:           )
298:         end
299: 
300:         keys = []
301:         values = []
302:         attributes.each_pair do |key, value|
303:           raise ArgumentError.new("#{value.inspect} is not a valid value for #{key.inspect}") if value.is_a?(Array)
304: 
305:           keys << table[key].to_sql
306:           values << value
307:         end
308: 
309:         sql = if keys.size > 0
310:           "INSERT INTO #{table.to_sql} (#{keys.join(', ')}) VALUES ?"
311:         else
312:           "INSERT INTO #{table.to_sql} #{self.empty_insert_sql}"
313:         end
314: 
315:         result = connection do |db|
316:           db.create_command(sql).execute_non_query(values)
317:         end
318: 
319:         if result.to_i > 0
320:           instance.instance_variable_set(:@new_record, false)
321:           instance.key = result.last_insert_row if table.key.serial? && !attributes.include?(table.key.name)
322:           database_context.identity_map.set(instance)
323:           callback(instance, :after_create)
324:           return true
325:         else
326:           return false
327:         end
328:       end

[Source]

     # File lib/data_mapper/adapters/data_object_adapter.rb, line 285
285:       def create(database_context, instance)
286:         callback(instance, :before_create)
287: 
288:         instance = update_magic_properties(database_context, instance)
289: 
290:         table = self.table(instance)
291:         attributes = instance.dirty_attributes
292: 
293:         if table.multi_class?
294:           instance.instance_variable_set(
295:             table[:type].instance_variable_name,
296:             attributes[:type] = instance.class.name
297:           )
298:         end
299: 
300:         keys = []
301:         values = []
302:         attributes.each_pair do |key, value|
303:           raise ArgumentError.new("#{value.inspect} is not a valid value for #{key.inspect}") if value.is_a?(Array)
304: 
305:           keys << table[key].to_sql
306:           values << value
307:         end
308: 
309:         sql = if keys.size > 0
310:           "INSERT INTO #{table.to_sql} (#{keys.join(', ')}) VALUES ?"
311:         else
312:           "INSERT INTO #{table.to_sql} #{self.empty_insert_sql}"
313:         end
314: 
315:         result = connection do |db|
316:           db.create_command(sql).execute_non_query(values)
317:         end
318: 
319:         if result.to_i > 0
320:           instance.instance_variable_set(:@new_record, false)
321:           instance.key = result.last_insert_row if table.key.serial? && !attributes.include?(table.key.name)
322:           database_context.identity_map.set(instance)
323:           callback(instance, :after_create)
324:           return true
325:         else
326:           return false
327:         end
328:       end

[Source]

    # File lib/data_mapper/adapters/data_object_adapter.rb, line 69
69:       def create_connection
70:         raise NotImplementedError.new
71:       end

[Source]

    # File lib/data_mapper/adapters/data_object_adapter.rb, line 69
69:       def create_connection
70:         raise NotImplementedError.new
71:       end

[Source]

     # File lib/data_mapper/adapters/data_object_adapter.rb, line 176
176:       def delete(database_context, instance)
177:         table = self.table(instance)
178: 
179:         if instance.is_a?(Class)
180:           table.delete_all!
181:         else
182:           callback(instance, :before_destroy)
183: 
184:           table.associations.each do |association|
185:             instance.send(association.name).deactivate unless association.is_a?(::DataMapper::Associations::BelongsToAssociation)
186:           end
187: 
188:           if table.paranoid?
189:             instance.instance_variable_set(table.paranoid_column.instance_variable_name, Time::now)
190:             instance.save
191:           else
192:             if connection do |db|
193:                 command = db.create_command("DELETE FROM #{table.to_sql} WHERE #{table.key.to_sql} = ?")
194:                 command.execute_non_query(instance.key).to_i > 0
195:               end # connection do...end # if continued below:
196:               instance.instance_variable_set(:@new_record, true)
197:               instance.database_context = database_context
198:               instance.original_values.clear
199:               database_context.identity_map.delete(instance)
200:               callback(instance, :after_destroy)
201:             end
202:           end
203:         end
204:       end

[Source]

     # File lib/data_mapper/adapters/data_object_adapter.rb, line 176
176:       def delete(database_context, instance)
177:         table = self.table(instance)
178: 
179:         if instance.is_a?(Class)
180:           table.delete_all!
181:         else
182:           callback(instance, :before_destroy)
183: 
184:           table.associations.each do |association|
185:             instance.send(association.name).deactivate unless association.is_a?(::DataMapper::Associations::BelongsToAssociation)
186:           end
187: 
188:           if table.paranoid?
189:             instance.instance_variable_set(table.paranoid_column.instance_variable_name, Time::now)
190:             instance.save
191:           else
192:             if connection do |db|
193:                 command = db.create_command("DELETE FROM #{table.to_sql} WHERE #{table.key.to_sql} = ?")
194:                 command.execute_non_query(instance.key).to_i > 0
195:               end # connection do...end # if continued below:
196:               instance.instance_variable_set(:@new_record, true)
197:               instance.database_context = database_context
198:               instance.original_values.clear
199:               database_context.identity_map.delete(instance)
200:               callback(instance, :after_destroy)
201:             end
202:           end
203:         end
204:       end

[Source]

     # File lib/data_mapper/adapters/data_object_adapter.rb, line 281
281:       def empty_insert_sql
282:         "DEFAULT VALUES"
283:       end

[Source]

     # File lib/data_mapper/adapters/data_object_adapter.rb, line 281
281:       def empty_insert_sql
282:         "DEFAULT VALUES"
283:       end

[Source]

     # File lib/data_mapper/adapters/data_object_adapter.rb, line 147
147:       def execute(*args)
148:         db = create_connection
149:         command = db.create_command(args.shift)
150:         return command.execute_non_query(*args)
151:       rescue => e
152:         logger.error { e }
153:         raise e
154:       ensure
155:         db.close
156:       end

[Source]

     # File lib/data_mapper/adapters/data_object_adapter.rb, line 147
147:       def execute(*args)
148:         db = create_connection
149:         command = db.create_command(args.shift)
150:         return command.execute_non_query(*args)
151:       rescue => e
152:         logger.error { e }
153:         raise e
154:       ensure
155:         db.close
156:       end

Close any open connections.

[Source]

     # File lib/data_mapper/adapters/data_object_adapter.rb, line 97
 97:       def flush_connections!          
 98:         @connection_pool.available_connections.each do |active_connection|
 99:           begin
100:             active_connection.close
101:           rescue => close_connection_error
102:             # An error on closing the connection is almost expected
103:             # if the socket is broken.
104:             logger.warn { close_connection_error }
105:           end
106:         end
107: 
108:         # Reopen fresh connections.
109:         @connection_pool.instance_variable_set('@created_count', 0)
110:         @connection_pool.available_connections.clear
111:       end

Close any open connections.

[Source]

     # File lib/data_mapper/adapters/data_object_adapter.rb, line 97
 97:       def flush_connections!          
 98:         @connection_pool.available_connections.each do |active_connection|
 99:           begin
100:             active_connection.close
101:           rescue => close_connection_error
102:             # An error on closing the connection is almost expected
103:             # if the socket is broken.
104:             logger.warn { close_connection_error }
105:           end
106:         end
107: 
108:         # Reopen fresh connections.
109:         @connection_pool.instance_variable_set('@created_count', 0)
110:         @connection_pool.available_connections.clear
111:       end

[Source]

     # File lib/data_mapper/adapters/data_object_adapter.rb, line 348
348:       def get(database_context, klass, keys)
349:         table = self.table(klass)
350:         instance_id = table.key.type_cast_value(keys.first)
351:         instance = database_context.identity_map.get(klass, instance_id)
352: 
353:         return instance if instance
354: 
355:         column_indexes = {}
356:         select_columns = []
357: 
358:         table.columns.each_with_index do |column, i|
359:           column_indexes[column] = i
360:           select_columns << column.to_sql
361:         end
362: 
363:         sql = "SELECT #{select_columns.join(', ')} FROM #{table.to_sql} WHERE #{table.keys.map { |key| "#{key.to_sql} = ?" }.join(' AND ')}"
364: 
365:         connection do |db|
366:           reader = nil
367:           begin
368:             reader = db.create_command(sql).execute_reader(*keys)
369: 
370:             if reader.has_rows?
371: 
372:               instance_type = klass
373: 
374:               if table.multi_class? && table.type_column
375:                 value = reader.item(column_indexes[table.type_column])
376:                 instance_type = table.type_column.type_cast_value(value) unless value.blank?
377:               end
378: 
379:               if instance.nil?
380:                 instance = instance_type.allocate()
381:                 instance.instance_variable_set(:@__key, instance_id)
382:                 instance.instance_variable_set(:@new_record, false)
383:                 database_context.identity_map.set(instance)
384:               elsif instance.new_record?
385:                 instance.instance_variable_set(:@__key, instance_id)
386:                 instance.instance_variable_set(:@new_record, false)
387:                 database_context.identity_map.set(instance)
388:               end
389: 
390:               instance.database_context = database_context
391: 
392:               instance_type.callbacks.execute(:before_materialize, instance)
393: 
394:               originals = instance.original_values
395: 
396:               column_indexes.each_pair do |column, i|
397:                 value = column.type_cast_value(reader.item(i))
398:                 instance.instance_variable_set(column.instance_variable_name, value)
399: 
400:                 case value
401:                   when String, Date, Time then originals[column.name] = value.dup
402:                   else originals[column.name] = value
403:                 end
404:               end
405: 
406:               instance.loaded_set = [instance]
407: 
408:               instance_type.callbacks.execute(:after_materialize, instance)
409:             end # if reader.has_rows?
410:           ensure
411:             reader.close if reader && reader.open?
412:           end
413:         end # connection
414: 
415:         return instance
416:       end

[Source]

     # File lib/data_mapper/adapters/data_object_adapter.rb, line 348
348:       def get(database_context, klass, keys)
349:         table = self.table(klass)
350:         instance_id = table.key.type_cast_value(keys.first)
351:         instance = database_context.identity_map.get(klass, instance_id)
352: 
353:         return instance if instance
354: 
355:         column_indexes = {}
356:         select_columns = []
357: 
358:         table.columns.each_with_index do |column, i|
359:           column_indexes[column] = i
360:           select_columns << column.to_sql
361:         end
362: 
363:         sql = "SELECT #{select_columns.join(', ')} FROM #{table.to_sql} WHERE #{table.keys.map { |key| "#{key.to_sql} = ?" }.join(' AND ')}"
364: 
365:         connection do |db|
366:           reader = nil
367:           begin
368:             reader = db.create_command(sql).execute_reader(*keys)
369: 
370:             if reader.has_rows?
371: 
372:               instance_type = klass
373: 
374:               if table.multi_class? && table.type_column
375:                 value = reader.item(column_indexes[table.type_column])
376:                 instance_type = table.type_column.type_cast_value(value) unless value.blank?
377:               end
378: 
379:               if instance.nil?
380:                 instance = instance_type.allocate()
381:                 instance.instance_variable_set(:@__key, instance_id)
382:                 instance.instance_variable_set(:@new_record, false)
383:                 database_context.identity_map.set(instance)
384:               elsif instance.new_record?
385:                 instance.instance_variable_set(:@__key, instance_id)
386:                 instance.instance_variable_set(:@new_record, false)
387:                 database_context.identity_map.set(instance)
388:               end
389: 
390:               instance.database_context = database_context
391: 
392:               instance_type.callbacks.execute(:before_materialize, instance)
393: 
394:               originals = instance.original_values
395: 
396:               column_indexes.each_pair do |column, i|
397:                 value = column.type_cast_value(reader.item(i))
398:                 instance.instance_variable_set(column.instance_variable_name, value)
399: 
400:                 case value
401:                   when String, Date, Time then originals[column.name] = value.dup
402:                   else originals[column.name] = value
403:                 end
404:               end
405: 
406:               instance.loaded_set = [instance]
407: 
408:               instance_type.callbacks.execute(:after_materialize, instance)
409:             end # if reader.has_rows?
410:           ensure
411:             reader.close if reader && reader.open?
412:           end
413:         end # connection
414: 
415:         return instance
416:       end

[Source]

     # File lib/data_mapper/adapters/data_object_adapter.rb, line 158
158:       def handle_error(error)
159:         raise error
160:       end

[Source]

     # File lib/data_mapper/adapters/data_object_adapter.rb, line 158
158:       def handle_error(error)
159:         raise error
160:       end

[Source]

     # File lib/data_mapper/adapters/data_object_adapter.rb, line 344
344:       def load(database_context, klass, options)
345:         self.class::Commands::LoadCommand.new(self, database_context, klass, options).call
346:       end

[Source]

     # File lib/data_mapper/adapters/data_object_adapter.rb, line 344
344:       def load(database_context, klass, options)
345:         self.class::Commands::LoadCommand.new(self, database_context, klass, options).call
346:       end

[Source]

     # File lib/data_mapper/adapters/data_object_adapter.rb, line 117
117:       def query(*args)
118:         db = create_connection
119: 
120:         command = db.create_command(args.shift)
121: 
122:         reader = command.execute_reader(*args)
123:         fields = reader.fields.map { |field| Inflector.underscore(field).to_sym }
124:         results = []
125: 
126:         if fields.size > 1
127:           struct = Struct.new(*fields)
128: 
129:           reader.each do
130:             results << struct.new(*reader.current_row)
131:           end
132:         else
133:           reader.each do
134:             results << reader.item(0)
135:           end
136:         end
137: 
138:         return results
139:       rescue => e
140:         logger.error { e }
141:         raise e
142:       ensure
143:         reader.close if reader
144:         db.close
145:       end

[Source]

     # File lib/data_mapper/adapters/data_object_adapter.rb, line 117
117:       def query(*args)
118:         db = create_connection
119: 
120:         command = db.create_command(args.shift)
121: 
122:         reader = command.execute_reader(*args)
123:         fields = reader.fields.map { |field| Inflector.underscore(field).to_sym }
124:         results = []
125: 
126:         if fields.size > 1
127:           struct = Struct.new(*fields)
128: 
129:           reader.each do
130:             results << struct.new(*reader.current_row)
131:           end
132:         else
133:           reader.each do
134:             results << reader.item(0)
135:           end
136:         end
137: 
138:         return results
139:       rescue => e
140:         logger.error { e }
141:         raise e
142:       ensure
143:         reader.close if reader
144:         db.close
145:       end

[Source]

     # File lib/data_mapper/adapters/data_object_adapter.rb, line 206
206:       def save(database_context, instance, validate = true, cleared = Set.new)
207:         case instance
208:         when Class then
209:           table(instance).create!
210:           table(instance).activate_associations!
211:         when Mappings::Table then instance.create!
212:         when DataMapper::Persistence then
213:           event = instance.new_record? ? :create : :update
214: 
215:           return false if (validate && !instance.validate_recursively(event, Set.new)) || cleared.include?(instance)
216:           cleared << instance
217: 
218:           callback(instance, :before_save)
219: 
220:           return true unless instance.new_record? || instance.dirty?
221: 
222:           result = send(event, database_context, instance)
223: 
224:           instance.database_context = database_context
225:           instance.attributes.each_pair do |name, value|
226:             instance.original_values[name] = value
227:           end
228: 
229:           instance.loaded_associations.each do |association|
230:             association.save_without_validation(database_context, cleared) if association.dirty?
231:           end
232: 
233:           callback(instance, :after_save)
234:           result
235:         end
236:       rescue => error
237:         logger.error(error)
238:         raise error
239:       end

[Source]

     # File lib/data_mapper/adapters/data_object_adapter.rb, line 206
206:       def save(database_context, instance, validate = true, cleared = Set.new)
207:         case instance
208:         when Class then
209:           table(instance).create!
210:           table(instance).activate_associations!
211:         when Mappings::Table then instance.create!
212:         when DataMapper::Persistence then
213:           event = instance.new_record? ? :create : :update
214: 
215:           return false if (validate && !instance.validate_recursively(event, Set.new)) || cleared.include?(instance)
216:           cleared << instance
217: 
218:           callback(instance, :before_save)
219: 
220:           return true unless instance.new_record? || instance.dirty?
221: 
222:           result = send(event, database_context, instance)
223: 
224:           instance.database_context = database_context
225:           instance.attributes.each_pair do |name, value|
226:             instance.original_values[name] = value
227:           end
228: 
229:           instance.loaded_associations.each do |association|
230:             association.save_without_validation(database_context, cleared) if association.dirty?
231:           end
232: 
233:           callback(instance, :after_save)
234:           result
235:         end
236:       rescue => error
237:         logger.error(error)
238:         raise error
239:       end

[Source]

     # File lib/data_mapper/adapters/data_object_adapter.rb, line 241
241:       def save_without_validation(database_context, instance, cleared = Set.new)
242:         save(database_context, instance, false, cleared)
243:       end

[Source]

     # File lib/data_mapper/adapters/data_object_adapter.rb, line 241
241:       def save_without_validation(database_context, instance, cleared = Set.new)
242:         save(database_context, instance, false, cleared)
243:       end

[Source]

     # File lib/data_mapper/adapters/data_object_adapter.rb, line 162
162:       def schema
163:         @schema || ( @schema = self.class::Mappings::Schema.new(self, @configuration.database) )
164:       end

[Source]

     # File lib/data_mapper/adapters/data_object_adapter.rb, line 162
162:       def schema
163:         @schema || ( @schema = self.class::Mappings::Schema.new(self, @configuration.database) )
164:       end

[Source]

     # File lib/data_mapper/adapters/data_object_adapter.rb, line 418
418:       def table(instance)
419:         case instance
420:         when DataMapper::Adapters::Sql::Mappings::Table then instance
421:         when DataMapper::Persistence then schema[instance.class]
422:         when Class, String then schema[instance]
423:         else raise "Don't know how to map #{instance.inspect} to a table."
424:         end
425:       end

[Source]

     # File lib/data_mapper/adapters/data_object_adapter.rb, line 418
418:       def table(instance)
419:         case instance
420:         when DataMapper::Adapters::Sql::Mappings::Table then instance
421:         when DataMapper::Persistence then schema[instance.class]
422:         when Class, String then schema[instance]
423:         else raise "Don't know how to map #{instance.inspect} to a table."
424:         end
425:       end

[Source]

     # File lib/data_mapper/adapters/data_object_adapter.rb, line 113
113:       def transaction(&block)
114:         raise NotImplementedError.new
115:       end

[Source]

     # File lib/data_mapper/adapters/data_object_adapter.rb, line 113
113:       def transaction(&block)
114:         raise NotImplementedError.new
115:       end

[Source]

     # File lib/data_mapper/adapters/data_object_adapter.rb, line 245
245:       def update(database_context, instance)
246:         callback(instance, :before_update)
247: 
248:         instance = update_magic_properties(database_context, instance)
249: 
250:         table = self.table(instance)
251:         attributes = instance.dirty_attributes
252:         parameters = []
253: 
254:         unless attributes.empty?
255:           sql = "UPDATE " << table.to_sql << " SET "
256: 
257:           sql << attributes.map do |key, value|
258:             parameters << value
259:             "#{table[key].to_sql} = ?"
260:           end.join(', ')
261: 
262:           sql << " WHERE #{table.key.to_sql} = ?"
263:           parameters << instance.key
264: 
265:           result = connection do |db|
266:             db.create_command(sql).execute_non_query(*parameters)
267:           end
268: 
269:           # BUG: do_mysql returns inaccurate affected row counts for UPDATE statements.
270:           if true || result.to_i > 0
271:             callback(instance, :after_update)
272:             return true
273:           else
274:             return false
275:           end
276:         else
277:           true
278:         end
279:       end

[Source]

     # File lib/data_mapper/adapters/data_object_adapter.rb, line 245
245:       def update(database_context, instance)
246:         callback(instance, :before_update)
247: 
248:         instance = update_magic_properties(database_context, instance)
249: 
250:         table = self.table(instance)
251:         attributes = instance.dirty_attributes
252:         parameters = []
253: 
254:         unless attributes.empty?
255:           sql = "UPDATE " << table.to_sql << " SET "
256: 
257:           sql << attributes.map do |key, value|
258:             parameters << value
259:             "#{table[key].to_sql} = ?"
260:           end.join(', ')
261: 
262:           sql << " WHERE #{table.key.to_sql} = ?"
263:           parameters << instance.key
264: 
265:           result = connection do |db|
266:             db.create_command(sql).execute_non_query(*parameters)
267:           end
268: 
269:           # BUG: do_mysql returns inaccurate affected row counts for UPDATE statements.
270:           if true || result.to_i > 0
271:             callback(instance, :after_update)
272:             return true
273:           else
274:             return false
275:           end
276:         else
277:           true
278:         end
279:       end

[Source]

     # File lib/data_mapper/adapters/data_object_adapter.rb, line 337
337:       def update_magic_properties(database_context, instance)
338:         instance.class.properties.find_all { |property| MAGIC_PROPERTIES.has_key?(property.name) }.each do |property|
339:           instance.instance_eval(&MAGIC_PROPERTIES[property.name])
340:         end
341:         instance
342:       end

[Source]

     # File lib/data_mapper/adapters/data_object_adapter.rb, line 337
337:       def update_magic_properties(database_context, instance)
338:         instance.class.properties.find_all { |property| MAGIC_PROPERTIES.has_key?(property.name) }.each do |property|
339:           instance.instance_eval(&MAGIC_PROPERTIES[property.name])
340:         end
341:         instance
342:       end

[Validate]