Module: DataMapper::Persistence

Included in:
Base
Defined in:
lib/data_mapper/persistence.rb

Overview

See DataMapper::Persistence::ClassMethods for DataMapper’s DSL documentation.

Defined Under Namespace

Modules: ClassMethods

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#loaded_setObject

This probably needs to be protected



16
17
18
# File 'lib/data_mapper/persistence.rb', line 16

def loaded_set
  @loaded_set
end

Class Method Details

.auto_migrate!Object



64
65
66
67
68
# File 'lib/data_mapper/persistence.rb', line 64

def self.auto_migrate!
  subclasses.each do |subclass|
    subclass.auto_migrate!
  end
end

.dependenciesObject



75
76
77
# File 'lib/data_mapper/persistence.rb', line 75

def self.dependencies
  @dependency_queue || (@dependency_queue = DependencyQueue.new) 
end

.included(klass) ⇒ Object



18
19
20
21
22
23
24
25
26
27
28
# File 'lib/data_mapper/persistence.rb', line 18

def self.included(klass)
  klass.extend(ClassMethods)

  klass.send(:include, Associations)
  klass.send(:include, Validations)
  klass.send(:include, CallbacksHelper)
  klass.send(:include, Support::ActiveRecordImpersonation)
  klass.send(:include, Support::Serialization)

  prepare_for_persistence(klass)
end

.prepare_for_persistence(klass) ⇒ Object



30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
# File 'lib/data_mapper/persistence.rb', line 30

def self.prepare_for_persistence(klass)
  klass.instance_variable_set('@properties', [])
  
  klass.send :extend, AutoMigrations
  klass.subclasses
  DataMapper::Persistence::subclasses << klass unless klass == DataMapper::Base
  klass.send(:undef_method, :id) if method_defined?(:id)

  return if klass == DataMapper::Base
  
  # When this class is sub-classed, copy the declared columns.
  klass.class_eval do
    def self.subclasses
      @subclasses || (@subclasses = [])
    end
    
    def self.inherited(subclass)
      super_table = database.table(self)
      
      if super_table.type_column.nil?
        super_table.add_column(:type, :class, {})
      end
      
      subclass.instance_variable_set("@callbacks", self.callbacks.dup)
      
      self::subclasses << subclass
    end
    
    def self.persistent?
      true
    end
  end
end

.subclassesObject

Track classes that include this module.



71
72
73
# File 'lib/data_mapper/persistence.rb', line 71

def self.subclasses
  @subclasses || (@subclasses = [])
end

Instance Method Details

#==(other) ⇒ Object



376
377
378
# File 'lib/data_mapper/persistence.rb', line 376

def ==(other)
  other.is_a?(self.class) && private_attributes == other.send(:private_attributes)
end

#^(other) ⇒ Object

Returns the difference between two objects, in terms of their attributes.



381
382
383
384
385
386
387
388
389
390
391
392
393
394
# File 'lib/data_mapper/persistence.rb', line 381

def ^(other)
  results = {}
  
  self_attributes, other_attributes = attributes, other.attributes
  
  self_attributes.each_pair do |k,v|
    other_value = other_attributes[k]
    unless v == other_value
      results[k] = [v, other_value]
    end
  end
  
  results      
end

#attributesObject



415
416
417
418
419
420
421
422
423
424
425
426
427
# File 'lib/data_mapper/persistence.rb', line 415

def attributes
  pairs = {}
  
  database_context.table(self).columns.each do |column|
    if self.class.public_method_defined?(column.name)
      lazy_load!(column.name) if column.lazy?
      value = instance_variable_get(column.instance_variable_name)
      pairs[column.name] = column.type == :class ? value.to_s : value
    end
  end
  
  pairs
end

#attributes=(values_hash) ⇒ Object

Mass-assign mapped fields.



346
347
348
349
350
351
352
353
354
355
356
357
358
# File 'lib/data_mapper/persistence.rb', line 346

def attributes=(values_hash)
  table = database_context.table(self.class)
  
  values_hash.delete_if do |key, value|
    !self.class.public_method_defined?("#{key}=")
  end.each_pair do |key, value|
    if respond_to?(key)
      send("#{key}=", value)
    elsif column = table[key]
      instance_variable_set(column.instance_variable_name, value)          
    end
  end
end

#database_contextObject



360
361
362
# File 'lib/data_mapper/persistence.rb', line 360

def database_context
  @database_context || ( @database_context = database )
end

#database_context=(value) ⇒ Object



364
365
366
# File 'lib/data_mapper/persistence.rb', line 364

def database_context=(value)
  @database_context = value
end

#dirty?Boolean

Returns:

  • (Boolean)


441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
# File 'lib/data_mapper/persistence.rb', line 441

def dirty?
  result = database_context.table(self).columns.any? do |column|
    if column.type == :object
      Marshal.dump(self.instance_variable_get(column.instance_variable_name)) != original_values[column.name]
    else
      self.instance_variable_get(column.instance_variable_name) != original_values[column.name]
    end
  end
  
  return true if result
  
  loaded_associations.any? do |loaded_association|
    loaded_association.dirty?
  end
end

#dirty_attributesObject



457
458
459
460
461
462
463
464
465
466
467
468
# File 'lib/data_mapper/persistence.rb', line 457

def dirty_attributes
  pairs = {}
  
  database_context.table(self).columns.each do |column|
    value = instance_variable_get(column.instance_variable_name)
    if value != original_values[column.name] && (!new_record? || !column.serial?)
      pairs[column.name] = column.type != :object ? value : YAML.dump(value)
    end
  end
  
  pairs
end

#initialize(details = nil) ⇒ Object



79
80
81
82
83
84
85
86
# File 'lib/data_mapper/persistence.rb', line 79

def initialize(details = nil)
  case details
  when Hash then self.attributes = details
  when details.respond_to?(:persistent?) then self.unsafe_attributes = details.attributes
  when Struct then self.unsafe_attributes = details.attributes
  when NilClass then nil
  end
end

#inspectObject



493
494
495
496
497
498
499
500
501
502
503
# File 'lib/data_mapper/persistence.rb', line 493

def inspect
  inspected_attributes = attributes.map { |k,v| "@#{k}=#{v.inspect}" }
  
  instance_variables.each do |name|
    if instance_variable_get(name).kind_of?(Associations::HasManyAssociation)
      inspected_attributes << "#{name}=#{instance_variable_get(name).inspect}"
    end
  end
  
  "#<%s:0x%x @new_record=%s, %s>" % [self.class.name, (object_id * 2), new_record?, inspected_attributes.join(', ')]
end

#keyObject



515
516
517
518
519
520
# File 'lib/data_mapper/persistence.rb', line 515

def key
  @__key || @__key = begin
    key_column = database_context.table(self.class).key
    key_column.type_cast_value(instance_variable_get(key_column.instance_variable_name))
  end
end

#key=(value) ⇒ Object



509
510
511
512
513
# File 'lib/data_mapper/persistence.rb', line 509

def key=(value)
  key_column = database_context.table(self.class).key
  @__key = key_column.type_cast_value(value)
  instance_variable_set(key_column.instance_variable_name, @__key)
end

#lazy_load!(*names) ⇒ Object

Lazy-loads the attributes for a loaded_set, then overwrites the accessors for the named methods so that the lazy_loading is skipped the second time.



315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
# File 'lib/data_mapper/persistence.rb', line 315

def lazy_load!(*names)
  
  names = names.map { |name| name.to_sym }.reject { |name| lazy_loaded_attributes.include?(name) }
  
  reset_attribute = lambda do |instance|
    singleton_class = (class << instance; self end)
    names.each do |name|
      instance.lazy_loaded_attributes << name
      singleton_class.send(:attr_accessor, name)
    end
  end
  
  unless names.empty? || new_record? || loaded_set.nil?
    
    key = database_context.table(self.class).key.to_sym
    keys_to_select = loaded_set.map do |instance|
      instance.send(key)
    end
    
    database_context.all(
      self.class,
      :select => ([key] + names),
      :reload => true,
      key => keys_to_select
    ).each(&reset_attribute)
  else
    reset_attribute[self]
  end
end

#lazy_loaded_attributesObject



396
397
398
# File 'lib/data_mapper/persistence.rb', line 396

def lazy_loaded_attributes
  @lazy_loaded_attributes || @lazy_loaded_attributes = Set.new
end

#loaded_associationsObject



505
506
507
# File 'lib/data_mapper/persistence.rb', line 505

def loaded_associations
  @loaded_associations || @loaded_associations = []
end

#loaded_attributesObject



400
401
402
403
404
405
406
407
408
# File 'lib/data_mapper/persistence.rb', line 400

def loaded_attributes
  pairs = {}
  
  database_context.table(self).columns.each do |column|
    pairs[column.name] = instance_variable_get(column.instance_variable_name)
  end
  
  pairs
end

#loggerObject



368
369
370
# File 'lib/data_mapper/persistence.rb', line 368

def logger
  self.class.logger
end

#new_record?Boolean

Returns:

  • (Boolean)


372
373
374
# File 'lib/data_mapper/persistence.rb', line 372

def new_record?
  @new_record.nil? || @new_record
end

#original_valuesObject



480
481
482
483
484
485
486
# File 'lib/data_mapper/persistence.rb', line 480

def original_values
  class << self
    attr_reader :original_values
  end
  
  @original_values = {}
end

#original_values=(values) ⇒ Object



470
471
472
473
474
475
476
477
478
# File 'lib/data_mapper/persistence.rb', line 470

def original_values=(values)
  values.each_pair do |k,v|
    original_values[k] = case v
      when String, Date, Time then v.dup
      # when column.type == :object then Marshal.dump(v)
      else v
    end
  end
end

#unsafe_attributes=(values_hash) ⇒ Object



429
430
431
432
433
434
435
436
437
438
439
# File 'lib/data_mapper/persistence.rb', line 429

def unsafe_attributes=(values_hash)
  table = database_context.table(self.class)
  
  values_hash.each_pair do |key, value|
    if respond_to?(key)
      send("#{key}=", value)
    elsif column = table[key]
      instance_variable_set(column.instance_variable_name, value)          
    end
  end
end

#update_attributes(update_hash) ⇒ Object



410
411
412
413
# File 'lib/data_mapper/persistence.rb', line 410

def update_attributes(update_hash)
  self.attributes = update_hash
  self.save
end